Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
83c8a8a
Add macos run using only the `trio` spawner
goodboy Oct 26, 2022
aee86f2
Run macos job on `uv` and newer `actions@v4`
goodboy Feb 25, 2026
2631fb4
Only run CI on <py3.14
goodboy Feb 25, 2026
86489cc
Use py version in job `name`, consider macos in linux matrix?
goodboy Feb 26, 2026
c5af2fa
Add a `@no_macos` skipif deco
goodboy Feb 25, 2026
706a4b7
Add 6sec timeout around `test_simple_rpc` suite for macos
goodboy Feb 25, 2026
86c9553
Loosen shml test assert for key shortening on macos
goodboy Mar 1, 2026
b7546fd
Longer timeout for `test_one_end_stream_not_opened`
goodboy Mar 2, 2026
82d02ef
Lul, never use `'uds'` tpt for macos test-scripts
goodboy Mar 2, 2026
7b89204
Tweak `do_ctlc()`'s `delay` default
goodboy Mar 2, 2026
51701fc
Ok just skip `test_shield_pause` for macos..
goodboy Mar 2, 2026
b30faac
Adjust debugger test suites for macos
goodboy Mar 2, 2026
e8f3d64
Increase prompt timeout for macos in CI
goodboy Mar 2, 2026
a1ea373
Ok.. try a longer prompt timeout?
goodboy Mar 2, 2026
9c1bcb2
Skip legacy-one-way suites on non-linux in CI
goodboy Mar 2, 2026
94dfeb1
Add delay before root-actor open, macos in CI..
goodboy Mar 2, 2026
fb73935
Add a `test_log` fixture for emitting from *within* test bodies or fi…
goodboy Mar 2, 2026
0e2949e
Bump docs-exs subproc timeout, exception log any timeouts
goodboy Mar 2, 2026
a72bb93
Bleh, bump timeout again for docs-exs suite when in CI
goodboy Mar 2, 2026
ab6c955
Lol fine! bump it a bit more XD
goodboy Mar 2, 2026
98a7d69
Always pre-sleep in `daemon` fixture when in non-linux CI..
goodboy Mar 2, 2026
4639685
Fill out types in `test_discovery` mod
goodboy Mar 2, 2026
776af3f
Register our `ctlcs_bish` marker to avoid warnings
goodboy Mar 2, 2026
5b2905b
Xplatform tweaks for `daemon` fixture
goodboy Mar 3, 2026
79396b4
2x the ctl-c loop prompt-timeout for non-linux in CI
goodboy Mar 3, 2026
712c009
Hike `testdir.spawn()` timeout on non-linux in CI
goodboy Mar 4, 2026
016306a
Allow `ctlcs_bish(<condition-args>)` skipping
goodboy Mar 4, 2026
bbc028e
Increase macos job timeout to 16s
goodboy Mar 9, 2026
b71e857
Skip a couple more `ctlc` flaking suites
goodboy Mar 4, 2026
fb94aa0
Tidy a typing-typo, add explicit `ids=` for paramed suites
goodboy Mar 9, 2026
d135ce9
Restyle `test_legacy_one_way_streaming` mod
goodboy Mar 9, 2026
f9bdb1b
Try one more timeout bumps for flaky docs streaming ex..
goodboy Mar 6, 2026
afd66ce
Final try, drop logging level in streaming example to see if macos ca…
goodboy Mar 6, 2026
9c4cd86
OK-FINE, skip streaming docs example on macos!
goodboy Mar 6, 2026
6ee0149
Another cancellation test timeout bump for non-linux
goodboy Mar 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,28 @@ jobs:


testing-linux:
name: '${{ matrix.os }} Python ${{ matrix.python }} - ${{ matrix.spawn_backend }}'
name: '${{ matrix.os }} Python${{ matrix.python-version }} - spawn_backend=${{ matrix.spawn_backend }}'
timeout-minutes: 10
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ['3.13']
os: [
ubuntu-latest,
# macos-latest, # ?TODO, better?
]
python-version: [
'3.13',
# '3.14',
]
spawn_backend: [
'trio',
# 'mp_spawn',
# 'mp_forkserver',
]

