Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
414a8c5
IPC ring bug impl with async read
Mar 12, 2025
9921ea3
General improvements
Mar 13, 2025
eceb292
move tractor._ipc.py into tractor.ipc._chan.py
Mar 13, 2025
8e3f581
Move tractor._shm to tractor.ipc._shm
Mar 13, 2025
af69272
Move linux specifics from tractor.ipc._shm into tractor.ipc._linux
Mar 14, 2025
566a11c
Move RingBuffSender|Receiver to its own tractor.ipc._ringbuf module
Mar 14, 2025
881813e
Add module headers and fix spacing on tractor._ipc._linux
Mar 14, 2025
2dd3a68
Handle cancelation on EventFD.read
Mar 14, 2025
1ed0c86
Address some of fomo\'s comments
Mar 14, 2025
84d25b5
Make ring buf api use pickle-able RBToken
Mar 14, 2025
26fef82
Add buf_size to RBToken and add sender cancel test, move disable_mant…
Mar 14, 2025
6f1f198
Break out transport protocol and tcp specifics into their own submodu…
Mar 16, 2025
c7d5b02
Starting to make `.ipc.Channel` work with multiple MsgTransports
Mar 22, 2025
5e2d456
Add root and random addr getters on MsgTransport type
Mar 22, 2025
0be9f5f
Finally switch to using address protocol in all runtime
Mar 23, 2025
f67e19a
Trying to make full suite pass with uds
Mar 23, 2025
568fb18
Rework/simplify transport addressing
goodboy Mar 30, 2025
63fac5a
Implement peer-info tracking for UDS streams
goodboy Mar 31, 2025
2540d1f
Adjust imports to use new `UnwrappedAddress`
goodboy Mar 31, 2025
bbae2c9
Allocate bind-addrs in subactors
goodboy Mar 31, 2025
7b3324b
Add a big boi `Channel.pformat()/__repr__()`
goodboy Mar 31, 2025
abdaf7b
Slight typing and multi-line styling tweaks in `.ipc` sugpkg
goodboy Mar 31, 2025
a6fefcc
Adjust lowlevel-tb hiding logic for `MsgStream`
goodboy Mar 31, 2025
8c0d961
Add `bidict` pkg as dep since used in `._addr` for now
goodboy Mar 31, 2025
a504d92
Adjust `._child` instantiation of `Actor` to use newly named `uuid` arg
goodboy Mar 31, 2025
b4ce618
Bit of multi-line styling for `LocalPortal`
goodboy Mar 31, 2025
44c9da1
Emphasize internal error block header-comment a bit
goodboy Mar 31, 2025
31196b9
Handle broken-pipes from `MsgpackTransport.send()`
goodboy Apr 1, 2025
7a3c9d0
Even more `tractor._addr.Address` simplifying
goodboy Apr 2, 2025
1c85338
Add a `MsgpackTransport.pformat()`
goodboy Apr 2, 2025
7d1512e
Add an `Actor.pformat()`
goodboy Apr 2, 2025
81bf810
Factor `breakpoint()` blocking into `@acm`
goodboy Apr 2, 2025
078e507
Add `psutil` to `--dev` / testing deps
goodboy Apr 2, 2025
acac605
Move `DebugRequestError` to `._exceptions`
goodboy Apr 3, 2025
ad211f8
More `._addr` boxing refinements
goodboy Apr 3, 2025
f15bbb3
UDS: translate file dne to connection-error
goodboy Apr 3, 2025
3cc835c
Mv `Actor._do_handshake()` to `Channel`, add `.aid`
goodboy Apr 3, 2025
412c66d
Mv to `Channel._do_handshake()` in `open_portal()`
goodboy Apr 3, 2025
0fcbedd
Change some low-hanging `.uid`s to `.aid`
goodboy Apr 3, 2025
d6d0112
Some more log message tweaks
goodboy Apr 3, 2025
708ce4a
Repair weird spawn test, start `test_root_runtime`
goodboy Apr 3, 2025
d9aee98
Add `Arbiter.is_registry()` in prep for proper `.discovery._registry`
goodboy Apr 3, 2025
be1d8bf
s/`._addr.preferred_transport`/`_state._def_tpt_proto`
goodboy Apr 4, 2025
bedde07
Unwrap `UDSAddress` as `tuple[str, str]`, i.e. sin pid
goodboy Apr 4, 2025
00d8a2a
Improve `TransportClosed.__repr__()`, add `src_exc`
goodboy Apr 6, 2025
ba45c03
Skip the ringbuf test mod for now since data-gen is a bit "heavy/lagg…
goodboy Apr 6, 2025
0944477
Add API-modernize-todo on `experimental._pubsub.fan_out_to_ctxs`
goodboy Apr 6, 2025
61df10b
Move concrete `Address`es to each tpt module
goodboy Apr 7, 2025
98c4614
Factor actor-embedded IPC-tpt-server to `ipc` subsys
goodboy Apr 10, 2025
79d0c17
Add `TransportClosed.from_src_exc()`
goodboy Apr 11, 2025
a7d4bcd
Absorb `TransportClosed` in `Portal.cancel_actor()`
goodboy Apr 11, 2025
52b5efd
Another `tn` eg-loosify inside `ActorNursery.cancel()`..
goodboy Apr 11, 2025
56ef4cb
Add `_state.current_ipc_protos()`
goodboy Apr 11, 2025
01d6f11
Use `current_ipc_protos()` as the `enable_transports`-default-when-`N…
goodboy Apr 11, 2025
0477a62
Never hide non-[msgtype/tpt-closed] error tbs in `Channel.send()`
goodboy Apr 11, 2025
0711576
Passthrough `_pause()` kwargs from `_maybe_enter_pm()`
goodboy Apr 11, 2025
26fedec
Mv `Actor._stream_handler()` to `.ipc._server` func
goodboy Apr 11, 2025
f67b063
Move peer-tracking attrs from `Actor` -> `IPCServer`
goodboy Apr 11, 2025
7533e93
Log listener bind status for TCP as for UDS
goodboy Jun 11, 2025
8538a9c
Decouple actor-state from low-level ipc-server
goodboy Jun 11, 2025
1f3cef5
Fix now invalid `Actor._peers` ref..
goodboy Jul 10, 2025
9c0de24
Be explicit with `SpawnSpec` processing in subs
goodboy May 13, 2025
a331f6d
Return `Path` from `_get_mod_abspath()` helper fn
goodboy May 15, 2025
ae2687b
Bump lock file for new 3.13 wheels/schema
goodboy Jun 12, 2025
6d2f4d1
Detail the docs on `Context._maybe_raise_remote_err()`
goodboy Jun 13, 2025
05df634
Use `Channel.aid: Aid` throughout `.ipc._server`
goodboy Jun 16, 2025
28e32b8
Use `enable_transports: list[str]` parameter
goodboy Jun 17, 2025
27e6ad1
Mk `.ipc._tcp.TCPAddress` validate with `ipaddress`
goodboy Jul 8, 2025
c0eef3b
Bump GH CI to use `uv` throughout!
goodboy Jul 13, 2025
cbfb0d0
Don't use `uv sync --locked` for now
goodboy Jul 13, 2025
309360d
Add latest `typing-extension`, needed by `stackscope`
goodboy Jul 13, 2025
c2e7dc7
Avoid silent `stackscope`-test fail due to dep
goodboy May 15, 2025
161884f
Adjust back `.devx._debug` import
goodboy Jul 13, 2025
ad9833a
Update actions badge links in readme
goodboy Jul 13, 2025
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
119 changes: 78 additions & 41 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,70 @@ on:
workflow_dispatch:

jobs:

mypy:
name: 'MyPy'
# ------ sdist ------
# test that we can generate a software distribution and install it
# thus avoid missing file issues after packaging.
#
# -[x] produce sdist with uv
# ------ - ------
sdist-linux:
name: 'sdist'
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Setup python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install latest uv
uses: astral-sh/setup-uv@v6

- name: Install dependencies
run: pip install -U . --upgrade-strategy eager -r requirements-test.txt
- name: Build sdist as tar.gz
run: uv build --sdist --python=3.13

- name: Run MyPy check
run: mypy tractor/ --ignore-missing-imports --show-traceback
- name: Install sdist from .tar.gz
run: python -m pip install dist/*.tar.gz

# test that we can generate a software distribution and install it
# thus avoid missing file issues after packaging.
sdist-linux:
name: 'sdist'
runs-on: ubuntu-latest
# ------ type-check ------
# mypy:
# name: 'MyPy'
# runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2
# steps:
# - name: Checkout
# uses: actions/checkout@v4

- name: Setup python
uses: actions/setup-python@v2
with:
python-version: '3.11'
# - name: Install latest uv
# uses: astral-sh/setup-uv@v6

# # faster due to server caching?
# # https://docs.astral.sh/uv/guides/integration/github/#setting-up-python
# - name: "Set up Python"
# uses: actions/setup-python@v6
# with:
# python-version-file: "pyproject.toml"

# # w uv
# # - name: Set up Python
# # run: uv python install

# - name: Setup uv venv
# run: uv venv .venv --python=3.13

- name: Build sdist
run: python setup.py sdist --formats=zip
# - name: Install
# run: uv sync --dev

- name: Install sdist from .zips
run: python -m pip install dist/*.zip
# # TODO, ty cmd over repo
# # - name: type check with ty
# # run: ty ./tractor/

# # - uses: actions/cache@v3
# # name: Cache uv virtenv as default .venv
# # with:
# # path: ./.venv
# # key: venv-${{ hashFiles('uv.lock') }}

# - name: Run MyPy check
# run: mypy tractor/ --ignore-missing-imports --show-traceback


testing-linux:
Expand All @@ -59,32 +83,45 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
python: ['3.11']
python-version: ['3.13']
spawn_backend: [
'trio',
'mp_spawn',
'mp_forkserver',
# 'mp_spawn',
# 'mp_forkserver',
]

steps:

- name: Checkout
uses: actions/checkout@v2
- uses: actions/checkout@v4

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

# GH way.. faster?
# - name: setup-python@v6
# uses: actions/setup-python@v6
# with:
# python-version: '${{ matrix.python-version }}'

# consider caching for speedups?
# https://docs.astral.sh/uv/guides/integration/github/#caching

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

- name: Install dependencies
run: pip install -U . -r requirements-test.txt -r requirements-docs.txt --upgrade-strategy eager
# - name: Install dependencies
# run: pip install -U . -r requirements-test.txt -r requirements-docs.txt --upgrade-strategy eager

- name: List dependencies
run: pip list
- name: List deps tree
run: uv tree

- name: Run tests
run: pytest tests/ --spawn-backend=${{ matrix.spawn_backend }} -rsx
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
# debug the CI failures. Anyone wanting to hack and solve them is very
# welcome, but our primary user base is not using that OS.
Expand Down
19 changes: 19 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{ pkgs ? import <nixpkgs> {} }:
let
nativeBuildInputs = with pkgs; [
stdenv.cc.cc.lib
uv
];

in
pkgs.mkShell {
inherit nativeBuildInputs;

LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath nativeBuildInputs;
TMPDIR = "/tmp";

shellHook = ''
set -e
uv venv .venv --python=3.12
'';
}
8 changes: 5 additions & 3 deletions docs/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -689,9 +689,11 @@ channel`_!
.. _msgspec: https://jcristharif.com/msgspec/
.. _guest: https://trio.readthedocs.io/en/stable/reference-lowlevel.html?highlight=guest%20mode#using-guest-mode-to-run-trio-on-top-of-other-event-loops


