From 0c22f7d5f3b5f5dd9d9d99a973fa3d9f55bcda6d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:24:20 +0000 Subject: [PATCH 1/8] chore: switch project tooling to ty --- .github/workflows/lint-test.yaml | 4 +- .gitignore | 5 - .pre-commit-config.yaml | 11 +- AGENTS.md | 2 +- CONTRIBUTING.md | 9 +- Makefile | 3 +- README.md | 2 +- .../plugboard_schemas/__init__.py | 2 +- .../plugboard_schemas/_validator_registry.py | 2 +- plugboard-schemas/pyproject.toml | 8 - plugboard/__init__.py | 2 +- plugboard/component/component.py | 4 +- plugboard/component/utils.py | 21 +- plugboard/connector/asyncio_channel.py | 6 +- plugboard/connector/ray_channel.py | 8 +- plugboard/events/event_handlers.py | 3 +- plugboard/library/llm.py | 4 +- plugboard/library/sql_io.py | 27 +-- plugboard/state/state_backend.py | 6 +- plugboard/utils/logging.py | 4 +- plugboard/utils/ray.py | 6 +- pyproject.toml | 23 ++- tests/integration/test_component_decorator.py | 7 +- tests/integration/test_job_id_wiring.py | 6 +- tests/integration/test_tuner.py | 9 +- tests/unit/test_llm.py | 1 + tests/unit/test_schemas.py | 6 +- uv.lock | 181 +++--------------- 28 files changed, 139 insertions(+), 233 deletions(-) diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml index ea9291bc4..2411f1523 100644 --- a/.github/workflows/lint-test.yaml +++ b/.github/workflows/lint-test.yaml @@ -52,9 +52,7 @@ jobs: - name: Type checking run: | - uv run mypy plugboard/ --explicit-package-bases - uv run mypy plugboard-schemas/plugboard_schemas/ --explicit-package-bases - uv run mypy tests/ + uv run ty check plugboard/ plugboard-schemas/plugboard_schemas/ tests/ if: always() - name: Code complexity diff --git a/.gitignore b/.gitignore index 2407baa44..9107d2280 100644 --- a/.gitignore +++ b/.gitignore @@ -146,11 +146,6 @@ venv.bak/ # mkdocs documentation /site -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - # Pyre type checker .pyre/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7b6323346..19fc07c54 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,15 +11,10 @@ repos: args: [ --fix ] # Run the formatter. - id: ruff-format -- repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.15.0 +- repo: https://github.com/astral-sh/ty + rev: 0.0.61 hooks: - - id: mypy - additional_dependencies: - - types-PyYAML - - types-requests - - pydantic - - msgspec[yaml] + - id: ty - repo: https://github.com/rubik/xenon rev: v0.9.3 hooks: diff --git a/AGENTS.md b/AGENTS.md index 2bb5af985..cfc7f6e9d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -53,7 +53,7 @@ Plugboard is an event-driven framework in Python for simulating and orchestratin - You can delegate to the `lint` agent in `.github/agents` to resolve linting issues. - **Tools**: - `ruff` - Formatting and linting. - - `mypy` - Static type checking. + - `ty` - Static type checking. - **Commands**: - `make lint` - Check for issues. - `make format` - Auto-format code. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bab13f862..3257e35d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,11 +28,18 @@ uv run pytest . ### Linting -We use [ruff](https://github.com/astral-sh/ruff) for code formatting and style. Install the pre-commit hook by running +We use [ruff](https://github.com/astral-sh/ruff) for code formatting and style, and +[ty](https://github.com/astral-sh/ty) for static type checking. Install the pre-commit hook by +running ```sh uv run pre-commit install ``` +You can run the full local lint suite with +```sh +make lint +``` + ### Documentation The package documentation uses [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) and can be viewed locally by running diff --git a/Makefile b/Makefile index 408230690..f4e11d373 100644 --- a/Makefile +++ b/Makefile @@ -35,8 +35,7 @@ init: $(VENV)/__makefile_stamps_init lint: init uv run ruff check uv run ruff format --check - uv run mypy $(SRC)/ --explicit-package-bases - uv run mypy $(TESTS)/ + uv run ty check $(SRC)/ ./plugboard-schemas/plugboard_schemas/ $(TESTS)/ .PHONY: test test: init diff --git a/README.md b/README.md index 1d08a70bc..8e43f4129 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Some examples of what you can build with Plugboard include: - **YAML model specification** format for saving model definitions, allowing you to run the same model locally or in cloud infrastructure; - A **command line interface** for executing models; - Built to handle the **data intensive simulation** requirements of industrial process applications; -- Modern implementation with **Python 3.12+** based around **asyncio** with complete type annotation coverage; +- Modern implementation with **Python 3.12+** based around **asyncio** with complete type annotation coverage checked with **ty**; - Built-in integrations for **loading/saving data** from cloud storage and SQL databases; - Built-in **LLM integrations** for building AI-augmented process models with support for multiple providers; - **Detailed logging** of component inputs, outputs and state for monitoring and process mining or surrogate modelling use-cases. diff --git a/plugboard-schemas/plugboard_schemas/__init__.py b/plugboard-schemas/plugboard_schemas/__init__.py index b578491e9..5928a087c 100644 --- a/plugboard-schemas/plugboard_schemas/__init__.py +++ b/plugboard-schemas/plugboard_schemas/__init__.py @@ -53,7 +53,7 @@ ) -__version__ = version(__package__) +__version__ = version("plugboard-schemas") __all__ = [ diff --git a/plugboard-schemas/plugboard_schemas/_validator_registry.py b/plugboard-schemas/plugboard_schemas/_validator_registry.py index 9738993a9..a94b83573 100644 --- a/plugboard-schemas/plugboard_schemas/_validator_registry.py +++ b/plugboard-schemas/plugboard_schemas/_validator_registry.py @@ -46,7 +46,7 @@ def __len__(self) -> int: return len(self._validators) def __repr__(self) -> str: - names = [fn.__name__ for fn in self._validators] + names = [getattr(fn, "__name__", type(fn).__name__) for fn in self._validators] return f"{type(self).__name__}({names!r})" diff --git a/plugboard-schemas/pyproject.toml b/plugboard-schemas/pyproject.toml index b682b8445..71ea2f738 100644 --- a/plugboard-schemas/pyproject.toml +++ b/plugboard-schemas/pyproject.toml @@ -37,14 +37,6 @@ root = ".." [tool.uv] package = true -[tool.mypy] # Static type checking -exclude = [".git", "__pycache__", ".venv", "venv"] -ignore_missing_imports = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -no_implicit_optional = true -plugins = "pydantic.mypy" - [tool.ruff] # Code formatting and linting line-length = 100 src = ["plugboard_schemas"] diff --git a/plugboard/__init__.py b/plugboard/__init__.py index 501cb51e3..e009248dc 100644 --- a/plugboard/__init__.py +++ b/plugboard/__init__.py @@ -3,4 +3,4 @@ from importlib.metadata import version -__version__ = version(__package__) +__version__ = version("plugboard") diff --git a/plugboard/component/component.py b/plugboard/component/component.py index 933170e98..af51a2eb6 100644 --- a/plugboard/component/component.py +++ b/plugboard/component/component.py @@ -178,8 +178,8 @@ def _configure_io(cls) -> None: cls.io = IO( inputs=sorted(io_args["inputs"], key=str), outputs=sorted(io_args["outputs"], key=str), - input_events=sorted(io_args["input_events"], key=str), - output_events=sorted(io_args["output_events"], key=str), + input_events=_t.cast(list[_t.Type[Event]], sorted(io_args["input_events"], key=str)), + output_events=_t.cast(list[_t.Type[Event]], sorted(io_args["output_events"], key=str)), event_field_coverage=event_field_coverage, ) # Set exports for subclass diff --git a/plugboard/component/utils.py b/plugboard/component/utils.py index b9e4f75c1..b40a4af39 100644 --- a/plugboard/component/utils.py +++ b/plugboard/component/utils.py @@ -11,10 +11,17 @@ from plugboard.utils import gen_rand_str -_FuncT = _t.TypeVar( - "_FuncT", - bound=_t.Callable[..., _t.Union[dict[str, _t.Any], _t.Awaitable[dict[str, _t.Any]]]], -) +class _ComponentFunction(_t.Protocol): + __name__: str + __module__: str + __doc__: str | None + + def __call__( + self, *args: _t.Any, **kwargs: _t.Any + ) -> dict[str, _t.Any] | _t.Awaitable[dict[str, _t.Any]]: ... + + +_FuncT = _t.TypeVar("_FuncT", bound=_ComponentFunction) _FUNC_COMPONENT_DOC_TEMPLATE = Template( """Component for wrapped function $name. @@ -101,9 +108,11 @@ async def step(self) -> _t.Any: def _ensure_async_callable(func: _FuncT) -> _t.Callable[..., _t.Awaitable[dict[str, _t.Any]]]: if inspect.iscoroutinefunction(func): - return func + return _t.cast(_t.Callable[..., _t.Awaitable[dict[str, _t.Any]]], func) + + sync_func = _t.cast(_t.Callable[..., dict[str, _t.Any]], func) async def _async_func(*args: _t.Any, **kwargs: _t.Any) -> dict[str, _t.Any]: - return func(*args, **kwargs) # type: ignore[return-value] + return sync_func(*args, **kwargs) return _async_func diff --git a/plugboard/connector/asyncio_channel.py b/plugboard/connector/asyncio_channel.py index d9b6dd123..ce9c7f9e5 100644 --- a/plugboard/connector/asyncio_channel.py +++ b/plugboard/connector/asyncio_channel.py @@ -32,13 +32,13 @@ def __init__( self._queue: asyncio.Queue = queue or asyncio.Queue(maxsize=maxsize) self._subscribers: _t.Optional[set[asyncio.Queue]] = subscribers - async def send(self, item: _t.Any) -> None: + async def send(self, msg: _t.Any) -> None: """Sends an item through the `Channel`.""" if self._subscribers is None: - return await self._queue.put(item) + return await self._queue.put(msg) async with asyncio.TaskGroup() as tg: for queue in self._subscribers: - tg.create_task(queue.put(item)) + tg.create_task(queue.put(msg)) async def recv(self) -> _t.Any: """Returns an item received from the `Channel`.""" diff --git a/plugboard/connector/ray_channel.py b/plugboard/connector/ray_channel.py index 9bb5ba2c4..63a653be7 100644 --- a/plugboard/connector/ray_channel.py +++ b/plugboard/connector/ray_channel.py @@ -23,9 +23,9 @@ class RayChannel(Channel): @depends_on_optional("ray") def __init__( # noqa: D417 self, - actor_options: _t.Optional[dict] = None, + actor_options: _t.Optional[dict[str, _t.Any]] = None, **kwargs: _t.Any, - ): + ) -> None: """Instantiates `RayChannel`. Args: @@ -51,9 +51,9 @@ def is_closed(self) -> bool: """ return self._actor.getattr.remote("is_closed") # type: ignore - async def send(self, item: _t.Any) -> None: + async def send(self, msg: _t.Any) -> None: """Sends an item through the `RayChannel`.""" - await self._actor.send.remote(item) # type: ignore + await self._actor.send.remote(msg) # type: ignore async def recv(self) -> _t.Any: """Returns an item received from the `RayChannel`.""" diff --git a/plugboard/events/event_handlers.py b/plugboard/events/event_handlers.py index a92003d90..c1031a911 100644 --- a/plugboard/events/event_handlers.py +++ b/plugboard/events/event_handlers.py @@ -50,7 +50,8 @@ def decorator(method: AsyncCallable) -> AsyncCallable: def _get_class_path_for_method(method: AsyncCallable) -> str: """Get the fully qualified path for the class containing a method.""" module_name = method.__module__ - qualname_parts = method.__qualname__.split(".") + qualname = getattr(method, "__qualname__", type(method).__qualname__) + qualname_parts = qualname.split(".") class_name = qualname_parts[-2] # Last part is the method name return f"{module_name}.{class_name}" diff --git a/plugboard/library/llm.py b/plugboard/library/llm.py index fe303b719..9322ba562 100644 --- a/plugboard/library/llm.py +++ b/plugboard/library/llm.py @@ -86,7 +86,9 @@ def _set_response(self, chat_response: ChatResponse, expand: bool) -> None: if not expand: self.response: str | None = chat_response.message.content else: - for field, value in chat_response.raw.model_dump().items(): # type: ignore[union-attr] + if chat_response.raw is None: + raise ValueError("Expected structured response payload from LLM.") + for field, value in chat_response.raw.model_dump().items(): setattr(self, field, value) diff --git a/plugboard/library/sql_io.py b/plugboard/library/sql_io.py index d56507574..ea9c0010f 100644 --- a/plugboard/library/sql_io.py +++ b/plugboard/library/sql_io.py @@ -1,10 +1,11 @@ """Provides `SQLReader` and `SQLWriter` components to access SQL databases from Plugboard models.""" +import collections.abc as cabc from collections import defaultdict, deque import typing as _t from sqlalchemy import MetaData, Table, insert, text -from sqlalchemy.engine import Engine, Row, create_engine +from sqlalchemy.engine import Connection, Engine, Row, create_engine from sqlalchemy.exc import InvalidRequestError from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine @@ -41,10 +42,12 @@ def __init__( self._connection_string = connection_string self._query = query self._params = params or {} - self._reader: _t.Optional[_t.AsyncIterator | _t.Iterator] = None + self._reader: cabc.AsyncIterator[cabc.Sequence[Row[_t.Any]]] | cabc.Iterator[ + cabc.Sequence[Row[_t.Any]] + ] | None = None self._connect_args = connect_args or {} - async def _run_query_async(self) -> _t.AsyncIterator[_t.Sequence[Row]]: + async def _run_query_async(self) -> cabc.AsyncIterator[cabc.Sequence[Row[_t.Any]]]: engine = create_async_engine(self._connection_string, **self._connect_args) async with engine.connect() as conn: if self._chunk_size: @@ -61,7 +64,7 @@ async def _run_query_async(self) -> _t.AsyncIterator[_t.Sequence[Row]]: yield list(result) raise NoMoreDataException - def _run_query_sync(self) -> _t.Iterator[_t.Sequence[Row]]: + def _run_query_sync(self) -> cabc.Iterator[cabc.Sequence[Row[_t.Any]]]: engine = create_engine(self._connection_string, **self._connect_args) with engine.connect() as conn: if self._chunk_size: @@ -77,7 +80,7 @@ def _run_query_sync(self) -> _t.Iterator[_t.Sequence[Row]]: yield list(result) raise NoMoreDataException - async def _fetch(self) -> _t.Sequence[Row]: + async def _fetch(self) -> cabc.Sequence[Row[_t.Any]]: if self._reader is None: try: self._reader = self._run_query_async() @@ -87,9 +90,9 @@ async def _fetch(self) -> _t.Sequence[Row]: self._reader = self._run_query_sync() return next(self._reader) - if isinstance(self._reader, _t.AsyncIterator): + if isinstance(self._reader, cabc.AsyncIterator): return await self._reader.__anext__() - return next(self._reader) + return next(_t.cast(cabc.Iterator[cabc.Sequence[Row[_t.Any]]], self._reader)) async def _convert(self, data: _t.Sequence[Row]) -> dict[str, deque]: converted_data: dict[str, deque] = defaultdict(deque) @@ -138,11 +141,11 @@ async def _save_rows_async(self, data: list[dict[str, _t.Any]]) -> None: raise RuntimeError("No async database connection available") async with self._engine.connect() as conn: if self._table is None: - await conn.run_sync( - self._metadata.reflect, - only=[self._table_name], - ) - self._table = Table(self._table_name, self._metadata, autoload_with=self._engine) # type: ignore[arg-type] + def _load_table(sync_conn: Connection) -> Table: + self._metadata.reflect(bind=sync_conn, only=[self._table_name]) + return Table(self._table_name, self._metadata, autoload_with=sync_conn) + + self._table = await conn.run_sync(_load_table) await conn.execute(insert(self._table).values(data)) def _save_rows_sync(self, data: list[dict[str, _t.Any]]) -> None: diff --git a/plugboard/state/state_backend.py b/plugboard/state/state_backend.py index 6257ba229..39e4acd47 100644 --- a/plugboard/state/state_backend.py +++ b/plugboard/state/state_backend.py @@ -37,18 +37,18 @@ def __init__( metadata: Metadata key value pairs. kwargs: Additional keyword arguments. """ - self._local_state = {"job_id": job_id, "metadata": metadata, **kwargs} + self._local_state: dict[str, _t.Any] = {"job_id": job_id, "metadata": metadata, **kwargs} self._initialised_with_job_id = False self._logger = DI.logger.resolve_sync().bind(cls=self.__class__.__name__, job_id=job_id) self._logger.info("StateBackend created") self._ctx = ExitStack() - def __getstate__(self) -> dict: + def __getstate__(self) -> dict[str, _t.Any]: state = self.__dict__.copy() state.pop("_ctx", None) return state - def __setstate__(self, state: dict) -> None: + def __setstate__(self, state: dict[str, _t.Any]) -> None: self.__dict__.update(state) self._ctx = ExitStack() job_id = self._local_state.get("job_id") diff --git a/plugboard/utils/logging.py b/plugboard/utils/logging.py index 0c9fde88d..333b3b404 100644 --- a/plugboard/utils/logging.py +++ b/plugboard/utils/logging.py @@ -11,10 +11,10 @@ def _is_ipython() -> bool: try: - from builtins import get_ipython # type: ignore [attr-defined] # noqa: F401 + from IPython import get_ipython except ImportError: return False - return True + return get_ipython() is not None def _serialiser(obj: _t.Any, default: _t.Callable | None) -> bytes: diff --git a/plugboard/utils/ray.py b/plugboard/utils/ray.py index e3037d177..b84d298fe 100644 --- a/plugboard/utils/ray.py +++ b/plugboard/utils/ray.py @@ -31,13 +31,14 @@ def _call_with_name(func: _t.Callable, path: tuple[str, ...]) -> _t.Callable: # underlying function (which supports __signature__ assignment) rather than # the bound method object (which does not). wraps_target = getattr(func, "__func__", func) + func_name = getattr(func, "__name__", type(func).__name__) @wraps(wraps_target) def wrapper(self: _ActorWrapper, *args: _t.Any, **kwargs: _t.Any) -> _t.Callable: obj = self._self for name in path: obj = getattr(obj, name) - return getattr(obj, func.__name__)(*args, **kwargs) + return getattr(obj, func_name)(*args, **kwargs) return wrapper @@ -47,13 +48,14 @@ def _call_with_name_async(func: _t.Callable, path: tuple[str, ...]) -> _t.Callab # underlying function (which supports __signature__ assignment) rather than # the bound method object (which does not). wraps_target = getattr(func, "__func__", func) + func_name = getattr(func, "__name__", type(func).__name__) @wraps(wraps_target) async def wrapper(self: _ActorWrapper, *args: _t.Any, **kwargs: _t.Any) -> _t.Callable: obj = self._self for name in path: obj = getattr(obj, name) - return await getattr(obj, func.__name__)(*args, **kwargs) + return await getattr(obj, func_name)(*args, **kwargs) return wrapper diff --git a/pyproject.toml b/pyproject.toml index c997d2d38..5c30996ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,11 +63,11 @@ dev = [ "ipywidgets>=8.1.5,<9", "jupyterlab>=4.2,<5", "licensecheck>=2025.1.0", - "mypy>=1.11,<3", "nbstripout>=0.8,<1", "pre-commit>=3.8,<5", "radon>=6.0.1,<7", "ruff>=0.5,<1", + "ty>=0.0.61", "types-aiofiles>=24.1,<26", "xenon>=0.9.3,<1", ] @@ -147,13 +147,20 @@ parallel = true concurrency = ["multiprocessing", "thread"] sigterm = true -[tool.mypy] # Static type checking -exclude = [".git", "__pycache__", ".venv", "venv", "docs", "examples"] -ignore_missing_imports = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -no_implicit_optional = true -plugins = "pydantic.mypy" +[tool.ty] # Static type checking + +[tool.ty.analysis] +replace-imports-with-any = [ + "openai_responses.**", + "pandas.**", + "ray.**", + "websockets.**", +] + +[tool.ty.rules] +invalid-type-form = "ignore" +possibly-missing-submodule = "ignore" +unused-type-ignore-comment = "ignore" [tool.ruff] # Code formatting and linting line-length = 100 diff --git a/tests/integration/test_component_decorator.py b/tests/integration/test_component_decorator.py index e1ae893a8..a6db2a51e 100644 --- a/tests/integration/test_component_decorator.py +++ b/tests/integration/test_component_decorator.py @@ -142,8 +142,13 @@ async def test_process_builder_with_decorated_components( ) -> None: """Tests a process using components created with the component decorator executes correctly.""" iters = 10 + process_type = ( + "plugboard.process.LocalProcess" + if process_cls.__name__ == "LocalProcess" + else "plugboard.process.RayProcess" + ) process_spec = ProcessSpec( - type=f"{process_cls.__module__}.{process_cls.__name__}", + type=process_type, args=ProcessArgsSpec( components=[ ComponentSpec( diff --git a/tests/integration/test_job_id_wiring.py b/tests/integration/test_job_id_wiring.py index c820236b0..d7fbbb21f 100644 --- a/tests/integration/test_job_id_wiring.py +++ b/tests/integration/test_job_id_wiring.py @@ -65,8 +65,10 @@ def built_process(self) -> _t.Optional[Process]: def build(self, spec: ProcessSpec) -> Process: """Build the process.""" self._built_process = self._actual_build_fn(spec) - setattr(self._built_process, "run", lambda: self._mock_process_run(self._built_process)) - return self._built_process + built_process = self._built_process + assert built_process is not None + setattr(built_process, "run", lambda: self._mock_process_run(built_process)) + return built_process @staticmethod async def _mock_process_run(process: Process) -> None: diff --git a/tests/integration/test_tuner.py b/tests/integration/test_tuner.py index bba81b826..2b144320e 100644 --- a/tests/integration/test_tuner.py +++ b/tests/integration/test_tuner.py @@ -137,6 +137,7 @@ async def test_tune(config: dict, mode: str, process_type: str, ray_ctx: None) - best_result = tuner.run( spec=process_spec, ) + assert not isinstance(best_result, list) result = tuner.result_grid # There must be no failed trials assert not any(t.error for t in result) @@ -206,6 +207,7 @@ async def test_multi_objective_tune(config: dict, ray_ctx: None) -> None: best_result = tuner.run( spec=process_spec, ) + assert isinstance(best_result, list) result = tuner.result_grid # There must be no failed trials assert not [t for t in result if t.error] @@ -247,6 +249,7 @@ async def test_process_parameter_tuning(config: dict, ray_ctx: None) -> None: best_result = tuner.run( spec=process_spec, ) + assert not isinstance(best_result, list) result = tuner.result_grid # There must be no failed trials assert not [t for t in result if t.error] @@ -289,6 +292,7 @@ async def test_tune_with_constraint(config: dict, ray_ctx: None) -> None: best_result = tuner.run( spec=process_spec, ) + assert not isinstance(best_result, list) result = tuner.result_grid # There must be no failed trials assert not any(t.error for t in result) @@ -362,6 +366,7 @@ async def test_custom_space_tune( """Tests tuning with a custom search space.""" spec = ConfigSpec.model_validate(dynamic_param_config) process_spec = spec.plugboard.process + space_func_name = getattr(space_func, "__name__", "") tuner = Tuner( objective=ObjectiveSpec( object_type="component", @@ -389,7 +394,7 @@ async def test_custom_space_tune( num_samples=10, mode="max", max_concurrent=2, - algorithm=OptunaSpec(space=f"tests.integration.test_tuner.{space_func.__name__}"), + algorithm=OptunaSpec(space=f"tests.integration.test_tuner.{space_func_name}"), ) tuner.run( spec=process_spec, @@ -404,6 +409,6 @@ async def test_custom_space_tune( if r.config["n_list"] < 5: # When n_list < 5, all list_param values are negative assert all(v < 0.0 for v in r.config["component.d.arg.list_param"]) - if space_func.__name__ == "custom_space_with_process_spec": + if space_func_name == "custom_space_with_process_spec": # The iters parameter must be set based on the process params assert r.config["component.a.arg.iters"] <= process_spec.args.parameters["max_iters"] diff --git a/tests/unit/test_llm.py b/tests/unit/test_llm.py index 1518d80cc..cc3392692 100644 --- a/tests/unit/test_llm.py +++ b/tests/unit/test_llm.py @@ -134,6 +134,7 @@ async def test_openai_structured_chat( assert llm.x == 45 assert llm.y == "test" else: + assert llm.response is not None assert json.loads(llm.response) == test_response.model_dump() diff --git a/tests/unit/test_schemas.py b/tests/unit/test_schemas.py index e69e76d0e..1d5539747 100644 --- a/tests/unit/test_schemas.py +++ b/tests/unit/test_schemas.py @@ -1,5 +1,7 @@ """Provides unit tests for the schemas module.""" +import typing as _t + import msgspec import pytest @@ -24,7 +26,7 @@ def test_config_spec() -> None: def test_tune_spec() -> None: """Test the TuneSpec class.""" - valid_spec = { + valid_spec: dict[str, _t.Any] = { "objective": { "object_type": "component", "object_name": "my_component", @@ -69,7 +71,7 @@ def test_tune_spec() -> None: # Validate the TuneSpec with the valid specification _ = TuneSpec(args=TuneArgsSpec.model_validate(valid_spec)) - invalid_spec = valid_spec.copy() + invalid_spec: dict[str, _t.Any] = valid_spec.copy() invalid_spec["mode"] = ["min", "max"] # Invalid mode should raise a validation error with pytest.raises(ValueError): diff --git a/uv.lock b/uv.lock index 0038089b5..3578e203c 100644 --- a/uv.lock +++ b/uv.lock @@ -359,46 +359,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, ] -[[package]] -name = "ast-serialize" -version = "0.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/81/9d/09e27731bd5864a9ce04e3244074e674bb8936bf62b45e0357248717adac/ast_serialize-0.5.0.tar.gz", hash = "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6", size = 61157, upload-time = "2026-05-17T17:48:29.429Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/9a/13dde51ba9e15f8b97957ab7cb0120d0e381524d651c6bd630b9c359227f/ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a", size = 1183520, upload-time = "2026-05-17T17:47:30.831Z" }, - { url = "https://files.pythonhosted.org/packages/37/de/5a7f0a9fe68944f536632a5af84676739c7d2582be42deb082634bf3a754/ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b", size = 1175779, upload-time = "2026-05-17T17:47:32.551Z" }, - { url = "https://files.pythonhosted.org/packages/9c/81/0bb853e76e4f6e9a1855d569003c59e19ffac45f7079d91505d1bb212f92/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1", size = 1233750, upload-time = "2026-05-17T17:47:34.731Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d3/4cf705beeccc08754d0bbda99aefff26110e209b9a07ac8a6b60eec48531/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6", size = 1235942, upload-time = "2026-05-17T17:47:36.287Z" }, - { url = "https://files.pythonhosted.org/packages/26/c8/ee097e437ea27dd2b8b227865c875492b585650a5802a22d82b304c8201b/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2", size = 1442517, upload-time = "2026-05-17T17:47:38.17Z" }, - { url = "https://files.pythonhosted.org/packages/ff/bd/68063442838f1ba68ec72b5436430bc75b3bb17a1a3c3063f09b0c05ae2b/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903", size = 1254081, upload-time = "2026-05-17T17:47:39.826Z" }, - { url = "https://files.pythonhosted.org/packages/50/e2/1e520793bc6a4e4524a6ab022391e827825eaa0c3811828bfdc6852eca26/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261", size = 1259910, upload-time = "2026-05-17T17:47:41.369Z" }, - { url = "https://files.pythonhosted.org/packages/4e/e1/49b60f467979979cfe6913b43948ff25bca971ad0591d181812f163a988e/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027", size = 1250678, upload-time = "2026-05-17T17:47:43.702Z" }, - { url = "https://files.pythonhosted.org/packages/74/ba/66ab9555de6275677566f6574e5ef6c29cb185ea866f643bc06f8280a8ee/ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937", size = 1301603, upload-time = "2026-05-17T17:47:46.256Z" }, - { url = "https://files.pythonhosted.org/packages/66/42/6aca9b9abc710014b2be9059689e5dd1679339e78f567ffb4d255a9e2050/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c", size = 1410332, upload-time = "2026-05-17T17:47:47.899Z" }, - { url = "https://files.pythonhosted.org/packages/47/68/2f76594432a22581ecf878b5e75a9b8601c24b2241cf0bbeb1e21fcf370c/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b", size = 1509979, upload-time = "2026-05-17T17:47:50.942Z" }, - { url = "https://files.pythonhosted.org/packages/40/ac/a93c9b58292653f6c595752f677a08e608f903b710594909e9231a389b3b/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab", size = 1505002, upload-time = "2026-05-17T17:47:54.093Z" }, - { url = "https://files.pythonhosted.org/packages/14/2e/b278f68c497ee2f1d1576cbbef8db5281cd4a5f2db040537592ac9c8862e/ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3", size = 1456231, upload-time = "2026-05-17T17:47:56.311Z" }, - { url = "https://files.pythonhosted.org/packages/0b/43/419be1c566a4c504cd8fd60ce2f84e790f295495c0f327cfaeadf3d51012/ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38", size = 1058668, upload-time = "2026-05-17T17:47:58.305Z" }, - { url = "https://files.pythonhosted.org/packages/03/6f/c9d4d549295ed05111aeb8853232d1afd9d0a179fddb01eeffbb3a4a6842/ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c", size = 1101075, upload-time = "2026-05-17T17:48:00.35Z" }, - { url = "https://files.pythonhosted.org/packages/d0/8e/d00c5ab30c58222e07d62956fca86c59d91b9ad32997e633c38b526623a3/ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb", size = 1075347, upload-time = "2026-05-17T17:48:01.753Z" }, - { url = "https://files.pythonhosted.org/packages/e0/9e/dc2530acb3a60dc6e46d65abf27d1d9f86721694757906a148d90a6860de/ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101", size = 1191380, upload-time = "2026-05-17T17:48:03.738Z" }, - { url = "https://files.pythonhosted.org/packages/26/0a/bd3d18a582f273d6c843d16bb9e22e9e16365ff7991e92f18f798e9f1224/ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a", size = 1183879, upload-time = "2026-05-17T17:48:05.463Z" }, - { url = "https://files.pythonhosted.org/packages/40/ae/1f919100f8620887af58fcc381c61a1f218cdf89c6e155f87b213e61010a/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211", size = 1244529, upload-time = "2026-05-17T17:48:07.008Z" }, - { url = "https://files.pythonhosted.org/packages/c6/ca/6376559dcce707cdbc1d0d9a13c8d3baaaa501e949ce0ebdc4230cd881aa/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf", size = 1240560, upload-time = "2026-05-17T17:48:08.46Z" }, - { url = "https://files.pythonhosted.org/packages/35/b2/a620e206b5aeb7efbf2710336df57d457cffbb3991076bbcc1147ef9abd4/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9", size = 1451172, upload-time = "2026-05-17T17:48:09.922Z" }, - { url = "https://files.pythonhosted.org/packages/fa/e0/4ad5c04c24a40481b2935ce9a0ccdb6023dc8b667167d06ae530cc3512f2/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee", size = 1265072, upload-time = "2026-05-17T17:48:11.469Z" }, - { url = "https://files.pythonhosted.org/packages/b2/71/4d1d479aa56d0101c40e17720c3d6ac2af7269ea0487a80b18e7bfd1a5b7/ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809", size = 1270488, upload-time = "2026-05-17T17:48:13.575Z" }, - { url = "https://files.pythonhosted.org/packages/6d/4f/0de1bbe06f6edef9fde4ed12ca8e7b3ec7e6e2bd4e672c5af487f7957665/ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43", size = 1260702, upload-time = "2026-05-17T17:48:15.141Z" }, - { url = "https://files.pythonhosted.org/packages/75/61/e00872439cfdddcc3c1b6cdaa6e5d904ba8e26a18807c67c4e14409d0ca8/ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934", size = 1311182, upload-time = "2026-05-17T17:48:16.779Z" }, - { url = "https://files.pythonhosted.org/packages/76/8e/699a5b955f7926956c95e9e1d74132acad73c2fe7a426f94da89123c20aa/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759", size = 1421410, upload-time = "2026-05-17T17:48:18.527Z" }, - { url = "https://files.pythonhosted.org/packages/a9/ae/d5b7626874478997adc7a29ab28accf21e596fb590c944290401dfd0b29e/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887", size = 1516587, upload-time = "2026-05-17T17:48:20.133Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ce/b59e02a82d9c4244d64cde502e0b00e83e38816abe19155ceb5437402c7f/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27", size = 1515171, upload-time = "2026-05-17T17:48:21.921Z" }, - { url = "https://files.pythonhosted.org/packages/8b/38/d8d90042747d05aa08d4efcf1c99035a5f670a6bf4c214d31644392afbca/ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d", size = 1464668, upload-time = "2026-05-17T17:48:23.544Z" }, - { url = "https://files.pythonhosted.org/packages/dd/51/5b840c4df7334104cecffa28f23904fe81ca89ca223d2450e288de39fd3c/ast_serialize-0.5.0-cp39-abi3-win32.whl", hash = "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a", size = 1068311, upload-time = "2026-05-17T17:48:25.027Z" }, - { url = "https://files.pythonhosted.org/packages/41/11/ca5672c7d491825bc4cd6702dea106a6b60d928707712ec257c7833ae476/ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash = "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590", size = 1108931, upload-time = "2026-05-17T17:48:26.591Z" }, - { url = "https://files.pythonhosted.org/packages/45/19/cc8bd127d28a43da249aa955cfd164cf8fd534e79e42cea96c4854d72fd0/ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642", size = 1081181, upload-time = "2026-05-17T17:48:28.122Z" }, -] - [[package]] name = "asttokens" version = "3.0.1" @@ -2500,66 +2460,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/59/97/9b410ed8fbc6e79c1ee8b13f8777a80137d4bc189caf2c6202358e66192c/lazy_object_proxy-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:7601ec171c7e8584f8ff3f4e440aa2eebf93e854f04639263875b8c2971f819f", size = 26988, upload-time = "2025-08-22T13:49:57.302Z" }, ] -[[package]] -name = "librt" -version = "0.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/40/08/9e7f6b5d2b5bed6ad055cdd5925f192bb403a51280f86b56554d9d0699a2/librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1", size = 200139, upload-time = "2026-05-10T18:17:25.138Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/d0/07c77e067f0838949b43bd89232c29d72efebb9d2801a9750184eb706b71/librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46", size = 144147, upload-time = "2026-05-10T18:15:53.227Z" }, - { url = "https://files.pythonhosted.org/packages/7a/24/8493538fa4f62f982686398a5b8f68008138a75086abdea19ade64bf4255/librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3", size = 143614, upload-time = "2026-05-10T18:15:54.657Z" }, - { url = "https://files.pythonhosted.org/packages/ff/1e/f8bad050810d9171f34a1648ed910e56814c2ba61639f2bd53c6377ae24b/librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67", size = 485538, upload-time = "2026-05-10T18:15:56.117Z" }, - { url = "https://files.pythonhosted.org/packages/c0/fe/3594ebfbaf03084ba4b120c9ba5c3183fd938a48725e9bbe6ff0a5159ad8/librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a", size = 479623, upload-time = "2026-05-10T18:15:57.544Z" }, - { url = "https://files.pythonhosted.org/packages/b0/da/5d1876984b3746c85dbd219dbfcb73c85f54ee263fd32e5b2a632ec14571/librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a", size = 513082, upload-time = "2026-05-10T18:15:58.805Z" }, - { url = "https://files.pythonhosted.org/packages/19/6e/55bdf5d5ca00c3e18430690bf2c953d8d3ffd3c337418173d33dec985dc9/librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f", size = 508105, upload-time = "2026-05-10T18:16:00.2Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/f1f23a7c595ee90ece4d35c851e5d104b1311a887ed1b4ac4c35bbd13da8/librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b", size = 522268, upload-time = "2026-05-10T18:16:01.708Z" }, - { url = "https://files.pythonhosted.org/packages/b6/02/5720f5697a7f54b78b3aefbe20df3a48cedcff1276618c4aa481177942ed/librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766", size = 527348, upload-time = "2026-05-10T18:16:03.496Z" }, - { url = "https://files.pythonhosted.org/packages/50/db/b4a47c6f91db4ff76348a0b3dd0cc65e090a078b765a810a62ff9434c3d3/librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d", size = 516294, upload-time = "2026-05-10T18:16:05.173Z" }, - { url = "https://files.pythonhosted.org/packages/9e/58/9384b2f4eb1ed1d273d40948a7c5c4b2360213b402ef3be4641c06299f9c/librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8", size = 553608, upload-time = "2026-05-10T18:16:06.839Z" }, - { url = "https://files.pythonhosted.org/packages/21/7b/5aa8848a7c6a9278c79375146da1812e695754ceec5f005e6043461a7315/librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a", size = 101879, upload-time = "2026-05-10T18:16:08.103Z" }, - { url = "https://files.pythonhosted.org/packages/37/33/8a745436944947575b584231750a41417de1a38cf6a2e9251d1065651c09/librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9", size = 119831, upload-time = "2026-05-10T18:16:09.174Z" }, - { url = "https://files.pythonhosted.org/packages/59/67/a6739ac96e28b7855808bdb0370e250606104a859750d209e5a0716fe7ab/librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c", size = 103470, upload-time = "2026-05-10T18:16:10.369Z" }, - { url = "https://files.pythonhosted.org/packages/82/61/e59168d4d0bf2bf90f4f0caf7a001bfc60254c3af4586013b04dc3ef517b/librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894", size = 144119, upload-time = "2026-05-10T18:16:11.771Z" }, - { url = "https://files.pythonhosted.org/packages/61/fd/caa1d60b12f7dd79ccea23054e06eeaebe266a5f52c40a6b651069200ce5/librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c", size = 143565, upload-time = "2026-05-10T18:16:13.334Z" }, - { url = "https://files.pythonhosted.org/packages/b8/a9/dc744f5c2b4978d48db970be29f22716d3413d28b14ad99740817315cf2c/librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea", size = 485395, upload-time = "2026-05-10T18:16:14.729Z" }, - { url = "https://files.pythonhosted.org/packages/8f/21/7f8e97a1e4dae952a5a95948f6f8507a173bc1e669f54340bba6ca1ca31b/librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230", size = 479383, upload-time = "2026-05-10T18:16:16.321Z" }, - { url = "https://files.pythonhosted.org/packages/a6/6d/d8ee9c114bebf2c50e29ec2aa940826fccb62a645c3e4c18760987d0e16d/librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2", size = 513010, upload-time = "2026-05-10T18:16:17.647Z" }, - { url = "https://files.pythonhosted.org/packages/f0/43/0b5708af2bd30a46400e72ba6bdaa8f066f15fb9a688527e34220e8d6c06/librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3", size = 508433, upload-time = "2026-05-10T18:16:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/4a/50/356187247d09013490481033183b3532b58acf8028bcb34b2b56a375c9b2/librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21", size = 522595, upload-time = "2026-05-10T18:16:20.642Z" }, - { url = "https://files.pythonhosted.org/packages/40/e7/c6ac4240899c7f3248079d5a9900debe0dadb3fdeaf856684c987105ba47/librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930", size = 527255, upload-time = "2026-05-10T18:16:22.352Z" }, - { url = "https://files.pythonhosted.org/packages/eb/b5/a81322dbeedeeaf9c1ee6f001734d28a09d8383ac9e6779bc24bbd0743c6/librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be", size = 516847, upload-time = "2026-05-10T18:16:23.627Z" }, - { url = "https://files.pythonhosted.org/packages/ae/66/6e6323787d592b55204a42595ff1102da5115601b53a7e9ddebc889a6da5/librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e", size = 553920, upload-time = "2026-05-10T18:16:25.025Z" }, - { url = "https://files.pythonhosted.org/packages/9c/21/623f8ca230857102066d9ca8c6c1734995908c4d0d1bee7bb2ef0021cb33/librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e", size = 101898, upload-time = "2026-05-10T18:16:26.649Z" }, - { url = "https://files.pythonhosted.org/packages/b3/1d/b4ebd44dd723f768469007515cb92251e0ae286c94c140f374801140fa74/librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47", size = 119812, upload-time = "2026-05-10T18:16:27.859Z" }, - { url = "https://files.pythonhosted.org/packages/3b/e4/b2f4ca7965ca373b491cdb4bc25cdb30c1649ca81a8782056a83850292a9/librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44", size = 103448, upload-time = "2026-05-10T18:16:29.066Z" }, - { url = "https://files.pythonhosted.org/packages/29/eb/dbce197da4e227779e56b5735f2decc3eb36e55a1cdbf1bd65d6639d76c1/librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd", size = 143345, upload-time = "2026-05-10T18:16:30.674Z" }, - { url = "https://files.pythonhosted.org/packages/76/a3/254bebd0c11c8ba684018efb8006ff22e466abce445215cca6c778e7d9de/librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4", size = 143131, upload-time = "2026-05-10T18:16:32.037Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3f/f77d6122d21ac7bf6ae8a7dfced1bd2a7ac545d3273ebdcaf8042f6d619f/librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8", size = 477024, upload-time = "2026-05-10T18:16:33.493Z" }, - { url = "https://files.pythonhosted.org/packages/ac/0a/2c996dadebaa7d9bbbd43ef2d4f3e66b6da545f838a41694ef6172cebec8/librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b", size = 474221, upload-time = "2026-05-10T18:16:34.864Z" }, - { url = "https://files.pythonhosted.org/packages/0a/7e/f5d92af8486b8272c23b3e686b46ff72d89c8169585eb61eef01a2ac7147/librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175", size = 505174, upload-time = "2026-05-10T18:16:36.705Z" }, - { url = "https://files.pythonhosted.org/packages/af/1a/cb0734fe86398eb33193ab753b7326255c74cac5eb09e76b9b16536e7adb/librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03", size = 497216, upload-time = "2026-05-10T18:16:38.418Z" }, - { url = "https://files.pythonhosted.org/packages/18/06/094820f91558b66e29943c0ec41c9914f460f48dd51fc503c3101e10842d/librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c", size = 513921, upload-time = "2026-05-10T18:16:39.848Z" }, - { url = "https://files.pythonhosted.org/packages/0b/c2/00de9018871a282f530cacb457d5ec0428f6ac7e6fedde9aff7468d9fb04/librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3", size = 520850, upload-time = "2026-05-10T18:16:41.471Z" }, - { url = "https://files.pythonhosted.org/packages/51/9d/64631832348fd1834fb3a61b996434edddaaf25a31d03b0a76273159d2cf/librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96", size = 504237, upload-time = "2026-05-10T18:16:43.15Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ec/ae5525eb16edc827a044e7bb8777a455ff95d4bca9379e7e6bddd7383647/librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe", size = 546261, upload-time = "2026-05-10T18:16:44.408Z" }, - { url = "https://files.pythonhosted.org/packages/5a/09/adce371f27ca039411da9659f7430fcc2ba6cd0c7b3e4467a0f091be7fa9/librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f", size = 96965, upload-time = "2026-05-10T18:16:46.039Z" }, - { url = "https://files.pythonhosted.org/packages/d6/ee/8ac720d98548f173c7ce2e632a7ca94673f74cacd5c8162a84af5b35958a/librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7", size = 115151, upload-time = "2026-05-10T18:16:47.133Z" }, - { url = "https://files.pythonhosted.org/packages/94/20/c900cf14efeb09b6bef2b2dff20779f73464b97fd58d1c6bccc379588ae3/librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1", size = 98850, upload-time = "2026-05-10T18:16:48.597Z" }, - { url = "https://files.pythonhosted.org/packages/0c/71/944bfe4b64e12abffcd3c15e1cce07f72f3d55655083786285f4dedeb532/librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72", size = 151138, upload-time = "2026-05-10T18:16:49.839Z" }, - { url = "https://files.pythonhosted.org/packages/b6/10/99e64a5c86989357fda078c8143c533389585f6473b7439172dd8f3b3b2d/librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa", size = 151976, upload-time = "2026-05-10T18:16:51.062Z" }, - { url = "https://files.pythonhosted.org/packages/21/31/5072ad880946d83e5ea4147d6d018c78eefce85b77819b19bdd0ee229435/librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548", size = 557927, upload-time = "2026-05-10T18:16:52.632Z" }, - { url = "https://files.pythonhosted.org/packages/5e/8d/70b5fb7cfbab60edbe7381614ab985da58e144fbf465c86d44c95f43cdca/librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2", size = 539698, upload-time = "2026-05-10T18:16:53.934Z" }, - { url = "https://files.pythonhosted.org/packages/fa/a3/ba3495a0b3edbd24a4cae0d1d3c64f39a9fc45d06e812101289b50c1a619/librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f", size = 577162, upload-time = "2026-05-10T18:16:55.589Z" }, - { url = "https://files.pythonhosted.org/packages/f7/db/36e25fb81f99937ff1b96612a1dc9fd66f039cb9cc3aee12c01fac31aab9/librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51", size = 566494, upload-time = "2026-05-10T18:16:56.975Z" }, - { url = "https://files.pythonhosted.org/packages/33/0d/3f622b47f0b013eeb9cf4cc07ae9bfe378d832a4eec998b2b209fe84244d/librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2", size = 596858, upload-time = "2026-05-10T18:16:58.374Z" }, - { url = "https://files.pythonhosted.org/packages/a9/02/71b90bc93039c46a2000651f6ad60122b114c8f54c4ad306e0e96f5b75ad/librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085", size = 590318, upload-time = "2026-05-10T18:16:59.676Z" }, - { url = "https://files.pythonhosted.org/packages/04/04/418cb3f75621e2b761fb1ab0f017f4d70a1a72a6e7c74ee4f7e8d198c2f3/librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3", size = 575115, upload-time = "2026-05-10T18:17:01.007Z" }, - { url = "https://files.pythonhosted.org/packages/cc/2c/5a2183ac58dd911f26b5d7e7d7d8f1d87fcecdddd99d6c12169a258ff62c/librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd", size = 617918, upload-time = "2026-05-10T18:17:02.682Z" }, - { url = "https://files.pythonhosted.org/packages/15/1f/dc6771a52592a4451be6effa200cbfc9cec61e4393d3033d81a9d307961d/librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8", size = 103562, upload-time = "2026-05-10T18:17:03.99Z" }, - { url = "https://files.pythonhosted.org/packages/62/4a/7d1415567027286a75ba1093ec4aca11f073e0f559c530cf3e0a757ad55c/librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c", size = 124327, upload-time = "2026-05-10T18:17:05.465Z" }, - { url = "https://files.pythonhosted.org/packages/ce/62/b40b382fa0c66fee1478073eb8db352a4a6beda4a1adccf1df911d8c289c/librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253", size = 102572, upload-time = "2026-05-10T18:17:06.809Z" }, -] - [[package]] name = "license-expression" version = "30.4.4" @@ -3290,50 +3190,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, ] -[[package]] -name = "mypy" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ast-serialize" }, - { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, - { name = "mypy-extensions" }, - { name = "pathspec" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/82/15/cca9d88503549ed6fedeaa1d448cdddd542ee8a490232d732e278036fbf2/mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633", size = 3898359, upload-time = "2026-05-11T18:37:36.237Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/b1/55861beb5c339b44f9a2ba92df9e2cb1eeb4ae1eee674cdf7772c797778b/mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af", size = 14874381, upload-time = "2026-05-11T18:37:31.784Z" }, - { url = "https://files.pythonhosted.org/packages/0b/b3/b7f770114b7d0ac92d0f76e8d93c2780844a70488a90e91821927850da86/mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6", size = 13665501, upload-time = "2026-05-11T18:34:23.063Z" }, - { url = "https://files.pythonhosted.org/packages/b6/f3/8ae2037967e2126689a0c11d99e2b707134a565191e92c60ca2572aec60a/mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211", size = 14045750, upload-time = "2026-05-11T18:31:48.151Z" }, - { url = "https://files.pythonhosted.org/packages/a0/32/615eb5911859e43d054941b0d0a7d06cfa2870eba86529cf385b052b111c/mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b", size = 15061630, upload-time = "2026-05-11T18:37:06.898Z" }, - { url = "https://files.pythonhosted.org/packages/d4/03/4eafbfff8bfab1b87082741eae6e6a624028c984e6708b73bce2a8570c9d/mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22", size = 15288831, upload-time = "2026-05-11T18:31:18.07Z" }, - { url = "https://files.pythonhosted.org/packages/99/ee/919661478e5891a3c96e549c036e467e64563ab85995b10c53c8358e16a3/mypy-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b", size = 11135228, upload-time = "2026-05-11T18:34:31.23Z" }, - { url = "https://files.pythonhosted.org/packages/24/0a/6a12b9782ca0831a553192f351679f4548abc9d19a7cc93bb7feb02084c7/mypy-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8", size = 10040684, upload-time = "2026-05-11T18:36:48.199Z" }, - { url = "https://files.pythonhosted.org/packages/6e/dd/c7191469c777f07689c032a8f7326e393ea34c92d6d76eb7ce5ba57ea66d/mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5", size = 14852174, upload-time = "2026-05-11T18:31:38.929Z" }, - { url = "https://files.pythonhosted.org/packages/55/8c/aed55408879043d72bb9135f4d0d19a02b886dd569631e113e3d2706cb8d/mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e", size = 13651542, upload-time = "2026-05-11T18:36:04.636Z" }, - { url = "https://files.pythonhosted.org/packages/3a/8e/f371a824b1f1fa8ea6e3dbb8703d232977d572be2329554a3bc4d960302f/mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e", size = 14033929, upload-time = "2026-05-11T18:35:55.742Z" }, - { url = "https://files.pythonhosted.org/packages/94/21/f54be870d6dd53a82c674407e0f8eed7174b05ec78d42e5abd7b42e84fd5/mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285", size = 15039200, upload-time = "2026-05-11T18:33:10.281Z" }, - { url = "https://files.pythonhosted.org/packages/17/99/bf21748626a40ce59fd29a39386ab46afec88b7bd2f0fa6c3a97c995523f/mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5", size = 15272690, upload-time = "2026-05-11T18:32:07.205Z" }, - { url = "https://files.pythonhosted.org/packages/d6/d7/9e90d2cf47100bea550ed2bc7b0d4de3a62181d84d5e37da0003e8462637/mypy-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65", size = 11147435, upload-time = "2026-05-11T18:33:56.477Z" }, - { url = "https://files.pythonhosted.org/packages/ec/46/e5c449e858798e35ffc90946282a27c62a77be743fe17480e4977374eb91/mypy-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d", size = 10035052, upload-time = "2026-05-11T18:32:30.049Z" }, - { url = "https://files.pythonhosted.org/packages/b0/ca/b279a672e874aedd5498ae25f722dacc8aa86bbffb939b3f97cbb1cf6686/mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2", size = 14848422, upload-time = "2026-05-11T18:35:45.984Z" }, - { url = "https://files.pythonhosted.org/packages/27/e6/3efe56c631d959b9b4454e208b0ac4b7f4f58b404c89f8bec7b49efdfc21/mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f", size = 13677374, upload-time = "2026-05-11T18:36:57.188Z" }, - { url = "https://files.pythonhosted.org/packages/84/7f/8107ea87a44fd1f1b59882442f033c9c3488c127201b1d1d15f1cbd6022e/mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4", size = 14055743, upload-time = "2026-05-11T18:35:18.361Z" }, - { url = "https://files.pythonhosted.org/packages/51/4d/b6d34db183133b83761b9199a82d31557cdbb70a380d8c3b3438e11882a3/mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef", size = 15020937, upload-time = "2026-05-11T18:34:59.618Z" }, - { url = "https://files.pythonhosted.org/packages/ff/d7/f08360c691d758acb02f45022c34d98b92892f4ea756644e1000d4b9f3d8/mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135", size = 15253371, upload-time = "2026-05-11T18:36:41.081Z" }, - { url = "https://files.pythonhosted.org/packages/67/1b/09460a13719530a19bce27bd3bc8449e83569dd2ba7faf51c9c3c30c0b61/mypy-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21", size = 11326429, upload-time = "2026-05-11T18:34:13.526Z" }, - { url = "https://files.pythonhosted.org/packages/40/62/75dbf0f82f7b6680340efc614af29dd0b3c17b8a4f1cd09b8bd2fd6bc814/mypy-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57", size = 10218799, upload-time = "2026-05-11T18:32:23.491Z" }, - { url = "https://files.pythonhosted.org/packages/b2/66/caca04ed7d972fb6eb6dd1ccd6df1de5c38fae8c5b3dc1c4e8e0d85ee6b9/mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e", size = 15923458, upload-time = "2026-05-11T18:35:28.64Z" }, - { url = "https://files.pythonhosted.org/packages/ed/52/2d90cbe49d014b13ed7ff337930c30bad35893fe38a1e4641e756bb62191/mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780", size = 14757697, upload-time = "2026-05-11T18:36:14.208Z" }, - { url = "https://files.pythonhosted.org/packages/ac/37/d98f4a14e081b238992d0ed96b6d39c7cc0148c9699eb71eaa68629665ea/mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd", size = 15405638, upload-time = "2026-05-11T18:33:48.249Z" }, - { url = "https://files.pythonhosted.org/packages/a3/c2/15c46613b24a84fad2aea1248bf9619b99c2767ae9071fe224c179a0b7d4/mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08", size = 16215852, upload-time = "2026-05-11T18:32:50.296Z" }, - { url = "https://files.pythonhosted.org/packages/5c/90/9c16a57f482c76d25f6379762b56bbf65c711d8158cf271fb2802cfb0640/mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081", size = 16452695, upload-time = "2026-05-11T18:33:38.182Z" }, - { url = "https://files.pythonhosted.org/packages/0f/4c/215a4eeb63cacc5f17f516691ea7285d11e249802b942476bff15922a314/mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7", size = 12866622, upload-time = "2026-05-11T18:34:39.945Z" }, - { url = "https://files.pythonhosted.org/packages/4b/50/1043e1db5f455ffe4c9ab22747cd8ca2bc492b1e4f4e21b130a44ee2b217/mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6", size = 10610798, upload-time = "2026-05-11T18:36:31.444Z" }, - { url = "https://files.pythonhosted.org/packages/0d/2a/13ca1f292f6db1b98ff495ef3467736b331621c5917cad984b7043e7348d/mypy-2.1.0-py3-none-any.whl", hash = "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289", size = 2693302, upload-time = "2026-05-11T18:31:29.246Z" }, -] - [[package]] name = "mypy-extensions" version = "1.1.0" @@ -3982,7 +3838,6 @@ all = [ { name = "mkdocs-material" }, { name = "mkdocstrings", extra = ["python"] }, { name = "moto", extra = ["server"] }, - { name = "mypy" }, { name = "nbstripout" }, { name = "openai-responses" }, { name = "optuna" }, @@ -4000,6 +3855,7 @@ all = [ { name = "ruff" }, { name = "s3fs" }, { name = "time-machine" }, + { name = "ty" }, { name = "types-aiofiles" }, { name = "websockets" }, { name = "xenon" }, @@ -4011,11 +3867,11 @@ dev = [ { name = "ipywidgets" }, { name = "jupyterlab" }, { name = "licensecheck" }, - { name = "mypy" }, { name = "nbstripout" }, { name = "pre-commit" }, { name = "radon" }, { name = "ruff" }, + { name = "ty" }, { name = "types-aiofiles" }, { name = "xenon" }, ] @@ -4101,7 +3957,6 @@ all = [ { name = "mkdocs-material", specifier = ">=9.5,<10" }, { name = "mkdocstrings", extras = ["python"], specifier = ">=0.25,<2" }, { name = "moto", extras = ["server"], specifier = ">=5.0,<6" }, - { name = "mypy", specifier = ">=1.11,<3" }, { name = "nbstripout", specifier = ">=0.8,<1" }, { name = "openai-responses", specifier = ">=0.11.4,<1" }, { name = "optuna", specifier = ">=3.0,<5" }, @@ -4119,6 +3974,7 @@ all = [ { name = "ruff", specifier = ">=0.5,<1" }, { name = "s3fs", specifier = ">=2024.9.0" }, { name = "time-machine", specifier = ">=2.15,<4" }, + { name = "ty", specifier = ">=0.0.61" }, { name = "types-aiofiles", specifier = ">=24.1,<26" }, { name = "websockets", specifier = ">=14.2,<17" }, { name = "xenon", specifier = ">=0.9.3,<1" }, @@ -4130,11 +3986,11 @@ dev = [ { name = "ipywidgets", specifier = ">=8.1.5,<9" }, { name = "jupyterlab", specifier = ">=4.2,<5" }, { name = "licensecheck", specifier = ">=2025.1.0" }, - { name = "mypy", specifier = ">=1.11,<3" }, { name = "nbstripout", specifier = ">=0.8,<1" }, { name = "pre-commit", specifier = ">=3.8,<5" }, { name = "radon", specifier = ">=6.0.1,<7" }, { name = "ruff", specifier = ">=0.5,<1" }, + { name = "ty", specifier = ">=0.0.61" }, { name = "types-aiofiles", specifier = ">=24.1,<26" }, { name = "xenon", specifier = ">=0.9.3,<1" }, ] @@ -5362,8 +5218,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, - { name = "jeepney", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "cryptography" }, + { name = "jeepney" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ @@ -5823,6 +5679,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bb/4a/2e5583e544bc437d5e8e54b47db87430df9031b29b48d17f26d129fa60c0/trove_classifiers-2026.1.14.14-py3-none-any.whl", hash = "sha256:1f9553927f18d0513d8e5ff80ab8980b8202ce37ecae0e3274ed2ef11880e74d", size = 14197, upload-time = "2026-01-14T14:54:49.067Z" }, ] +[[package]] +name = "ty" +version = "0.0.61" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/63/6944925d0fe9a4bb9cc744e6c045a42bbd2ee4654c103190674577a36c3f/ty-0.0.61.tar.gz", hash = "sha256:acbf0d914cc7e2e57ccc440036af36114819e2a604a5ffb554e72e4ca7dd65a2", size = 6234957, upload-time = "2026-07-18T01:39:54.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/cf/044f31523e2768e3e64b0ca2ec32f70b3a731d4a2caa6ea110baf26e251c/ty-0.0.61-py3-none-linux_armv6l.whl", hash = "sha256:148779b8675eac93f40ec58bd70037fe67537117f20a23272264f8f136d41336", size = 11891448, upload-time = "2026-07-18T01:39:18.449Z" }, + { url = "https://files.pythonhosted.org/packages/d2/55/558cfe76b65d91d1854bbfac336020bd42fd887caa632d845d13c0c539eb/ty-0.0.61-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:08217382b3385808ee7288501ea3214b32631b08d1fd091ece6799b0c95264c5", size = 11602442, upload-time = "2026-07-18T01:39:20.914Z" }, + { url = "https://files.pythonhosted.org/packages/27/be/78c0ae6634cd606a68e5b46b338db427a48a1800c96a749b2d2f7a702e03/ty-0.0.61-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6d99c729011b47dec20e78a32ac9c8f6defd4cf62f7bb851bbccf70dde6cee50", size = 11125286, upload-time = "2026-07-18T01:39:22.893Z" }, + { url = "https://files.pythonhosted.org/packages/a4/18/a40793962f1b6337938ddb0bca7496b54e70879e23b4d2cc8dfd7e5d1af3/ty-0.0.61-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cda607978ae271b77e51c947663218bce635c3507e256865444b10c37cdb60d", size = 11663403, upload-time = "2026-07-18T01:39:25.017Z" }, + { url = "https://files.pythonhosted.org/packages/98/c1/7879244da5b30407dc368946d36be5024380073408b079f144ffe034030e/ty-0.0.61-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d78f160a0f9434d570cdcdbc4dafba1f6aac3c47a32f9f63995b3cb55ffe4b6", size = 11715250, upload-time = "2026-07-18T01:39:27.045Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/8a4637cd58abd37f315dd515e24c582986cb1bfdf2edc4786882f5a4f69a/ty-0.0.61-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09aeab4800b36e93e4ce918699004da642d74988cac920b7592a6a2b9be6611c", size = 12393876, upload-time = "2026-07-18T01:39:29.197Z" }, + { url = "https://files.pythonhosted.org/packages/27/4b/27e7c640b1272743503229aa17ae2167a538040c4716a2fa1777c2b34fea/ty-0.0.61-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dccc8136df44142a109953a168be17b4915c99876b047d0b6672c31dae939bdf", size = 12958187, upload-time = "2026-07-18T01:39:31.308Z" }, + { url = "https://files.pythonhosted.org/packages/3a/f5/70eaaefb6081fb0a8115cff66fbfaa20dafac8c646df2477adad95a59de2/ty-0.0.61-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:220760c2d13a887d027ee1093172c24ac35b6e634805329c93a30908ae4d3f5c", size = 12560101, upload-time = "2026-07-18T01:39:33.35Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/17bae3b6429b5c479dc6c1e344d34e1f79efbc27531f15f3ee5b5da63745/ty-0.0.61-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:effefbb89da7128d18059529d1c2ea390fe7f1f3882690d257ca2143d49a0c34", size = 12225389, upload-time = "2026-07-18T01:39:35.436Z" }, + { url = "https://files.pythonhosted.org/packages/d2/0e/2ac380ba20d6395542c8df1d6fa4f00e2aead784c2e6aaefa1e02ed0610c/ty-0.0.61-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ba8b28a5ef811d5bb6461e37d76110c06fd20487474865c323d3d18b08b972b2", size = 12548403, upload-time = "2026-07-18T01:39:37.556Z" }, + { url = "https://files.pythonhosted.org/packages/b0/e5/7da4b73e825e1a9808c26d68b0156e9a37aede1846191210dfffb8c64042/ty-0.0.61-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:88ecd6d9b05e8174b1860dac9bd3e188d6cef5702b0d3239fd9f94f6ac73a29d", size = 11621813, upload-time = "2026-07-18T01:39:39.919Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3c/5b58015e998cd0d89b17a463b6321421457d86d987574e8dac65ddfceba3/ty-0.0.61-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb0cdfe4c48542ffb9a1139825dfa3d4aae49e96e966682ef7da762ab97831ff", size = 11734101, upload-time = "2026-07-18T01:39:42.097Z" }, + { url = "https://files.pythonhosted.org/packages/a6/21/294f4cc819b7b12ed659fd860e5cdfbd592d4c768c8f23596685dbc43e6b/ty-0.0.61-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dff03873c0c3d0b44738f8b6d403b0756a31cf54c65136397df7624c6159b1f0", size = 11988401, upload-time = "2026-07-18T01:39:44.183Z" }, + { url = "https://files.pythonhosted.org/packages/2e/26/0f96f79fdac118521a9771e9eef3f9b3f447d647b2c77953e80a1715c7e8/ty-0.0.61-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a9210e80e3d41c1dfc751e9e8e0980272f475031fafd0fb0f48aee233c78da03", size = 12330624, upload-time = "2026-07-18T01:39:46.662Z" }, + { url = "https://files.pythonhosted.org/packages/e3/08/1e62d1bca5c0cebdc7a34db1f4b61557aab85961cedd56953dd2c32d3e66/ty-0.0.61-py3-none-win32.whl", hash = "sha256:e3e1fe06f49a5492a922a5df2739834aa5ee978c7dd10414119dc8755cc40c9c", size = 11313991, upload-time = "2026-07-18T01:39:48.761Z" }, + { url = "https://files.pythonhosted.org/packages/26/f1/d8e33b3aeb36b73d81ae34d10e46ec4abf506d68f4e0a1491a76a593dd42/ty-0.0.61-py3-none-win_amd64.whl", hash = "sha256:25f2291169e0298fcdbba1b1fea64f8207a6c1908dddef32346fd5e3e6ac9221", size = 12311717, upload-time = "2026-07-18T01:39:50.881Z" }, + { url = "https://files.pythonhosted.org/packages/e1/14/7caec26d93a943c0e7d15eb7374644508d08cbd387d112b722b12d14e044/ty-0.0.61-py3-none-win_arm64.whl", hash = "sha256:3e496f7698bc4b5bbb1eb66d8b5799ba87596d88d36604ca359083893fa2fc49", size = 11693485, upload-time = "2026-07-18T01:39:52.73Z" }, +] + [[package]] name = "typer" version = "0.25.1" From 14aa6b14d5344e44ce2cf3dab94cc1a07b1eb56a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:27:21 +0000 Subject: [PATCH 2/8] fix ty diagnostics after migration --- plugboard/library/sql_io.py | 20 ++++++++++++++------ tests/integration/test_tuner.py | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugboard/library/sql_io.py b/plugboard/library/sql_io.py index ea9c0010f..4e7387bb5 100644 --- a/plugboard/library/sql_io.py +++ b/plugboard/library/sql_io.py @@ -1,7 +1,7 @@ """Provides `SQLReader` and `SQLWriter` components to access SQL databases from Plugboard models.""" -import collections.abc as cabc from collections import defaultdict, deque +import collections.abc as cabc import typing as _t from sqlalchemy import MetaData, Table, insert, text @@ -42,9 +42,11 @@ def __init__( self._connection_string = connection_string self._query = query self._params = params or {} - self._reader: cabc.AsyncIterator[cabc.Sequence[Row[_t.Any]]] | cabc.Iterator[ - cabc.Sequence[Row[_t.Any]] - ] | None = None + self._reader: ( + cabc.AsyncIterator[cabc.Sequence[Row[_t.Any]]] + | cabc.Iterator[cabc.Sequence[Row[_t.Any]]] + | None + ) = None self._connect_args = connect_args or {} async def _run_query_async(self) -> cabc.AsyncIterator[cabc.Sequence[Row[_t.Any]]]: @@ -84,14 +86,19 @@ async def _fetch(self) -> cabc.Sequence[Row[_t.Any]]: if self._reader is None: try: self._reader = self._run_query_async() - return await self._reader.__anext__() + async_reader = self._reader + return await async_reader.__anext__() except InvalidRequestError: # Fall back on synchronous connection self._reader = self._run_query_sync() return next(self._reader) if isinstance(self._reader, cabc.AsyncIterator): - return await self._reader.__anext__() + async_reader = _t.cast( + cabc.AsyncIterator[cabc.Sequence[Row[_t.Any]]], + self._reader, + ) + return await async_reader.__anext__() return next(_t.cast(cabc.Iterator[cabc.Sequence[Row[_t.Any]]], self._reader)) async def _convert(self, data: _t.Sequence[Row]) -> dict[str, deque]: @@ -141,6 +148,7 @@ async def _save_rows_async(self, data: list[dict[str, _t.Any]]) -> None: raise RuntimeError("No async database connection available") async with self._engine.connect() as conn: if self._table is None: + def _load_table(sync_conn: Connection) -> Table: self._metadata.reflect(bind=sync_conn, only=[self._table_name]) return Table(self._table_name, self._metadata, autoload_with=sync_conn) diff --git a/tests/integration/test_tuner.py b/tests/integration/test_tuner.py index 2b144320e..82dff5d11 100644 --- a/tests/integration/test_tuner.py +++ b/tests/integration/test_tuner.py @@ -343,6 +343,7 @@ async def test_tune_with_constraint_objective_value(config: dict, ray_ctx: None) best_result = tuner.run( spec=process_spec, ) + assert not isinstance(best_result, list) result = tuner.result_grid # There must be no failed trials assert not any(t.error for t in result) From 3dd3dcc538f58123a79ac068a9c84a801910e0c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:33:14 +0000 Subject: [PATCH 3/8] test: make process type assertion ty-friendly --- tests/integration/test_component_decorator.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/integration/test_component_decorator.py b/tests/integration/test_component_decorator.py index a6db2a51e..87e29befe 100644 --- a/tests/integration/test_component_decorator.py +++ b/tests/integration/test_component_decorator.py @@ -142,10 +142,9 @@ async def test_process_builder_with_decorated_components( ) -> None: """Tests a process using components created with the component decorator executes correctly.""" iters = 10 - process_type = ( - "plugboard.process.LocalProcess" - if process_cls.__name__ == "LocalProcess" - else "plugboard.process.RayProcess" + process_type = _t.cast( + _t.Literal["plugboard.process.LocalProcess", "plugboard.process.RayProcess"], + f"{process_cls.__module__}.{process_cls.__name__}", ) process_spec = ProcessSpec( type=process_type, From 91768d8d674c115c5445cba1f81a71d3b2f7c30b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:34:38 +0000 Subject: [PATCH 4/8] docs: address ty migration review feedback --- plugboard/component/utils.py | 2 ++ plugboard/library/sql_io.py | 1 + plugboard/utils/ray.py | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugboard/component/utils.py b/plugboard/component/utils.py index b40a4af39..c291f06d1 100644 --- a/plugboard/component/utils.py +++ b/plugboard/component/utils.py @@ -12,6 +12,8 @@ class _ComponentFunction(_t.Protocol): + """Callable protocol for functions that can be wrapped as Plugboard components.""" + __name__: str __module__: str __doc__: str | None diff --git a/plugboard/library/sql_io.py b/plugboard/library/sql_io.py index 4e7387bb5..376eda328 100644 --- a/plugboard/library/sql_io.py +++ b/plugboard/library/sql_io.py @@ -150,6 +150,7 @@ async def _save_rows_async(self, data: list[dict[str, _t.Any]]) -> None: if self._table is None: def _load_table(sync_conn: Connection) -> Table: + """Reflect and load the target table within a sync SQLAlchemy connection.""" self._metadata.reflect(bind=sync_conn, only=[self._table_name]) return Table(self._table_name, self._metadata, autoload_with=sync_conn) diff --git a/plugboard/utils/ray.py b/plugboard/utils/ray.py index b84d298fe..6bd415938 100644 --- a/plugboard/utils/ray.py +++ b/plugboard/utils/ray.py @@ -31,7 +31,7 @@ def _call_with_name(func: _t.Callable, path: tuple[str, ...]) -> _t.Callable: # underlying function (which supports __signature__ assignment) rather than # the bound method object (which does not). wraps_target = getattr(func, "__func__", func) - func_name = getattr(func, "__name__", type(func).__name__) + func_name = getattr(func, "__name__", "") @wraps(wraps_target) def wrapper(self: _ActorWrapper, *args: _t.Any, **kwargs: _t.Any) -> _t.Callable: @@ -48,7 +48,7 @@ def _call_with_name_async(func: _t.Callable, path: tuple[str, ...]) -> _t.Callab # underlying function (which supports __signature__ assignment) rather than # the bound method object (which does not). wraps_target = getattr(func, "__func__", func) - func_name = getattr(func, "__name__", type(func).__name__) + func_name = getattr(func, "__name__", "") @wraps(wraps_target) async def wrapper(self: _ActorWrapper, *args: _t.Any, **kwargs: _t.Any) -> _t.Callable: From a2f0557d42f05ad956a5165b5ae4d0c7579b3989 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:36:05 +0000 Subject: [PATCH 5/8] fix review feedback on ty migration --- plugboard-schemas/plugboard_schemas/__init__.py | 5 ++++- plugboard/__init__.py | 5 ++++- plugboard/utils/logging.py | 6 ++++-- uv.lock | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/plugboard-schemas/plugboard_schemas/__init__.py b/plugboard-schemas/plugboard_schemas/__init__.py index 5928a087c..65e4bcade 100644 --- a/plugboard-schemas/plugboard_schemas/__init__.py +++ b/plugboard-schemas/plugboard_schemas/__init__.py @@ -53,7 +53,10 @@ ) -__version__ = version("plugboard-schemas") +_PACKAGE_NAME = __package__ or __name__.split(".")[0] + + +__version__ = version(_PACKAGE_NAME) __all__ = [ diff --git a/plugboard/__init__.py b/plugboard/__init__.py index e009248dc..831061edf 100644 --- a/plugboard/__init__.py +++ b/plugboard/__init__.py @@ -3,4 +3,7 @@ from importlib.metadata import version -__version__ = version("plugboard") +_PACKAGE_NAME = __package__ or __name__.split(".")[0] + + +__version__ = version(_PACKAGE_NAME) diff --git a/plugboard/utils/logging.py b/plugboard/utils/logging.py index 333b3b404..95866a585 100644 --- a/plugboard/utils/logging.py +++ b/plugboard/utils/logging.py @@ -1,5 +1,6 @@ """Provides logging utilities.""" +import importlib import logging import typing as _t @@ -11,10 +12,11 @@ def _is_ipython() -> bool: try: - from IPython import get_ipython + ipython = importlib.import_module("IPython") except ImportError: return False - return get_ipython() is not None + get_ipython = getattr(ipython, "get_ipython", None) + return callable(get_ipython) and get_ipython() is not None def _serialiser(obj: _t.Any, default: _t.Callable | None) -> bytes: diff --git a/uv.lock b/uv.lock index 3578e203c..5d37c48c5 100644 --- a/uv.lock +++ b/uv.lock @@ -5218,8 +5218,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography" }, - { name = "jeepney" }, + { name = "cryptography", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "jeepney", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ From 921b3a0ce5e40c5ba26ca4d8e4aafdfa261ad32a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:37:12 +0000 Subject: [PATCH 6/8] docs: clarify component function protocol --- plugboard/component/utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugboard/component/utils.py b/plugboard/component/utils.py index c291f06d1..9c0aa0e6f 100644 --- a/plugboard/component/utils.py +++ b/plugboard/component/utils.py @@ -12,7 +12,11 @@ class _ComponentFunction(_t.Protocol): - """Callable protocol for functions that can be wrapped as Plugboard components.""" + """Callable protocol for functions wrapped by `@component`. + + The decorator relies on the wrapped callable exposing `__name__`, `__module__`, and `__doc__` + so it can register the generated component class and build helpful generated documentation. + """ __name__: str __module__: str From 39687c9b77e2067275acf615f67586369219c71f Mon Sep 17 00:00:00 2001 From: Toby Coleman Date: Mon, 20 Jul 2026 10:13:47 +0100 Subject: [PATCH 7/8] Final updates from Claude session --- .devcontainer/devcontainer.json | 1 + .github/agents/lint.agent.md | 8 ++++---- .pre-commit-config.yaml | 4 ++-- pyproject.toml | 3 +++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c6d5c965b..fe4a88b26 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -25,6 +25,7 @@ "ms-python.python", "ms-toolsai.jupyter", "charliermarsh.ruff", + "astral-sh.ty", "GitHub.copilot", "GitHub.copilot-chat" ], diff --git a/.github/agents/lint.agent.md b/.github/agents/lint.agent.md index e30ee2431..205dbd9c2 100644 --- a/.github/agents/lint.agent.md +++ b/.github/agents/lint.agent.md @@ -7,7 +7,7 @@ model: ['GPT-5 mini (copilot)', 'GPT-4.1 (copilot)'] You are responsible for maintaining code quality in the Plugboard project by running linting tools and resolving any issues that arise. ## Your role: -- Run `ruff` to check for formatting and linting issues and `mypy` to check for type errors. +- Run `ruff` to check for formatting and linting issues and `ty` to check for type errors. - Review the output from these tools and identify any issues that need to be resolved. - Edit the code to fix any linting issues or type errors that are identified. - Ensure that all code is fully type-annotated and adheres to the project's coding standards. @@ -16,13 +16,13 @@ You are responsible for maintaining code quality in the Plugboard project by run ## Project knowledge: - The project uses `uv` for dependency management and running commands. -- Linting and formatting are handled by `ruff`, while static type checking is handled by `mypy`. -- `pyproject.toml` contains the settings for `ruff` and `mypy`. +- Linting and formatting are handled by `ruff`, while static type checking is handled by `ty`. +- `pyproject.toml` contains the settings for `ruff` and `ty`. ## Commands you can run: - Run `uv run ruff format` to reformat the code. - Run `uv run ruff check` to check for linting issues. -- Run `uv run mypy .` to check for type errors. +- Run `uv run ty check plugboard/ plugboard-schemas/plugboard_schemas/ tests/` to check for type errors. - Run `uv lock --check` to check that the uv lockfile is up to date. - Run `uv run xenon --max-absolute B --max-modules A --max-average A plugboard/` to check for code complexity. - Run `find . -name '*.ipynb' -not -path "./.venv/*" -exec uv run nbstripout --verify {} +` to check that Jupyter notebooks are stripped of output. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 19fc07c54..cef379380 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,8 +11,8 @@ repos: args: [ --fix ] # Run the formatter. - id: ruff-format -- repo: https://github.com/astral-sh/ty - rev: 0.0.61 +- repo: https://github.com/astral-sh/ty-pre-commit + rev: v0.0.61 hooks: - id: ty - repo: https://github.com/rubik/xenon diff --git a/pyproject.toml b/pyproject.toml index 5c30996ac..f79f6c4aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -149,6 +149,9 @@ sigterm = true [tool.ty] # Static type checking +[tool.ty.src] +exclude = ["docs", "examples"] + [tool.ty.analysis] replace-imports-with-any = [ "openai_responses.**", From b03c6e2bbe9942f2f36df499a3d8fbeb9068576f Mon Sep 17 00:00:00 2001 From: Toby Coleman Date: Wed, 19 Aug 2026 22:22:34 +0100 Subject: [PATCH 8/8] chore: align ty pre-commit rev with lockfile --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cef379380..b43b4bb63 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: # Run the formatter. - id: ruff-format - repo: https://github.com/astral-sh/ty-pre-commit - rev: v0.0.61 + rev: v0.0.73 hooks: - id: ty - repo: https://github.com/rubik/xenon