steps:

- uses: actions/checkout@v4

- name: 'Install uv + py-${{ matrix.python-version }}'
Expand Down Expand Up @@ -120,6 +125,42 @@ jobs:
- name: Run tests
run: uv run pytest tests/ --spawn-backend=${{ matrix.spawn_backend }} -rsx

testing-macos:
name: '${{ matrix.os }} Python${{ matrix.python-version }} - spawn_backend=${{ matrix.spawn_backend }}'
timeout-minutes: 16
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [
macos-latest,
]
python-version: [
'3.13',
# '3.14',
]
spawn_backend: [
'trio',
]

steps:
- uses: actions/checkout@v4

- name: 'Install uv + py-${{ matrix.python-version }}'
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install the project w uv
run: uv sync --all-extras --dev

- name: List deps tree
run: uv tree

- name: Run tests w uv
run: uv run pytest tests/ --spawn-backend=${{ matrix.spawn_backend }} -rsx

# XXX legacy NOTE XXX
#
# We skip 3.10 on windows for now due to not having any collabs to
Expand Down
16 changes: 15 additions & 1 deletion examples/debugging/shield_hang_in_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

'''
import os
import platform
import signal

import trio
Expand Down Expand Up @@ -31,13 +32,26 @@ async def main(
from_test: bool = False,
) -> None:

if platform.system() != 'Darwin':
tpt = 'uds'
else:
# XXX, precisely we can't use pytest's tmp-path generation
# for tests.. apparently because:
#
# > The OSError: AF_UNIX path too long in macOS Python occurs
# > because the path to the Unix domain socket exceeds the
# > operating system's maximum path length limit (around 104
#
# WHICH IS just, wtf hillarious XD
tpt = 'tcp'

async with (
tractor.open_nursery(
debug_mode=True,
enable_stack_on_sig=True,
# maybe_enable_greenback=False,
loglevel='devx',
enable_transports=['uds'],
enable_transports=[tpt],
) as an,
):
ptl: tractor.Portal = await an.start_actor(
Expand Down
17 changes: 16 additions & 1 deletion examples/debugging/subactor_bp_in_ctx.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import platform

import tractor
import trio

Expand Down Expand Up @@ -34,9 +36,22 @@ async def just_bp(

async def main():

if platform.system() != 'Darwin':
tpt = 'uds'
else:
# XXX, precisely we can't use pytest's tmp-path generation
# for tests.. apparently because:
#
# > The OSError: AF_UNIX path too long in macOS Python occurs
# > because the path to the Unix domain socket exceeds the
# > operating system's maximum path length limit (around 104
#
# WHICH IS just, wtf hillarious XD
tpt = 'tcp'

async with tractor.open_nursery(
debug_mode=True,
enable_transports=['uds'],
enable_transports=[tpt],
loglevel='devx',
) as n:
p = await n.start_actor(
Expand Down
8 changes: 5 additions & 3 deletions examples/full_fledged_streaming_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def main() -> list[int]:
# yes, a nursery which spawns `trio`-"actors" B)
an: ActorNursery
async with tractor.open_nursery(
loglevel='cancel',
loglevel='error',
# debug_mode=True,
) as an:

Expand Down Expand Up @@ -118,8 +118,10 @@ async def main() -> list[int]:
cancelled: bool = await portal.cancel_actor()
assert cancelled

print(f"STREAM TIME = {time.time() - start}")
print(f"STREAM + SPAWN TIME = {time.time() - pre_start}")
print(
f"STREAM TIME = {time.time() - start}\n"
f"STREAM + SPAWN TIME = {time.time() - pre_start}\n"
)
assert result_stream == list(range(seed))
return result_stream

Expand Down
86 changes: 76 additions & 10 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import time

import pytest
import tractor
from tractor._testing import (
examples_dir as examples_dir,
tractor_test as tractor_test,
Expand All @@ -22,6 +23,7 @@
'tractor._testing.pytest',
]

_non_linux: bool = platform.system() != 'Linux'

# Sending signal.SIGINT on subprocess fails on windows. Use CTRL_* alternatives
if platform.system() == 'Windows':
Expand All @@ -44,6 +46,10 @@
platform.system() == "Windows",
reason="Test is unsupported on windows",
)
no_macos = pytest.mark.skipif(
platform.system() == "Darwin",
reason="Test is unsupported on MacOS",
)


def pytest_addoption(
Expand All @@ -61,19 +67,54 @@ def pytest_addoption(


@pytest.fixture(scope='session', autouse=True)
def loglevel(request):
def loglevel(request) -> str:
import tractor
orig = tractor.log._default_loglevel
level = tractor.log._default_loglevel = request.config.option.loglevel
log = tractor.log.get_console_log(
level=level,
name='tractor', # <- enable root logger
)
log.info(f'Test-harness logging level: {level}\n')
log.info(
f'Test-harness set runtime loglevel: {level!r}\n'
)
yield level
tractor.log._default_loglevel = orig


@pytest.fixture(scope='function')
def test_log(
request,
loglevel: str,
) -> tractor.log.StackLevelAdapter:
'''
Deliver a per test-module-fn logger instance for reporting from
within actual test bodies/fixtures.

For example this can be handy to report certain error cases from
exception handlers using `test_log.exception()`.

'''
modname: str = request.function.__module__
log = tractor.log.get_logger(
name=modname, # <- enable root logger
# pkg_name='tests',
)
_log = tractor.log.get_console_log(
level=loglevel,
logger=log,
name=modname,
# pkg_name='tests',
)
_log.debug(
f'In-test-logging requested\n'
f'test_log.name: {log.name!r}\n'
f'level: {loglevel!r}\n'

)
yield _log


_ci_env: bool = os.environ.get('CI', False)


Expand Down Expand Up @@ -110,6 +151,7 @@ def daemon(
testdir: pytest.Pytester,
reg_addr: tuple[str, int],
tpt_proto: str,
ci_env: bool,

) -> subprocess.Popen:
'''
Expand Down Expand Up @@ -147,13 +189,25 @@ def daemon(
**kwargs,
)

# TODO! we should poll for the registry socket-bind to take place
# and only once that's done yield to the requester!
# -[ ] TCP: use the `._root.open_root_actor()`::`ping_tpt_socket()`
# closure!
# -[ ] UDS: can we do something similar for 'pinging" the
# file-socket?
#
global _PROC_SPAWN_WAIT
# UDS sockets are **really** fast to bind()/listen()/connect()
# so it's often required that we delay a bit more starting
# the first actor-tree..
if tpt_proto == 'uds':
global _PROC_SPAWN_WAIT
_PROC_SPAWN_WAIT = 0.6

if _non_linux and ci_env:
_PROC_SPAWN_WAIT += 1

# XXX, allow time for the sub-py-proc to boot up.
# !TODO, see ping-polling ideas above!
time.sleep(_PROC_SPAWN_WAIT)

assert not proc.returncode
Expand All @@ -163,18 +217,30 @@ def daemon(
# XXX! yeah.. just be reaaal careful with this bc sometimes it
# can lock up on the `_io.BufferedReader` and hang..
stderr: str = proc.stderr.read().decode()
if stderr:
stdout: str = proc.stdout.read().decode()
if (
stderr
or
stdout
):
print(
f'Daemon actor tree produced STDERR:\n'
f'Daemon actor tree produced output:\n'
f'{proc.args}\n'
f'\n'
f'{stderr}\n'
f'stderr: {stderr!r}\n'
f'stdout: {stdout!r}\n'
)
if proc.returncode != -2:
raise RuntimeError(
'Daemon actor tree failed !?\n'
f'{proc.args}\n'

if (rc := proc.returncode) != -2:
msg: str = (
f'Daemon actor tree was not cancelled !?\n'
f'proc.args: {proc.args!r}\n'
f'proc.returncode: {rc!r}\n'
)
if rc < 0:
raise RuntimeError(msg)

log.error(msg)


# @pytest.fixture(autouse=True)
Expand Down
Loading