.. |gh_actions| image:: https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fgoodboy%2Ftractor%2Fbadge&style=popout-square
:target: https://actions-badge.atrox.dev/goodboy/tractor/goto
..
NOTE, on generating badge links from the UI
https://docs.github.com/en/actions/how-tos/monitoring-and-troubleshooting-workflows/monitoring-workflows/adding-a-workflow-status-badge?ref=gitguardian-blog-automated-secrets-detection#using-the-ui
.. |gh_actions| image:: https://github.com/goodboy/tractor/actions/workflows/ci.yml/badge.svg?branch=main
:target: https://github.com/goodboy/tractor/actions/workflows/ci.yml

.. |docs| image:: https://readthedocs.org/projects/tractor/badge/?version=latest
:target: https://tractor.readthedocs.io/en/latest/?badge=latest
Expand Down
6 changes: 6 additions & 0 deletions examples/debugging/restore_builtin_breakpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
import trio
import tractor

# ensure mod-path is correct!
from tractor.devx._debug import (
_sync_pause_from_builtin as _sync_pause_from_builtin,
)


async def main() -> None:

Expand All @@ -13,6 +18,7 @@ async def main() -> None:

async with tractor.open_nursery(
debug_mode=True,
loglevel='devx',
) as an:
assert an
assert (
Expand Down
2 changes: 1 addition & 1 deletion examples/service_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async def main(service_name):
async with tractor.open_nursery() as an:
await an.start_actor(service_name)

async with tractor.get_registry('127.0.0.1', 1616) as portal:
async with tractor.get_registry() as portal:
print(f"Arbiter is listening on {portal.channel}")

async with tractor.wait_for_actor(service_name) as sockaddr:
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ dependencies = [
"pdbp>=1.6,<2", # windows only (from `pdbp`)
# typed IPC msging
"msgspec>=0.19.0",
"cffi>=1.17.1",
"bidict>=0.23.1",
]

# ------ project ------
Expand All @@ -59,9 +61,12 @@ dev = [
# `tractor.devx` tooling
"greenback>=1.2.1,<2",
"stackscope>=0.2.2,<0.3",
# ^ requires this?
"typing-extensions>=4.14.1",
"pyperclip>=1.9.0",
"prompt-toolkit>=3.0.50",
"xonsh>=0.19.2",
"psutil>=7.0.0",
]
# TODO, add these with sane versions; were originally in
# `requirements-docs.txt`..
Expand Down
6 changes: 3 additions & 3 deletions tests/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async def test_reg_then_unreg(reg_addr):
portal = await n.start_actor('actor', enable_modules=[__name__])
uid = portal.channel.uid

async with tractor.get_registry(*reg_addr) as aportal:
async with tractor.get_registry(reg_addr) as aportal:
# this local actor should be the arbiter
assert actor is aportal.actor

Expand Down Expand Up @@ -160,7 +160,7 @@ async def spawn_and_check_registry(
async with tractor.open_root_actor(
registry_addrs=[reg_addr],
):
async with tractor.get_registry(*reg_addr) as portal:
async with tractor.get_registry(reg_addr) as portal:
# runtime needs to be up to call this
actor = tractor.current_actor()

Expand Down Expand Up @@ -300,7 +300,7 @@ async def close_chans_before_nursery(
async with tractor.open_root_actor(
registry_addrs=[reg_addr],
):
async with tractor.get_registry(*reg_addr) as aportal:
async with tractor.get_registry(reg_addr) as aportal:
try:
get_reg = partial(unpack_reg, aportal)

Expand Down
15 changes: 11 additions & 4 deletions tests/test_docs_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ def run(script_code):
# due to backpressure!!!
proc = testdir.popen(
cmdargs,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
**kwargs,
)
assert not proc.returncode
Expand Down Expand Up @@ -119,10 +122,14 @@ def test_example(
code = ex.read()

with run_example_in_subproc(code) as proc:
proc.wait()
err, _ = proc.stderr.read(), proc.stdout.read()
# print(f'STDERR: {err}')
# print(f'STDOUT: {out}')
err = None
try:
if not proc.poll():
_, err = proc.communicate(timeout=15)

except subprocess.TimeoutExpired as e:
proc.kill()
err = e.stderr

# if we get some gnarly output let's aggregate and raise
if err:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_inter_peer_cancellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ async def serve_subactors(
)
await ipc.send((
peer.chan.uid,
peer.chan.raddr,
peer.chan.raddr.unwrap(),
))

print('Spawner exiting spawn serve loop!')
Expand Down
2 changes: 1 addition & 1 deletion tests/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async def test_self_is_registered_localportal(reg_addr):
"Verify waiting on the arbiter to register itself using a local portal."
actor = tractor.current_actor()
assert actor.is_arbiter
async with tractor.get_registry(*reg_addr) as portal:
async with tractor.get_registry(reg_addr) as portal:
assert isinstance(portal, tractor._portal.LocalPortal)

with trio.fail_after(0.2):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_multi_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_abort_on_sigint(daemon):
@tractor_test
async def test_cancel_remote_arbiter(daemon, reg_addr):
assert not tractor.current_actor().is_arbiter
async with tractor.get_registry(*reg_addr) as portal:
async with tractor.get_registry(reg_addr) as portal:
await portal.cancel_actor()

time.sleep(0.1)
Expand All @@ -41,7 +41,7 @@ async def test_cancel_remote_arbiter(daemon, reg_addr):

# no arbiter socket should exist
with pytest.raises(OSError):
async with tractor.get_registry(*reg_addr) as portal:
async with tractor.get_registry(reg_addr) as portal:
pass


Expand Down
Loading