Compare commits
4 Commits
532a9834f3
...
fc5e80fea5
| Author | SHA1 | Date |
|---|---|---|
|
|
fc5e80fea5 | |
|
|
b7115fc875 | |
|
|
208e7c0926 | |
|
|
22cdf15b73 |
|
|
@ -148,9 +148,13 @@ jobs:
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: >
|
run: >
|
||||||
uv run
|
uv run
|
||||||
pytest tests/ -rsx
|
pytest
|
||||||
|
tests/
|
||||||
|
-rsx
|
||||||
--spawn-backend=${{ matrix.spawn_backend }}
|
--spawn-backend=${{ matrix.spawn_backend }}
|
||||||
--tpt-proto=${{ matrix.tpt_proto }}
|
--tpt-proto=${{ matrix.tpt_proto }}
|
||||||
|
--capture=fd
|
||||||
|
# ^XXX^ can't work with --spawn-method=main_thread_forkserver
|
||||||
|
|
||||||
# XXX legacy NOTE XXX
|
# XXX legacy NOTE XXX
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ dev = [
|
||||||
{include-group = 'devx'},
|
{include-group = 'devx'},
|
||||||
{include-group = 'testing'},
|
{include-group = 'testing'},
|
||||||
{include-group = 'repl'},
|
{include-group = 'repl'},
|
||||||
|
{include-group = 'sync_pause'},
|
||||||
]
|
]
|
||||||
devx = [
|
devx = [
|
||||||
# `tractor.devx` tooling
|
# `tractor.devx` tooling
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
'''
|
'''
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import platform
|
import platform
|
||||||
|
import os
|
||||||
import signal
|
import signal
|
||||||
import time
|
import time
|
||||||
from typing import (
|
from typing import (
|
||||||
|
|
@ -56,6 +57,7 @@ type PexpectSpawner = Callable[
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def spawn(
|
def spawn(
|
||||||
start_method: str,
|
start_method: str,
|
||||||
|
loglevel: str,
|
||||||
testdir: pytest.Pytester,
|
testdir: pytest.Pytester,
|
||||||
reg_addr: tuple[str, int],
|
reg_addr: tuple[str, int],
|
||||||
|
|
||||||
|
|
@ -67,11 +69,12 @@ def spawn(
|
||||||
'''
|
'''
|
||||||
supported_spawners: set[str] = {
|
supported_spawners: set[str] = {
|
||||||
'trio',
|
'trio',
|
||||||
# ?TODO, other spawners that will work?
|
# `examples/debugging/<script>.py` picks up the spawn
|
||||||
# - [ ] need to pass `start_method={spawner}` to underlying
|
# backend via the `TRACTOR_SPAWN_METHOD` env-var which
|
||||||
# `examples/debugging/<script>.py` somehow?
|
# is honored inside `tractor._root.open_root_actor()`,
|
||||||
# 'main_thread_forkserver',
|
# so no per-script edits are required.
|
||||||
# 'subint_forkserver',
|
'main_thread_forkserver',
|
||||||
|
'subint_forkserver',
|
||||||
}
|
}
|
||||||
if start_method not in supported_spawners:
|
if start_method not in supported_spawners:
|
||||||
pytest.skip(
|
pytest.skip(
|
||||||
|
|
@ -88,12 +91,35 @@ def spawn(
|
||||||
https://docs.python.org/3/using/cmdline.html#using-on-controlling-color
|
https://docs.python.org/3/using/cmdline.html#using-on-controlling-color
|
||||||
|
|
||||||
'''
|
'''
|
||||||
import os
|
|
||||||
# disable colored tbs
|
# disable colored tbs
|
||||||
os.environ['PYTHON_COLORS'] = '0'
|
os.environ['PYTHON_COLORS'] = '0'
|
||||||
# disable all ANSI color output
|
# disable all ANSI color output
|
||||||
# os.environ['NO_COLOR'] = '1'
|
# os.environ['NO_COLOR'] = '1'
|
||||||
|
|
||||||
|
def set_spawn_method():
|
||||||
|
'''
|
||||||
|
Drive the actor-spawn backend inside the spawned
|
||||||
|
`examples/debugging/<script>.py` subproc via env-var
|
||||||
|
(consumed by `tractor._root.open_root_actor()`),
|
||||||
|
without requiring per-script CLI plumbing.
|
||||||
|
|
||||||
|
'''
|
||||||
|
os.environ['TRACTOR_SPAWN_METHOD'] = start_method
|
||||||
|
|
||||||
|
def set_loglevel():
|
||||||
|
'''
|
||||||
|
Forward the test-suite parametrized `loglevel` into the
|
||||||
|
spawned `examples/debugging/<script>.py` subproc via
|
||||||
|
env-var (consumed by `tractor._root.open_root_actor()`),
|
||||||
|
so console verbosity can be cranked or silenced from
|
||||||
|
the test harness without per-script edits.
|
||||||
|
|
||||||
|
'''
|
||||||
|
if loglevel:
|
||||||
|
os.environ['TRACTOR_LOGLEVEL'] = loglevel
|
||||||
|
else:
|
||||||
|
os.environ.pop('TRACTOR_LOGLEVEL', None)
|
||||||
|
|
||||||
spawned: PexpectSpawner|None = None
|
spawned: PexpectSpawner|None = None
|
||||||
|
|
||||||
def _spawn(
|
def _spawn(
|
||||||
|
|
@ -103,6 +129,8 @@ def spawn(
|
||||||
) -> pty_spawn.spawn:
|
) -> pty_spawn.spawn:
|
||||||
nonlocal spawned
|
nonlocal spawned
|
||||||
unset_colors()
|
unset_colors()
|
||||||
|
set_spawn_method()
|
||||||
|
set_loglevel()
|
||||||
spawned = testdir.spawn(
|
spawned = testdir.spawn(
|
||||||
cmd=mk_cmd(
|
cmd=mk_cmd(
|
||||||
cmd,
|
cmd,
|
||||||
|
|
@ -146,6 +174,14 @@ def spawn(
|
||||||
if ptyproc.isalive():
|
if ptyproc.isalive():
|
||||||
ptyproc.kill(signal.SIGKILL)
|
ptyproc.kill(signal.SIGKILL)
|
||||||
|
|
||||||
|
# Scope our env-var mutations to this single fixture invocation
|
||||||
|
# — both `TRACTOR_SPAWN_METHOD` and `TRACTOR_LOGLEVEL` are
|
||||||
|
# honored by `tractor._root.open_root_actor()` so leaking them
|
||||||
|
# past this test could inadvertently re-route a later in-process
|
||||||
|
# tractor test's spawn-backend / loglevel.
|
||||||
|
os.environ.pop('TRACTOR_SPAWN_METHOD', None)
|
||||||
|
os.environ.pop('TRACTOR_LOGLEVEL', None)
|
||||||
|
|
||||||
# TODO? ensure we've cleaned up any UDS-paths?
|
# TODO? ensure we've cleaned up any UDS-paths?
|
||||||
# breakpoint()
|
# breakpoint()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -841,7 +841,7 @@ def test_multi_nested_subactors_error_through_nurseries(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.timeout(15)
|
# @pytest.mark.timeout(15)
|
||||||
@has_nested_actors
|
@has_nested_actors
|
||||||
def test_root_nursery_cancels_before_child_releases_tty_lock(
|
def test_root_nursery_cancels_before_child_releases_tty_lock(
|
||||||
spawn,
|
spawn,
|
||||||
|
|
|
||||||
|
|
@ -535,13 +535,13 @@ async def kill_transport(
|
||||||
# At timeout the plugin hard-kills the pytest process — that's
|
# At timeout the plugin hard-kills the pytest process — that's
|
||||||
# the intended behavior here; the alternative is an unattended
|
# the intended behavior here; the alternative is an unattended
|
||||||
# suite run that never returns.
|
# suite run that never returns.
|
||||||
@pytest.mark.timeout(
|
# @pytest.mark.timeout(
|
||||||
30,
|
# 30,
|
||||||
# NOTE should be a 2.1s happy path.
|
# # NOTE should be a 2.1s happy path.
|
||||||
# XXX for `main_thread_forkserver` this is SUPER SENSITIVE
|
# # XXX for `main_thread_forkserver` this is SUPER SENSITIVE
|
||||||
# so keep it higher to avoid flaky runs..
|
# # so keep it higher to avoid flaky runs..
|
||||||
method='thread',
|
# method='thread',
|
||||||
)
|
# )
|
||||||
@pytest.mark.skipon_spawn_backend(
|
@pytest.mark.skipon_spawn_backend(
|
||||||
'subint',
|
'subint',
|
||||||
# 'main_thread_forkserver',
|
# 'main_thread_forkserver',
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ async def run_fork_in_non_trio_thread(
|
||||||
# `subint_sigint_starvation_issue.md`. Each test also has an
|
# `subint_sigint_starvation_issue.md`. Each test also has an
|
||||||
# inner `trio.fail_after()` so assertion failures fire fast
|
# inner `trio.fail_after()` so assertion failures fire fast
|
||||||
# under normal conditions.
|
# under normal conditions.
|
||||||
@pytest.mark.timeout(30, method='thread')
|
# @pytest.mark.timeout(30, method='thread')
|
||||||
def test_fork_from_worker_thread_via_trio(
|
def test_fork_from_worker_thread_via_trio(
|
||||||
) -> None:
|
) -> None:
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
|
|
@ -179,10 +179,10 @@ def test_subint_happy_teardown(
|
||||||
# `subint_sigint_starvation_issue.md` GIL-starvation flavor,
|
# `subint_sigint_starvation_issue.md` GIL-starvation flavor,
|
||||||
# so `method='thread'` keeps us safe in case ordering or
|
# so `method='thread'` keeps us safe in case ordering or
|
||||||
# load shifts the failure mode.
|
# load shifts the failure mode.
|
||||||
@pytest.mark.timeout(
|
# @pytest.mark.timeout(
|
||||||
3, # NOTE never passes pre-3.14+ subints support.
|
# 3, # NOTE never passes pre-3.14+ subints support.
|
||||||
method='thread',
|
# method='thread',
|
||||||
)
|
# )
|
||||||
def test_subint_non_checkpointing_child(
|
def test_subint_non_checkpointing_child(
|
||||||
reg_addr: tuple[str, int|str],
|
reg_addr: tuple[str, int|str],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
||||||
|
|
@ -430,10 +430,10 @@ async def inf_streamer(
|
||||||
print('streamer exited .open_streamer() block')
|
print('streamer exited .open_streamer() block')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.timeout(
|
# @pytest.mark.timeout(
|
||||||
6,
|
# 6,
|
||||||
method='signal',
|
# method='signal',
|
||||||
)
|
# )
|
||||||
def test_local_task_fanout_from_stream(
|
def test_local_task_fanout_from_stream(
|
||||||
reg_addr: tuple,
|
reg_addr: tuple,
|
||||||
debug_mode: bool,
|
debug_mode: bool,
|
||||||
|
|
|
||||||
|
|
@ -458,10 +458,10 @@ async def spawn_and_error(
|
||||||
# `test_nested_multierrors`. See
|
# `test_nested_multierrors`. See
|
||||||
# `ai/conc-anal/subint_forkserver_test_cancellation_leak_issue.md`
|
# `ai/conc-anal/subint_forkserver_test_cancellation_leak_issue.md`
|
||||||
# / #449 for the post-mortem.
|
# / #449 for the post-mortem.
|
||||||
@pytest.mark.timeout(
|
# @pytest.mark.timeout(
|
||||||
10,
|
# 10,
|
||||||
method='thread',
|
# method='thread',
|
||||||
)
|
# )
|
||||||
@tractor_test
|
@tractor_test
|
||||||
async def test_nested_multierrors(
|
async def test_nested_multierrors(
|
||||||
reg_addr: tuple,
|
reg_addr: tuple,
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,7 @@ async def open_root_actor(
|
||||||
f'_registry_addrs: {registry_addrs!r}\n'
|
f'_registry_addrs: {registry_addrs!r}\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# debug.mk_pdb().set_trace()
|
||||||
async with maybe_block_bp(
|
async with maybe_block_bp(
|
||||||
debug_mode=debug_mode,
|
debug_mode=debug_mode,
|
||||||
maybe_enable_greenback=maybe_enable_greenback,
|
maybe_enable_greenback=maybe_enable_greenback,
|
||||||
|
|
@ -284,6 +285,75 @@ async def open_root_actor(
|
||||||
)
|
)
|
||||||
enable_modules.extend(rpc_module_paths)
|
enable_modules.extend(rpc_module_paths)
|
||||||
|
|
||||||
|
# `TRACTOR_LOGLEVEL` env-var wins over any caller-passed
|
||||||
|
# `loglevel` so devs/test-runs can crank (or silence)
|
||||||
|
# console verbosity without touching application code.
|
||||||
|
env_ll_report: str = ''
|
||||||
|
if env_ll := os.environ.get('TRACTOR_LOGLEVEL'):
|
||||||
|
loglevel = env_ll
|
||||||
|
env_ll_report: str = (
|
||||||
|
f'Detected env-var setting,\n'
|
||||||
|
f'TRACTOR_LOGLEVEL={env_ll!r}\n'
|
||||||
|
f'\n'
|
||||||
|
f'Setting console loglevel per,\n'
|
||||||
|
f'loglevel={loglevel!r}\n'
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
loglevel
|
||||||
|
and
|
||||||
|
loglevel.upper() != env_ll.upper()
|
||||||
|
):
|
||||||
|
env_ll_report += (
|
||||||
|
f'\n'
|
||||||
|
f'NOTE env-var OVERRIDES caller-passed,\n'
|
||||||
|
f'loglevel={loglevel!r}\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
loglevel: str = (
|
||||||
|
loglevel
|
||||||
|
or
|
||||||
|
log._default_loglevel
|
||||||
|
)
|
||||||
|
loglevel: str = loglevel.upper()
|
||||||
|
|
||||||
|
assert loglevel
|
||||||
|
_log = log.get_console_log(
|
||||||
|
level=loglevel,
|
||||||
|
name='tractor',
|
||||||
|
logger=logger,
|
||||||
|
)
|
||||||
|
assert _log
|
||||||
|
if env_ll_report:
|
||||||
|
_log.info(env_ll_report)
|
||||||
|
|
||||||
|
# `TRACTOR_SPAWN_METHOD` env-var wins over any caller-passed
|
||||||
|
# `start_method` so devs/test-runs can swap the actor spawn
|
||||||
|
# backend without touching application code (e.g. driving
|
||||||
|
# the `examples/debugging/<script>.py` suite under each
|
||||||
|
# backend from `tests/devx/conftest.py::spawn`).
|
||||||
|
if env_sm := os.environ.get('TRACTOR_SPAWN_METHOD'):
|
||||||
|
start_method: str = env_sm
|
||||||
|
env_sm_report: str = (
|
||||||
|
f'Detected env-var setting,\n'
|
||||||
|
f'TRACTOR_SPAWN_METHOD={env_sm!r}\n'
|
||||||
|
f'\n'
|
||||||
|
f'Setting spawn backend as,\n'
|
||||||
|
f'start_method={env_sm!r}\n'
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
start_method
|
||||||
|
and
|
||||||
|
start_method != env_sm
|
||||||
|
):
|
||||||
|
_log.warning(
|
||||||
|
env_sm_report
|
||||||
|
+
|
||||||
|
f'NOTE env-var OVERRIDES caller-passed,\n'
|
||||||
|
f'`start_method={start_method!r}`\n'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_log.info(env_sm_report)
|
||||||
|
|
||||||
if start_method is not None:
|
if start_method is not None:
|
||||||
_spawn.try_set_start_method(start_method)
|
_spawn.try_set_start_method(start_method)
|
||||||
|
|
||||||
|
|
@ -300,12 +370,6 @@ async def open_root_actor(
|
||||||
wrap_address(uw_addr)
|
wrap_address(uw_addr)
|
||||||
for uw_addr in uw_reg_addrs
|
for uw_addr in uw_reg_addrs
|
||||||
]
|
]
|
||||||
loglevel: str = (
|
|
||||||
loglevel
|
|
||||||
or
|
|
||||||
log._default_loglevel
|
|
||||||
)
|
|
||||||
loglevel: str = loglevel.upper()
|
|
||||||
|
|
||||||
# Debug-mode is currently only supported for backends whose
|
# Debug-mode is currently only supported for backends whose
|
||||||
# subactor root runtime is trio-native (so `tractor.devx.
|
# subactor root runtime is trio-native (so `tractor.devx.
|
||||||
|
|
@ -341,13 +405,6 @@ async def open_root_actor(
|
||||||
f'{_spawn._spawn_method!r}.'
|
f'{_spawn._spawn_method!r}.'
|
||||||
)
|
)
|
||||||
|
|
||||||
assert loglevel
|
|
||||||
_log = log.get_console_log(
|
|
||||||
level=loglevel,
|
|
||||||
name='tractor',
|
|
||||||
)
|
|
||||||
assert _log
|
|
||||||
|
|
||||||
# TODO: factor this into `.devx._stackscope`!!
|
# TODO: factor this into `.devx._stackscope`!!
|
||||||
if (
|
if (
|
||||||
debug_mode
|
debug_mode
|
||||||
|
|
|
||||||
|
|
@ -346,7 +346,6 @@ from __future__ import annotations
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import sys
|
|
||||||
import threading
|
import threading
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import (
|
from typing import (
|
||||||
|
|
@ -370,7 +369,6 @@ from ._spawn import (
|
||||||
cancel_on_completion,
|
cancel_on_completion,
|
||||||
soft_kill,
|
soft_kill,
|
||||||
)
|
)
|
||||||
from ._subint import _has_subints
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from tractor.discovery._addr import UnwrappedAddress
|
from tractor.discovery._addr import UnwrappedAddress
|
||||||
|
|
@ -832,13 +830,6 @@ async def main_thread_forkserver_proc(
|
||||||
thread instead of `trio.lowlevel.open_process()`.
|
thread instead of `trio.lowlevel.open_process()`.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if not _has_subints:
|
|
||||||
raise RuntimeError(
|
|
||||||
f'The {"main_thread_forkserver"!r} spawn backend '
|
|
||||||
f'requires Python 3.14+.\n'
|
|
||||||
f'Current runtime: {sys.version}'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Backend-scoped config pulled from `proc_kwargs`. Using
|
# Backend-scoped config pulled from `proc_kwargs`. Using
|
||||||
# `proc_kwargs` (vs a first-class kwarg on this function)
|
# `proc_kwargs` (vs a first-class kwarg on this function)
|
||||||
# matches how other backends expose per-spawn tuning
|
# matches how other backends expose per-spawn tuning
|
||||||
|
|
|
||||||
|
|
@ -135,13 +135,15 @@ def try_set_start_method(
|
||||||
case 'mp_spawn':
|
case 'mp_spawn':
|
||||||
_ctx = mp.get_context('spawn')
|
_ctx = mp.get_context('spawn')
|
||||||
|
|
||||||
case 'trio':
|
case (
|
||||||
|
'trio'
|
||||||
|
| 'main_thread_forkserver'
|
||||||
|
):
|
||||||
_ctx = None
|
_ctx = None
|
||||||
|
|
||||||
case (
|
case (
|
||||||
'subint'
|
'subint'
|
||||||
| 'subint_fork'
|
| 'subint_fork'
|
||||||
| 'main_thread_forkserver'
|
|
||||||
| 'subint_forkserver'
|
| 'subint_forkserver'
|
||||||
):
|
):
|
||||||
# All subint-family backends need no `mp.context`;
|
# All subint-family backends need no `mp.context`;
|
||||||
|
|
|
||||||
68
uv.lock
68
uv.lock
|
|
@ -682,6 +682,7 @@ dependencies = [
|
||||||
|
|
||||||
[package.dev-dependencies]
|
[package.dev-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
|
{ name = "greenback", marker = "python_full_version < '3.14'" },
|
||||||
{ name = "pexpect" },
|
{ name = "pexpect" },
|
||||||
{ name = "prompt-toolkit" },
|
{ name = "prompt-toolkit" },
|
||||||
{ name = "psutil" },
|
{ name = "psutil" },
|
||||||
|
|
@ -736,6 +737,7 @@ requires-dist = [
|
||||||
|
|
||||||
[package.metadata.requires-dev]
|
[package.metadata.requires-dev]
|
||||||
dev = [
|
dev = [
|
||||||
|
{ name = "greenback", marker = "python_full_version == '3.13.*'", specifier = ">=1.2.1,<2" },
|
||||||
{ name = "pexpect", specifier = ">=4.9.0,<5" },
|
{ name = "pexpect", specifier = ">=4.9.0,<5" },
|
||||||
{ name = "prompt-toolkit", specifier = ">=3.0.50" },
|
{ name = "prompt-toolkit", specifier = ">=3.0.50" },
|
||||||
{ name = "psutil", specifier = ">=7.0.0" },
|
{ name = "psutil", specifier = ">=7.0.0" },
|
||||||
|
|
@ -744,7 +746,7 @@ dev = [
|
||||||
{ name = "pytest-timeout", specifier = ">=2.3" },
|
{ name = "pytest-timeout", specifier = ">=2.3" },
|
||||||
{ name = "stackscope", specifier = ">=0.2.2,<0.3" },
|
{ name = "stackscope", specifier = ">=0.2.2,<0.3" },
|
||||||
{ name = "typing-extensions", specifier = ">=4.14.1" },
|
{ name = "typing-extensions", specifier = ">=4.14.1" },
|
||||||
{ name = "xonsh", editable = "../xonsh" },
|
{ name = "xonsh", specifier = ">=0.23.0" },
|
||||||
]
|
]
|
||||||
devx = [
|
devx = [
|
||||||
{ name = "stackscope", specifier = ">=0.2.2,<0.3" },
|
{ name = "stackscope", specifier = ">=0.2.2,<0.3" },
|
||||||
|
|
@ -756,7 +758,7 @@ repl = [
|
||||||
{ name = "prompt-toolkit", specifier = ">=3.0.50" },
|
{ name = "prompt-toolkit", specifier = ">=3.0.50" },
|
||||||
{ name = "psutil", specifier = ">=7.0.0" },
|
{ name = "psutil", specifier = ">=7.0.0" },
|
||||||
{ name = "pyperclip", specifier = ">=1.9.0" },
|
{ name = "pyperclip", specifier = ">=1.9.0" },
|
||||||
{ name = "xonsh", editable = "../xonsh" },
|
{ name = "xonsh", specifier = ">=0.23.0" },
|
||||||
]
|
]
|
||||||
subints = [{ name = "msgspec", marker = "python_full_version >= '3.14'", specifier = ">=0.21.0" }]
|
subints = [{ name = "msgspec", marker = "python_full_version >= '3.14'", specifier = ">=0.21.0" }]
|
||||||
sync-pause = [{ name = "greenback", marker = "python_full_version == '3.13.*'", specifier = ">=1.2.1,<2" }]
|
sync-pause = [{ name = "greenback", marker = "python_full_version == '3.13.*'", specifier = ">=1.2.1,<2" }]
|
||||||
|
|
@ -870,61 +872,15 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xonsh"
|
name = "xonsh"
|
||||||
source = { editable = "../xonsh" }
|
version = "0.23.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
[package.metadata]
|
sdist = { url = "https://files.pythonhosted.org/packages/60/e5/2dfa99e21a8118bed0e73ed50e91962fdad01b900e23497064e8810b03b5/xonsh-0.23.2.tar.gz", hash = "sha256:633608c8292938af0f242f05326cc2912f25fa72bd808824ab0534a6df304402", size = 1030659, upload-time = "2026-04-26T19:28:40.744Z" }
|
||||||
requires-dist = [
|
wheels = [
|
||||||
{ name = "click", marker = "extra == 'full'" },
|
{ url = "https://files.pythonhosted.org/packages/53/0d/bf7869dd57b40888ea1da8fc88f70d8e94ec2f8ee236ea4c22a757593235/xonsh-0.23.2-py311-none-any.whl", hash = "sha256:a38dd84e23e97fc42e0156c80024b3449474dfcbb6c3a344bd38c45a2b2de44d", size = 756215, upload-time = "2026-04-26T19:28:38.875Z" },
|
||||||
{ name = "coverage", marker = "extra == 'test'", specifier = ">=5.3.1" },
|
{ url = "https://files.pythonhosted.org/packages/f7/9f/b1bb0c15bf2120469c94b062f4b854588370ab94c7a1679c84ff646bf50b/xonsh-0.23.2-py312-none-any.whl", hash = "sha256:190a348fa19774de8e697af5f44c9adb95aca687fa475b31dda23d1a3462a3c6", size = 756224, upload-time = "2026-04-26T19:28:39.17Z" },
|
||||||
{ name = "distro", marker = "sys_platform == 'linux' and extra == 'full'" },
|
{ url = "https://files.pythonhosted.org/packages/83/23/8e037579ac86d8f266b4116338f902eab04175b88574a6438ee739dd3084/xonsh-0.23.2-py313-none-any.whl", hash = "sha256:4ebbf42a94f505d25694f154556ca0caa149a3f59870ec850bd13ad8df519dce", size = 756728, upload-time = "2026-04-26T19:28:39.493Z" },
|
||||||
{ name = "distro", marker = "extra == 'linux'" },
|
{ url = "https://files.pythonhosted.org/packages/05/ec/090300d9c5f14f58b5a684302f43535457f733a62f11673aa3ac38460717/xonsh-0.23.2-py314-none-any.whl", hash = "sha256:5efcd0f6db8f9f1dace256de2c04c3c044f2d86b48434187c43a69d602283a9e", size = 756767, upload-time = "2026-04-26T19:28:37.218Z" },
|
||||||
{ name = "furo", marker = "extra == 'doc'" },
|
|
||||||
{ name = "gnureadline", marker = "sys_platform == 'darwin' and extra == 'full'" },
|
|
||||||
{ name = "gnureadline", marker = "extra == 'mac'" },
|
|
||||||
{ name = "matplotlib", marker = "extra == 'doc'" },
|
|
||||||
{ name = "myst-parser", marker = "extra == 'doc'" },
|
|
||||||
{ name = "numpydoc", marker = "extra == 'doc'" },
|
|
||||||
{ name = "pre-commit", marker = "extra == 'dev'" },
|
|
||||||
{ name = "prompt-toolkit", marker = "extra == 'bestshell'", specifier = ">=3.0.29" },
|
|
||||||
{ name = "prompt-toolkit", marker = "extra == 'ptk'", specifier = ">=3.0.29" },
|
|
||||||
{ name = "prompt-toolkit", marker = "extra == 'test'", specifier = ">=3.0.29" },
|
|
||||||
{ name = "psutil", marker = "extra == 'doc'" },
|
|
||||||
{ name = "pygments", marker = "extra == 'bestshell'", specifier = ">=2.2" },
|
|
||||||
{ name = "pygments", marker = "extra == 'pygments'", specifier = ">=2.2" },
|
|
||||||
{ name = "pygments", marker = "extra == 'test'", specifier = ">=2.2" },
|
|
||||||
{ name = "pyperclip", marker = "extra == 'ptk'" },
|
|
||||||
{ name = "pyte", marker = "extra == 'test'", specifier = ">=0.8.0" },
|
|
||||||
{ name = "pytest", marker = "extra == 'test'", specifier = ">=7" },
|
|
||||||
{ name = "pytest-cov", marker = "extra == 'test'" },
|
|
||||||
{ name = "pytest-mock", marker = "extra == 'test'" },
|
|
||||||
{ name = "pytest-rerunfailures", marker = "extra == 'test'" },
|
|
||||||
{ name = "pytest-subprocess", marker = "extra == 'test'" },
|
|
||||||
{ name = "pytest-timeout", marker = "extra == 'test'" },
|
|
||||||
{ name = "pyzmq", marker = "extra == 'doc'" },
|
|
||||||
{ name = "re-ver", marker = "extra == 'dev'" },
|
|
||||||
{ name = "requests", marker = "extra == 'test'" },
|
|
||||||
{ name = "restructuredtext-lint", marker = "extra == 'test'" },
|
|
||||||
{ name = "runthis-sphinxext", marker = "extra == 'doc'" },
|
|
||||||
{ name = "setproctitle", marker = "sys_platform == 'win32' and extra == 'full'" },
|
|
||||||
{ name = "setproctitle", marker = "extra == 'proctitle'" },
|
|
||||||
{ name = "sphinx", marker = "extra == 'doc'", specifier = ">=3.1" },
|
|
||||||
{ name = "sphinx-autobuild", marker = "extra == 'doc'" },
|
|
||||||
{ name = "sphinx-prompt", marker = "extra == 'doc'" },
|
|
||||||
{ name = "sphinx-reredirects", marker = "extra == 'doc'" },
|
|
||||||
{ name = "sphinx-sitemap", marker = "extra == 'doc'" },
|
|
||||||
{ name = "tomli", marker = "extra == 'dev'" },
|
|
||||||
{ name = "tornado", marker = "extra == 'doc'" },
|
|
||||||
{ name = "ujson", marker = "extra == 'full'" },
|
|
||||||
{ name = "virtualenv", marker = "extra == 'test'", specifier = ">=20.16.2" },
|
|
||||||
{ name = "xonsh", extras = ["bestshell"], marker = "extra == 'doc'" },
|
|
||||||
{ name = "xonsh", extras = ["bestshell"], marker = "extra == 'test'" },
|
|
||||||
{ name = "xonsh", extras = ["doc", "test"], marker = "extra == 'dev'" },
|
|
||||||
{ name = "xonsh", extras = ["ptk", "pygments"], marker = "extra == 'full'" },
|
|
||||||
]
|
]
|
||||||
provides-extras = ["ptk", "pygments", "mac", "linux", "proctitle", "full", "bestshell", "test", "dev", "doc"]
|
|
||||||
|
|
||||||
[package.metadata.requires-dev]
|
|
||||||
dev = [{ name = "xonsh", extras = ["dev"] }]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zipp"
|
name = "zipp"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue