From e647c3dab0d81802baf3524aa821161256b99d29 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Fri, 22 Nov 2024 16:26:25 -0300 Subject: [PATCH 01/45] feat: Basic support for SCXML test suit --- conftest.py | 31 ++++- pyproject.toml | 18 ++- statemachine/callbacks.py | 11 +- statemachine/dispatcher.py | 2 +- statemachine/io/__init__.py | 64 +++++++++++ statemachine/io/scxml.py | 126 +++++++++++++++++++++ statemachine/spec_parser.py | 25 +++- tests/test_spec_parser.py | 57 ++++++++-- tests/w3c_tests/__init__.py | 0 tests/w3c_tests/conftest.py | 49 ++++++++ tests/w3c_tests/test_testcases.py | 12 ++ tests/w3c_tests/testcases/test144-ok.scxml | 33 ++++++ tests/w3c_tests/testcases/test145.scxml | 31 +++++ tests/w3c_tests/testcases/test147.scxml | 36 ++++++ uv.lock | 82 ++++++++++---- 15 files changed, 534 insertions(+), 43 deletions(-) create mode 100644 statemachine/io/__init__.py create mode 100644 statemachine/io/scxml.py create mode 100644 tests/w3c_tests/__init__.py create mode 100644 tests/w3c_tests/conftest.py create mode 100644 tests/w3c_tests/test_testcases.py create mode 100644 tests/w3c_tests/testcases/test144-ok.scxml create mode 100644 tests/w3c_tests/testcases/test145.scxml create mode 100644 tests/w3c_tests/testcases/test147.scxml diff --git a/conftest.py b/conftest.py index 4c2c0c63..978d6d03 100644 --- a/conftest.py +++ b/conftest.py @@ -6,8 +6,7 @@ @pytest.fixture(autouse=True, scope="session") def add_doctest_context(doctest_namespace): # noqa: PT004 - from statemachine import State - from statemachine import StateMachine + from statemachine import State, StateMachine from statemachine.utils import run_async_from_sync class ContribAsyncio: @@ -43,3 +42,31 @@ def has_dot_installed(): def requires_dot_installed(request, has_dot_installed): if not has_dot_installed: pytest.skip(f"Test {request.node.nodeid} requires 'dot' that is not installed.") + + +# @pytest.fixture(autouse=True, scope="module") +# def mock_dot_write(request): +# """ +# This fixture avoids updating files while executing tests +# """ + +# def open_effect( +# filename, +# mode="r", +# *args, +# **kwargs, +# ): +# if mode in ("r", "rt", "rb"): +# return open(filename, mode, *args, **kwargs) +# elif filename.startswith("/tmp/"): +# return open(filename, mode, *args, **kwargs) +# elif "b" in mode: +# return io.BytesIO() +# else: +# return io.StringIO() + +# # using global mock instead of the fixture mocker due to the ScopeMismatch +# # this fixture is module scoped and mocker is function scoped +# with mock.patch("pydot.core.io.open", spec=True) as m: +# m.side_effect = open_effect +# yield m diff --git a/pyproject.toml b/pyproject.toml index b324b715..8cf54ca5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ dev = [ "pytest-benchmark >=4.0.0", "pytest-asyncio", "pydot", + "pydot", "django >=5.0.8; python_version >='3.10'", "pytest-django >=4.8.0; python_version >'3.8'", "Sphinx; python_version >'3.8'", @@ -52,7 +53,7 @@ dev = [ "sphinx-autobuild; python_version >'3.8'", "furo >=2024.5.6; python_version >'3.8'", "sphinx-copybutton >=0.5.2; python_version >'3.8'", - "pdbr>=0.8.9; python_version >'3.8'", + "pdbr>=0.8.9; python_version >='3.8'", ] [build-system] @@ -78,6 +79,21 @@ addopts = [ "--benchmark-group-by=name", "--pdbcls=pdbr:RichPdb", ] +addopts = [ + "--ignore=docs/conf.py", + "--ignore=docs/auto_examples/", + "--ignore=docs/_build/", + "--ignore=tests/examples/", + "--cov", + "--cov-config", + ".coveragerc", + "--doctest-glob=*.md", + "--doctest-modules", + "--doctest-continue-on-failure", + "--benchmark-autosave", + "--benchmark-group-by=name", + "--pdbcls=pdbr:RichPdb", +] doctest_optionflags = "ELLIPSIS IGNORE_EXCEPTION_DETAIL NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL" asyncio_mode = "auto" markers = ["""slow: marks tests as slow (deselect with '-m "not slow"')"""] diff --git a/statemachine/callbacks.py b/statemachine/callbacks.py index 0a6613c1..7286bb63 100644 --- a/statemachine/callbacks.py +++ b/statemachine/callbacks.py @@ -5,6 +5,7 @@ from enum import IntEnum from enum import IntFlag from enum import auto +from functools import partial from inspect import isawaitable from typing import TYPE_CHECKING from typing import Callable @@ -89,10 +90,10 @@ def __init__( self.attr_name: str = func and func.fget and func.fget.__name__ or "" elif callable(func): self.reference = SpecReference.CALLABLE - self.is_bounded = hasattr(func, "__self__") - self.attr_name = ( - func.__name__ if not self.is_event or self.is_bounded else f"_{func.__name__}_" - ) + is_partial = isinstance(func, partial) + self.is_bounded = is_partial or hasattr(func, "__self__") + name = func.func.__name__ if is_partial else func.__name__ + self.attr_name = name if not self.is_event or self.is_bounded else f"_{name}_" if not self.is_bounded: func.attr_name = self.attr_name func.is_event = is_event @@ -110,7 +111,7 @@ def __repr__(self): return f"{type(self).__name__}({self.func!r}, is_convention={self.is_convention!r})" def __str__(self): - name = getattr(self.func, "__name__", self.func) + name = self.attr_name if self.expected_value is False: name = f"!{name}" return name diff --git a/statemachine/dispatcher.py b/statemachine/dispatcher.py index e8f24e11..e465fff0 100644 --- a/statemachine/dispatcher.py +++ b/statemachine/dispatcher.py @@ -166,7 +166,7 @@ def _search_callable(self, spec): yield listener.build_key(spec.attr_name), partial(callable_method, func) return - yield f"{spec.attr_name}@None", partial(callable_method, spec.func) + yield f"{spec.attr_name}-{id(spec.func)}@None", partial(callable_method, spec.func) def search_name(self, name): for listener in self.items: diff --git a/statemachine/io/__init__.py b/statemachine/io/__init__.py new file mode 100644 index 00000000..4f43491c --- /dev/null +++ b/statemachine/io/__init__.py @@ -0,0 +1,64 @@ +from typing import Dict + +from ..factory import StateMachineMetaclass +from ..state import State +from ..statemachine import StateMachine +from ..transition_list import TransitionList + + +def create_machine_class_from_definition( + name: str, definition: dict, **extra_kwargs +) -> StateMachine: + """ + Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass. + + Example usage with a traffic light machine: + + >>> machine = create_machine_class_from_definition( + ... "TrafficLightMachine", + ... { + ... "states": { + ... "green": {"initial": True}, + ... "yellow": {}, + ... "red": {}, + ... }, + ... "events": { + ... "change": [ + ... {"from": "green", "to": "yellow"}, + ... {"from": "yellow", "to": "red"}, + ... {"from": "red", "to": "green"}, + ... ] + ... }, + ... } + ... ) + + """ + + states_instances = { + state_id: State(**state_kwargs) for state_id, state_kwargs in definition["states"].items() + } + + events: Dict[str, TransitionList] = {} + for event_name, transitions in definition["events"].items(): + for transition_data in transitions: + source = states_instances[transition_data["from"]] + target = states_instances[transition_data["to"]] + + transition = source.to( + target, + event=event_name, + cond=transition_data.get("cond"), + unless=transition_data.get("unless"), + on=transition_data.get("on"), + before=transition_data.get("before"), + after=transition_data.get("after"), + ) + + if event_name in events: + events[event_name] |= transition + elif event_name is not None: + events[event_name] = transition + + attrs_mapper = {**extra_kwargs, **states_instances, **events} + + return StateMachineMetaclass(name, (StateMachine,), attrs_mapper) # type: ignore[return-value] diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py new file mode 100644 index 00000000..66414bfd --- /dev/null +++ b/statemachine/io/scxml.py @@ -0,0 +1,126 @@ +""" +Simple SCXML parser that converts SCXML documents to state machine definitions. +""" + +import xml.etree.ElementTree as ET +from functools import partial +from typing import Any +from typing import Dict +from typing import List + +from statemachine.statemachine import StateMachine + + +def send_event(machine: StateMachine, event_to_send: str) -> None: + machine.send(event_to_send) + + +def assign(model, location, expr): + pass + + +def strip_namespaces(tree): + """Remove all namespaces from tags and attributes in place. + + Leaves only the local names in the subtree. + """ + for el in tree.iter(): + tag = el.tag + if tag and isinstance(tag, str) and tag[0] == "{": + el.tag = tag.partition("}")[2] + attrib = el.attrib + if attrib: + for name, value in list(attrib.items()): + if name and isinstance(name, str) and name[0] == "{": + del attrib[name] + attrib[name.partition("}")[2]] = value + + +def parse_scxml(scxml_content: str) -> Dict[str, Any]: # noqa: C901 + """ + Parse SCXML content and return a dictionary definition compatible with + create_machine_class_from_definition. + + The returned dictionary has the format: + { + "states": { + "state_id": {"initial": True}, + ... + }, + "events": { + "event_name": [ + {"from": "source_state", "to": "target_state"}, + ... + ] + } + } + """ + # Parse XML content + root = ET.fromstring(scxml_content) + strip_namespaces(root) + + # Find the scxml element (it might be the root or a child) + scxml = root if "scxml" in root.tag else root.find(".//scxml") + if scxml is None: + raise ValueError("No scxml element found in document") + + # Get initial state from scxml element + initial_state = scxml.get("initial") + + # Build states dictionary + states = {} + events: Dict[str, List[Dict[str, str]]] = {} + + def _parse_state(state_elem, final=False): # noqa: C901 + state_id = state_elem.get("id") + if not state_id: + raise ValueError("All states must have an id") + + # Mark as initial if specified + states[state_id] = {"initial": state_id == initial_state, "final": final} + + # Process transitions + for trans_elem in state_elem.findall("transition"): + event = trans_elem.get("event") or None + target = trans_elem.get("target") + + if target: + if event not in events: + events[event] = [] + + if target not in states: + states[target] = {} + + events[event].append( + { + "from": state_id, + "to": target, + } + ) + + for onentry_elem in state_elem.findall("onentry"): + for raise_elem in onentry_elem.findall("raise"): + event = raise_elem.get("event") + if event: + state = states[state_id] + if "enter" not in state: + state["enter"] = [] + state["enter"].append(partial(send_event, event_to_send=event)) + + # First pass: collect all states and mark initial + for state_elem in scxml.findall(".//state"): + _parse_state(state_elem) + + # Second pass: collect final states + for state_elem in scxml.findall(".//final"): + _parse_state(state_elem, final=True) + + # If no initial state was specified, mark the first state as initial + if not initial_state and states: + first_state = next(iter(states)) + states[first_state]["initial"] = True + + return { + "states": states, + "events": events, + } diff --git a/statemachine/spec_parser.py b/statemachine/spec_parser.py index 7596c083..f76419a5 100644 --- a/statemachine/spec_parser.py +++ b/statemachine/spec_parser.py @@ -51,6 +51,23 @@ def decorated(*args, **kwargs) -> bool: return decorated +def build_custom_operator(operator) -> Callable: + def custom_comparator(left: Callable, right: Callable) -> Callable: + def decorated(*args, **kwargs) -> bool: + return bool(operator(left(*args, **kwargs), right(*args, **kwargs))) + + return decorated + + return custom_comparator + + +def build_constant(constant) -> Callable: + def decorated(*args, **kwargs): + return constant + + return decorated + + def custom_or(left: Callable, right: Callable) -> Callable: def decorated(*args, **kwargs) -> bool: return left(*args, **kwargs) or right(*args, **kwargs) # type: ignore[no-any-return] @@ -118,9 +135,13 @@ def build_expression(node, variable_hook, operator_mapping): # noqa: C901 node, ast.NameConstant ): # pragma: no cover | python3.7 return build_constant(node.value) - elif hasattr(ast, "Str") and isinstance(node, ast.Str): # pragma: no cover | python3.7 + elif hasattr(ast, "Str") and isinstance( + node, ast.Str + ): # pragma: no cover | python3.7 return build_constant(node.s) - elif hasattr(ast, "Num") and isinstance(node, ast.Num): # pragma: no cover | python3.7 + elif hasattr(ast, "Num") and isinstance( + node, ast.Num + ): # pragma: no cover | python3.7 return build_constant(node.n) else: raise ValueError(f"Unsupported expression structure: {node.__class__.__name__}") diff --git a/tests/test_spec_parser.py b/tests/test_spec_parser.py index ff12fac4..1272e990 100644 --- a/tests/test_spec_parser.py +++ b/tests/test_spec_parser.py @@ -2,8 +2,7 @@ import pytest -from statemachine.spec_parser import operator_mapping -from statemachine.spec_parser import parse_boolean_expr +from statemachine.spec_parser import operator_mapping, parse_boolean_expr logger = logging.getLogger(__name__) DEBUG = logging.DEBUG @@ -41,7 +40,11 @@ def decorated(*args, **kwargs): [ ("frodo_has_ring", True, ["frodo_has_ring"]), ("frodo_has_ring or sauron_alive", True, ["frodo_has_ring"]), - ("frodo_has_ring and gandalf_present", True, ["frodo_has_ring", "gandalf_present"]), + ( + "frodo_has_ring and gandalf_present", + True, + ["frodo_has_ring", "gandalf_present"], + ), ("sauron_alive", False, ["sauron_alive"]), ("not sauron_alive", True, ["sauron_alive"]), ( @@ -49,8 +52,16 @@ def decorated(*args, **kwargs): True, ["frodo_has_ring", "gandalf_present"], ), - ("not sauron_alive and orc_army_ready", False, ["sauron_alive", "orc_army_ready"]), - ("not (not sauron_alive and orc_army_ready)", True, ["sauron_alive", "orc_army_ready"]), + ( + "not sauron_alive and orc_army_ready", + False, + ["sauron_alive", "orc_army_ready"], + ), + ( + "not (not sauron_alive and orc_army_ready)", + True, + ["sauron_alive", "orc_army_ready"], + ), ( "(frodo_has_ring and sam_is_loyal) or (not sauron_alive and orc_army_ready)", True, @@ -63,10 +74,26 @@ def decorated(*args, **kwargs): ), ("not (not frodo_has_ring)", True, ["frodo_has_ring"]), ("!(!frodo_has_ring)", True, ["frodo_has_ring"]), - ("frodo_has_ring and orc_army_ready", False, ["frodo_has_ring", "orc_army_ready"]), - ("frodo_has_ring ^ orc_army_ready", False, ["frodo_has_ring", "orc_army_ready"]), - ("frodo_has_ring and not orc_army_ready", True, ["frodo_has_ring", "orc_army_ready"]), - ("frodo_has_ring ^ !orc_army_ready", True, ["frodo_has_ring", "orc_army_ready"]), + ( + "frodo_has_ring and orc_army_ready", + False, + ["frodo_has_ring", "orc_army_ready"], + ), + ( + "frodo_has_ring ^ orc_army_ready", + False, + ["frodo_has_ring", "orc_army_ready"], + ), + ( + "frodo_has_ring and not orc_army_ready", + True, + ["frodo_has_ring", "orc_army_ready"], + ), + ( + "frodo_has_ring ^ !orc_army_ready", + True, + ["frodo_has_ring", "orc_army_ready"], + ), ( "frodo_has_ring and (sam_is_loyal or (gandalf_present and not sauron_alive))", True, @@ -89,7 +116,11 @@ def decorated(*args, **kwargs): True, ["orc_army_ready", "frodo_has_ring", "gandalf_present"], ), - ("orc_army_ready and (frodo_has_ring and gandalf_present)", False, ["orc_army_ready"]), + ( + "orc_army_ready and (frodo_has_ring and gandalf_present)", + False, + ["orc_army_ready"], + ), ( "!orc_army_ready and (frodo_has_ring and gandalf_present)", True, @@ -146,7 +177,8 @@ def test_expressions(expression, expected, caplog, hooks_called): if hooks_called: assert caplog.record_tuples == [ - ("tests.test_spec_parser", DEBUG, f"variable_hook({hook})") for hook in hooks_called + ("tests.test_spec_parser", DEBUG, f"variable_hook({hook})") + for hook in hooks_called ] @@ -257,5 +289,6 @@ def test_should_evaluate_values_only_once(expression, expected, caplog, hooks_ca if hooks_called: assert caplog.record_tuples == [ - ("tests.test_spec_parser", DEBUG, f"variable_hook({hook})") for hook in hooks_called + ("tests.test_spec_parser", DEBUG, f"variable_hook({hook})") + for hook in hooks_called ] diff --git a/tests/w3c_tests/__init__.py b/tests/w3c_tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/w3c_tests/conftest.py b/tests/w3c_tests/conftest.py new file mode 100644 index 00000000..51c7fcde --- /dev/null +++ b/tests/w3c_tests/conftest.py @@ -0,0 +1,49 @@ +from pathlib import Path + +import pytest + +CURRENT_DIR = Path(__file__).parent +TESTCASES_DIR = CURRENT_DIR / "testcases" +SUPPORTED_EXTENSIONS = "scxml" + + +@pytest.fixture() +def sm_class(testcase_path: Path): + """ + Construct a StateMachine class from the SCXML file + """ + from statemachine.io import create_machine_class_from_definition + from statemachine.io.scxml import parse_scxml + + # Read SCXML content + scxml_content = testcase_path.read_text() + + # Parse SCXML into dictionary format + definition = parse_scxml(scxml_content) + + # Create state machine class + try: + return create_machine_class_from_definition("SCXMLStateMachine", definition) + except Exception as e: + raise Exception( + f"Failed to create state machine class: {e} from definition: {definition}" + ) from e + + +def pytest_generate_tests(metafunc): + if "testcase_path" not in metafunc.fixturenames: + return + + fail_marks = [pytest.mark.xfail] + + metafunc.parametrize( + "testcase_path", + [ + pytest.param( + testcase_path, + id=str(testcase_path.name), + marks=fail_marks if "ok" not in testcase_path.name else [], + ) + for testcase_path in TESTCASES_DIR.glob("**/*.scxml") + ], + ) diff --git a/tests/w3c_tests/test_testcases.py b/tests/w3c_tests/test_testcases.py new file mode 100644 index 00000000..7734a22d --- /dev/null +++ b/tests/w3c_tests/test_testcases.py @@ -0,0 +1,12 @@ +from statemachine import StateMachine + +""" +Test cases as defined by W3C SCXML Test Suite +""" + + +def test_usecase(testcase_path, sm_class): + # sm._graph().write_png(f"{testcase_path.name}.png") + sm = sm_class() + assert isinstance(sm, StateMachine) + assert sm.current_state.id == "pass" diff --git a/tests/w3c_tests/testcases/test144-ok.scxml b/tests/w3c_tests/testcases/test144-ok.scxml new file mode 100644 index 00000000..482ca62e --- /dev/null +++ b/tests/w3c_tests/testcases/test144-ok.scxml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test145.scxml b/tests/w3c_tests/testcases/test145.scxml new file mode 100644 index 00000000..905b1cc1 --- /dev/null +++ b/tests/w3c_tests/testcases/test145.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test147.scxml b/tests/w3c_tests/testcases/test147.scxml new file mode 100644 index 00000000..bd76de4f --- /dev/null +++ b/tests/w3c_tests/testcases/test147.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uv.lock b/uv.lock index 6bc20dba..9f04324f 100644 --- a/uv.lock +++ b/uv.lock @@ -1,7 +1,8 @@ version = 1 requires-python = ">=3.7" resolution-markers = [ - "python_full_version < '3.9'", + "python_full_version < '3.8'", + "python_full_version == '3.8.*'", "python_full_version == '3.9.*'", "python_full_version == '3.10.*'", "python_full_version >= '3.11'", @@ -215,6 +216,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] +[[package]] +name = "commonmark" +version = "0.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/48/a60f593447e8f0894ebb7f6e6c1f25dafc5e89c5879fdc9360ae93ff83f0/commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", size = 95764 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/92/dfd892312d822f36c55366118b95d914e5f16de11044a27cf10a7d71bbbf/commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9", size = 51068 }, +] + [[package]] name = "coverage" version = "7.2.7" @@ -343,7 +353,7 @@ version = "2024.8.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "beautifulsoup4", marker = "python_full_version >= '3.9'" }, - { name = "pygments", marker = "python_full_version >= '3.9'" }, + { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "sphinx", marker = "python_full_version >= '3.9'" }, { name = "sphinx-basic-ng", marker = "python_full_version >= '3.9'" }, ] @@ -394,7 +404,7 @@ version = "6.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.8'" }, - { name = "zipp", marker = "python_full_version < '3.10'" }, + { name = "zipp", marker = "python_full_version < '3.8' or python_full_version == '3.9.*'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } wheels = [ @@ -611,8 +621,8 @@ name = "pdbr" version = "0.8.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pyreadline3", marker = "python_full_version >= '3.9' and sys_platform == 'win32'" }, - { name = "rich", marker = "python_full_version >= '3.9'" }, + { name = "pyreadline3", marker = "python_full_version >= '3.8' and sys_platform == 'win32'" }, + { name = "rich", marker = "python_full_version >= '3.8'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/29/1d/40420fda7c53fd071d8f62dcdb550c9f82fee54c2fda6842337890d87334/pdbr-0.8.9.tar.gz", hash = "sha256:3e0e1fb78761402bcfc0713a9c73acc2f639406b1b8da7233c442b965eee009d", size = 15942 } wheels = [ @@ -718,7 +728,8 @@ name = "pluggy" version = "1.2.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.9'", + "python_full_version < '3.8'", + "python_full_version == '3.8.*'", "python_full_version == '3.9.*'", ] dependencies = [ @@ -780,10 +791,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/90/c9b51f3cdff89cd8f93382060330f43d1af098a6624cff439e700791e922/pydot-2.0.0-py3-none-any.whl", hash = "sha256:408a47913ea7bd5d2d34b274144880c1310c4aee901f353cf21fe2e526a4ea28", size = 22675 }, ] +[[package]] +name = "pygments" +version = "2.17.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.8.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/55/59/8bccf4157baf25e4aa5a0bb7fa3ba8600907de105ebc22b0c78cfbf6f565/pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367", size = 4827772 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", size = 1179756 }, +] + [[package]] name = "pygments" version = "2.18.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.9.*'", + "python_full_version == '3.10.*'", + "python_full_version >= '3.11'", +] sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } wheels = [ { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 }, @@ -807,12 +835,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 }, ] +[[package]] +name = "pyreadline3" +version = "3.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 }, +] + [[package]] name = "pytest" version = "7.4.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.9'", + "python_full_version < '3.8'", + "python_full_version == '3.8.*'", "python_full_version == '3.9.*'", ] dependencies = [ @@ -869,7 +907,8 @@ name = "pytest-benchmark" version = "4.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.9'", + "python_full_version < '3.8'", + "python_full_version == '3.8.*'", "python_full_version == '3.9.*'", ] dependencies = [ @@ -969,10 +1008,11 @@ dev = [ { name = "furo", marker = "python_full_version >= '3.9'" }, { name = "mypy" }, { name = "myst-parser", marker = "python_full_version >= '3.9'" }, - { name = "pdbr", marker = "python_full_version >= '3.9'" }, + { name = "pdbr", marker = "python_full_version >= '3.8'" }, { name = "pillow", marker = "python_full_version >= '3.9'" }, { name = "pre-commit" }, { name = "pydot" }, + { name = "pydot" }, { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytest-asyncio" }, @@ -998,10 +1038,11 @@ dev = [ { name = "furo", marker = "python_full_version >= '3.9'", specifier = ">=2024.5.6" }, { name = "mypy" }, { name = "myst-parser", marker = "python_full_version >= '3.9'" }, - { name = "pdbr", marker = "python_full_version >= '3.9'", specifier = ">=0.8.9" }, + { name = "pdbr", marker = "python_full_version >= '3.8'", specifier = ">=0.8.9" }, { name = "pillow", marker = "python_full_version >= '3.9'" }, { name = "pre-commit" }, { name = "pydot" }, + { name = "pydot" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-benchmark", specifier = ">=4.0.0" }, @@ -1085,16 +1126,17 @@ wheels = [ [[package]] name = "rich" -version = "13.9.4" +version = "10.16.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown-it-py", marker = "python_full_version >= '3.9'" }, - { name = "pygments", marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "colorama", marker = "python_full_version >= '3.8'" }, + { name = "commonmark", marker = "python_full_version >= '3.8'" }, + { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, + { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +sdist = { url = "https://files.pythonhosted.org/packages/74/c3/e55ebdd66540503cee29cd3bb18a90bcfd5587a0cf3680173c368be56093/rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b", size = 197585 } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, + { url = "https://files.pythonhosted.org/packages/0a/0d/58939059015dce00122b008c3edccbb68f0767126020c939116e6d764cd7/rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03", size = 214400 }, ] [[package]] @@ -1162,7 +1204,7 @@ dependencies = [ { name = "importlib-metadata", marker = "python_full_version == '3.9.*'" }, { name = "jinja2", marker = "python_full_version >= '3.9'" }, { name = "packaging", marker = "python_full_version >= '3.9'" }, - { name = "pygments", marker = "python_full_version >= '3.9'" }, + { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "requests", marker = "python_full_version >= '3.9'" }, { name = "snowballstemmer", marker = "python_full_version >= '3.9'" }, { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.9'" }, @@ -1288,11 +1330,11 @@ wheels = [ [[package]] name = "sqlparse" -version = "0.5.1" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/82/dfa23ec2cbed08a801deab02fe7c904bfb00765256b155941d789a338c68/sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e", size = 84502 } +sdist = { url = "https://files.pythonhosted.org/packages/65/16/10f170ec641ed852611b6c9441b23d10b5702ab5288371feab3d36de2574/sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c", size = 72383 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/a5/b2860373aa8de1e626b2bdfdd6df4355f0565b47e51f7d0c54fe70faf8fe/sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4", size = 44156 }, + { url = "https://files.pythonhosted.org/packages/98/5a/66d7c9305baa9f11857f247d4ba761402cea75db6058ff850ed7128957b7/sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3", size = 41183 }, ] [[package]] From 067d4d80c0eab22c8de21f237c415f70faef1b6d Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Fri, 22 Nov 2024 19:26:29 -0300 Subject: [PATCH 02/45] feat: Support for onentry/raise/assign/log/if/elseif/else elements; When entering a top level final state the SM terminates --- statemachine/engines/base.py | 4 + statemachine/engines/sync.py | 8 +- statemachine/io/__init__.py | 126 +++++----- statemachine/io/scxml.py | 217 ++++++++++++++++-- statemachine/statemachine.py | 4 + tests/w3c_tests/conftest.py | 2 +- .../{test147.scxml => test147-ok.scxml} | 0 tests/w3c_tests/testcases/test148.scxml | 36 +++ 8 files changed, 316 insertions(+), 81 deletions(-) rename tests/w3c_tests/testcases/{test147.scxml => test147-ok.scxml} (100%) create mode 100644 tests/w3c_tests/testcases/test148.scxml diff --git a/statemachine/engines/base.py b/statemachine/engines/base.py index 0aa2f131..bb010599 100644 --- a/statemachine/engines/base.py +++ b/statemachine/engines/base.py @@ -5,6 +5,7 @@ from ..event import BoundEvent from ..event_data import TriggerData +from ..exceptions import TransitionNotAllowed from ..state import State from ..transition import Transition @@ -19,9 +20,12 @@ def __init__(self, sm: "StateMachine", rtc: bool = True): self._sentinel = object() self._rtc = rtc self._processing = Lock() + self._running = True def put(self, trigger_data: TriggerData): """Put the trigger on the queue without blocking the caller.""" + if not self._running and not self.sm.allow_event_without_transition: + raise TransitionNotAllowed(trigger_data.event, self.sm.current_state) self._external_queue.append(trigger_data) def start(self): diff --git a/statemachine/engines/sync.py b/statemachine/engines/sync.py index 4400cd08..b6de604b 100644 --- a/statemachine/engines/sync.py +++ b/statemachine/engines/sync.py @@ -61,7 +61,7 @@ def processing_loop(self): first_result = self._sentinel try: # Execute the triggers in the queue in FIFO order until the queue is empty - while self._external_queue: + while self._running and self._external_queue: trigger_data = self._external_queue.popleft() try: result = self._trigger(trigger_data) @@ -99,7 +99,7 @@ def _trigger(self, trigger_data: TriggerData): return result if executed else None - def _activate(self, trigger_data: TriggerData, transition: "Transition"): + def _activate(self, trigger_data: TriggerData, transition: "Transition"): # noqa: C901 event_data = EventData(trigger_data=trigger_data, transition=transition) args, kwargs = event_data.args, event_data.extended_kwargs @@ -124,6 +124,10 @@ def _activate(self, trigger_data: TriggerData, transition: "Transition"): self.sm._callbacks.call(target.enter.key, *args, **kwargs) self.sm._callbacks.call(transition.after.key, *args, **kwargs) + if target.final: + self._external_queue.clear() + self._running = False + if len(result) == 0: result = None elif len(result) == 1: diff --git a/statemachine/io/__init__.py b/statemachine/io/__init__.py index 4f43491c..060478ac 100644 --- a/statemachine/io/__init__.py +++ b/statemachine/io/__init__.py @@ -1,64 +1,62 @@ -from typing import Dict - -from ..factory import StateMachineMetaclass -from ..state import State -from ..statemachine import StateMachine -from ..transition_list import TransitionList - - -def create_machine_class_from_definition( - name: str, definition: dict, **extra_kwargs -) -> StateMachine: - """ - Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass. - - Example usage with a traffic light machine: - - >>> machine = create_machine_class_from_definition( - ... "TrafficLightMachine", - ... { - ... "states": { - ... "green": {"initial": True}, - ... "yellow": {}, - ... "red": {}, - ... }, - ... "events": { - ... "change": [ - ... {"from": "green", "to": "yellow"}, - ... {"from": "yellow", "to": "red"}, - ... {"from": "red", "to": "green"}, - ... ] - ... }, - ... } - ... ) - - """ - - states_instances = { - state_id: State(**state_kwargs) for state_id, state_kwargs in definition["states"].items() - } - - events: Dict[str, TransitionList] = {} - for event_name, transitions in definition["events"].items(): - for transition_data in transitions: - source = states_instances[transition_data["from"]] - target = states_instances[transition_data["to"]] - - transition = source.to( - target, - event=event_name, - cond=transition_data.get("cond"), - unless=transition_data.get("unless"), - on=transition_data.get("on"), - before=transition_data.get("before"), - after=transition_data.get("after"), - ) - - if event_name in events: - events[event_name] |= transition - elif event_name is not None: - events[event_name] = transition - - attrs_mapper = {**extra_kwargs, **states_instances, **events} - - return StateMachineMetaclass(name, (StateMachine,), attrs_mapper) # type: ignore[return-value] +from typing import Dict + +from ..factory import StateMachineMetaclass +from ..state import State +from ..statemachine import StateMachine +from ..transition_list import TransitionList + + +def create_machine_class_from_definition(name: str, definition: dict) -> StateMachine: + """ + Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass. + + Example usage with a traffic light machine: + + >>> machine = create_machine_class_from_definition( + ... "TrafficLightMachine", + ... { + ... "states": { + ... "green": {"initial": True}, + ... "yellow": {}, + ... "red": {}, + ... }, + ... "events": { + ... "change": [ + ... {"from": "green", "to": "yellow"}, + ... {"from": "yellow", "to": "red"}, + ... {"from": "red", "to": "green"}, + ... ] + ... }, + ... } + ... ) + + """ + + states_instances = { + state_id: State(**state_kwargs) + for state_id, state_kwargs in definition.pop("states").items() + } + + events: Dict[str, TransitionList] = {} + for event_name, transitions in definition.pop("events").items(): + for transition_data in transitions: + source = states_instances[transition_data["from"]] + target = states_instances[transition_data["to"]] + + transition = source.to( + target, + event=event_name, + cond=transition_data.get("cond"), + unless=transition_data.get("unless"), + on=transition_data.get("on"), + before=transition_data.get("before"), + after=transition_data.get("after"), + ) + + if event_name in events: + events[event_name] |= transition + elif event_name is not None: + events[event_name] = transition + + attrs_mapper = {**definition, **states_instances, **events} + return StateMachineMetaclass(name, (StateMachine,), attrs_mapper) # type: ignore[return-value] diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index 66414bfd..317a6286 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -2,12 +2,13 @@ Simple SCXML parser that converts SCXML documents to state machine definitions. """ +import re import xml.etree.ElementTree as ET -from functools import partial from typing import Any from typing import Dict from typing import List +from statemachine.model import Model from statemachine.statemachine import StateMachine @@ -15,8 +16,192 @@ def send_event(machine: StateMachine, event_to_send: str) -> None: machine.send(event_to_send) -def assign(model, location, expr): - pass +def parse_onentry(element): + """Parses the XML into a callable.""" + actions = [parse_element(child) for child in element] + + def execute_block(*args, **kwargs): + for action in actions: + action(*args, **kwargs) + + return execute_block + + +def parse_element(element): + """Parses an individual XML element into a callable.""" + tag = element.tag + if tag == "raise": + return parse_raise(element) + elif tag == "assign": + return parse_assign(element) + elif tag == "log": + return parse_log(element) + elif tag == "if": + return parse_if(element) + else: + raise ValueError(f"Unknown tag: {tag}") + + +def parse_raise(element): + """Parses the element into a callable.""" + event = element.attrib["event"] + + def raise_action(*args, **kwargs): + machine = kwargs["machine"] + machine.send(event) + + return raise_action + + +def parse_log(element): + """Parses the element into a callable.""" + label = element.attrib["label"] + expr = element.attrib["expr"] + + def raise_log(*args, **kwargs): + machine = kwargs["machine"] + kwargs.update(machine.model.__dict__) + value = eval(expr, {}, kwargs) + print(f"{label}: {value!r}") + + return raise_log + + +def parse_assign(element): + """Parses the element into a callable.""" + location = element.attrib["location"] + expr = element.attrib["expr"] + + def assign_action(*args, **kwargs): + machine = kwargs["machine"] + value = eval(expr, {}, {"machine": machine, **machine.model.__dict__}) + setattr(machine.model, location, value) + + return assign_action + + +def _normalize_cond(cond: "str | None") -> "str | None": + """ + Normalizes a JavaScript-like condition string to be compatible with Python's eval. + + - Replaces `true` with `True`. + - Replaces `false` with `False`. + - Replaces `null` with `None`. + - Ensures equality operators `===` and `!==` are converted to Python's `==` and `!=`. + - Handles logical operators `&&` and `||` converting them to `and` and `or`. + """ + if cond is None: + return None + + replacements = { + "true": "True", + "false": "False", + "null": "None", + "===": "==", + "!==": "!=", + "&&": "and", + "||": "or", + } + + # Use regex to replace each JavaScript-like token with its Python equivalent + pattern = re.compile(r"\b(?:true|false|null)\b|===|!==|&&|\|\|") + return pattern.sub(lambda match: replacements[match.group(0)], cond) + + +def parse_if(element): # noqa: C901 + """Parses the element into a callable.""" + branches = [] + else_branch = [] + + current_cond = _normalize_cond(element.attrib.get("cond")) + current_actions = [] + + for child in element: + tag = child.tag + if tag in ("elseif", "else"): + # Save the current branch before starting a new one + if current_cond is not None: + branches.append((current_cond, current_actions)) + elif tag == "else": + else_branch = current_actions + + # Update for the new branch + current_cond = _normalize_cond(child.attrib.get("cond")) + current_actions = [] + else: + # Add the action to the current branch + current_actions.append(parse_element(child)) + + # Add the last branch if needed + if current_cond is not None: + branches.append((current_cond, current_actions)) + + def if_action(*args, **kwargs): + machine = kwargs["machine"] + # Evaluate each branch in order + for cond, actions in branches: + if eval(cond, {}, {"machine": machine, **machine.model.__dict__}): + for action in actions: + action(*args, **kwargs) + return + # Execute the else branch if no condition matches + for action in else_branch: + action(*args, **kwargs) + + return if_action + + +def parse_datamodel(element): + """ + Parses the element into a callable that initializes the state machine model. + + Each element defines a variable with an `id` and an optional `expr`. + """ + data_elements = [parse_data(child) for child in element] + + def __init__( + self, + model: Any = None, + state_field: str = "state", + start_value: Any = None, + rtc: bool = True, + allow_event_without_transition: bool = False, + listeners: "List[object] | None" = None, + ): + model = model if model else Model() + for data_action in data_elements: + data_action(model) + + StateMachine.__init__( + self, + model, + state_field=state_field, + start_value=start_value, + rtc=rtc, + allow_event_without_transition=allow_event_without_transition, + listeners=listeners, + ) + + return __init__ + + +def parse_data(element): + """ + Parses a single element into a callable. + + - `id` is the variable name. + - `expr` is the initial value expression (optional). + """ + data_id = element.attrib["id"] + expr = element.attrib.get("expr") + + def data_initializer(model): + # Evaluate the expression if provided, or set to None + context = model.__dict__ + value = eval(expr, {}, context) if expr else None + setattr(model, data_id, value) + + return data_initializer def strip_namespaces(tree): @@ -99,13 +284,11 @@ def _parse_state(state_elem, final=False): # noqa: C901 ) for onentry_elem in state_elem.findall("onentry"): - for raise_elem in onentry_elem.findall("raise"): - event = raise_elem.get("event") - if event: - state = states[state_id] - if "enter" not in state: - state["enter"] = [] - state["enter"].append(partial(send_event, event_to_send=event)) + entry_action = parse_onentry(onentry_elem) + state = states[state_id] + if "enter" not in state: + state["enter"] = [] + state["enter"].append(entry_action) # First pass: collect all states and mark initial for state_elem in scxml.findall(".//state"): @@ -115,12 +298,18 @@ def _parse_state(state_elem, final=False): # noqa: C901 for state_elem in scxml.findall(".//final"): _parse_state(state_elem, final=True) + extra_data = { + "allow_event_without_transition": True, + } + + # To initialize the data model, we override the SM __init__ method + datamodel = scxml.find("datamodel") + if datamodel is not None: + extra_data["__init__"] = parse_datamodel(datamodel) + # If no initial state was specified, mark the first state as initial if not initial_state and states: first_state = next(iter(states)) states[first_state]["initial"] = True - return { - "states": states, - "events": events, - } + return {"states": states, "events": events, **extra_data} diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 378d55b5..7ece1402 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -313,3 +313,7 @@ def send(self, event: str, *args, **kwargs): if not isawaitable(result): return result return run_async_from_sync(result) + + @property + def is_terminated(self): + return self._engine.is_terminated diff --git a/tests/w3c_tests/conftest.py b/tests/w3c_tests/conftest.py index 51c7fcde..a05a094b 100644 --- a/tests/w3c_tests/conftest.py +++ b/tests/w3c_tests/conftest.py @@ -23,7 +23,7 @@ def sm_class(testcase_path: Path): # Create state machine class try: - return create_machine_class_from_definition("SCXMLStateMachine", definition) + return create_machine_class_from_definition(testcase_path.stem, definition) except Exception as e: raise Exception( f"Failed to create state machine class: {e} from definition: {definition}" diff --git a/tests/w3c_tests/testcases/test147.scxml b/tests/w3c_tests/testcases/test147-ok.scxml similarity index 100% rename from tests/w3c_tests/testcases/test147.scxml rename to tests/w3c_tests/testcases/test147-ok.scxml diff --git a/tests/w3c_tests/testcases/test148.scxml b/tests/w3c_tests/testcases/test148.scxml new file mode 100644 index 00000000..988d679b --- /dev/null +++ b/tests/w3c_tests/testcases/test148.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 91ae8430153d84b3559c62f6bc2e5eccccc64ebe Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Fri, 22 Nov 2024 22:16:04 -0300 Subject: [PATCH 03/45] fix: SCXML Parsing of if/else element --- statemachine/io/scxml.py | 12 ++++++++---- statemachine/statemachine.py | 2 +- tests/test_multiple_destinations.py | 2 ++ tests/w3c_tests/test_testcases.py | 14 ++++++++++++-- .../testcases/{test148.scxml => test148-ok.scxml} | 0 5 files changed, 23 insertions(+), 7 deletions(-) rename tests/w3c_tests/testcases/{test148.scxml => test148-ok.scxml} (100%) diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index 317a6286..3381c2c3 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -122,12 +122,14 @@ def parse_if(element): # noqa: C901 # Save the current branch before starting a new one if current_cond is not None: branches.append((current_cond, current_actions)) - elif tag == "else": - else_branch = current_actions # Update for the new branch - current_cond = _normalize_cond(child.attrib.get("cond")) - current_actions = [] + if tag == "elseif": + current_cond = _normalize_cond(child.attrib.get("cond")) + current_actions = [] + elif tag == "else": + current_cond = None + current_actions = else_branch # Start collecting actions for else else: # Add the action to the current branch current_actions.append(parse_element(child)) @@ -135,6 +137,8 @@ def parse_if(element): # noqa: C901 # Add the last branch if needed if current_cond is not None: branches.append((current_cond, current_actions)) + else: + else_branch = current_actions def if_action(*args, **kwargs): machine = kwargs["machine"] diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 7ece1402..3c1254b3 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -316,4 +316,4 @@ def send(self, event: str, *args, **kwargs): @property def is_terminated(self): - return self._engine.is_terminated + return not self._engine._running diff --git a/tests/test_multiple_destinations.py b/tests/test_multiple_destinations.py index 0ae60f64..4b442430 100644 --- a/tests/test_multiple_destinations.py +++ b/tests/test_multiple_destinations.py @@ -153,6 +153,8 @@ def on_validate(self): # then assert machine.completed.is_active + assert machine.is_terminated + with pytest.raises(exceptions.TransitionNotAllowed, match="Can't validate when in Completed."): assert machine.validate() diff --git a/tests/w3c_tests/test_testcases.py b/tests/w3c_tests/test_testcases.py index 7734a22d..3ac3ca39 100644 --- a/tests/w3c_tests/test_testcases.py +++ b/tests/w3c_tests/test_testcases.py @@ -2,11 +2,21 @@ """ Test cases as defined by W3C SCXML Test Suite -""" + +- https://www.w3.org/Voice/2013/scxml-irp/ +- https://alexzhornyak.github.io/SCXML-tutorial/Tests/ecma/W3C/Mandatory/Auto/report__USCXML_2_0_0___msvc2015_32bit__Win7_1.html +- https://github.com/alexzhornyak/PyBlendSCXML/tree/master/w3c_tests +- https://github.com/jbeard4/SCION/wiki/Pseudocode-for-SCION-step-algorithm + +""" # noqa: E501 def test_usecase(testcase_path, sm_class): - # sm._graph().write_png(f"{testcase_path.name}.png") + # from statemachine.contrib.diagram import DotGraphMachine + + # DotGraphMachine(sm_class).get_graph().write_png( + # testcase_path.parent / f"{testcase_path.stem}.png" + # ) sm = sm_class() assert isinstance(sm, StateMachine) assert sm.current_state.id == "pass" diff --git a/tests/w3c_tests/testcases/test148.scxml b/tests/w3c_tests/testcases/test148-ok.scxml similarity index 100% rename from tests/w3c_tests/testcases/test148.scxml rename to tests/w3c_tests/testcases/test148-ok.scxml From 28ccd8bde3d1548789c3648b742a066f95923f46 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Sat, 23 Nov 2024 18:27:53 -0300 Subject: [PATCH 04/45] feat: Support for SCXML foreach tag --- statemachine/engines/sync.py | 4 +- statemachine/event_data.py | 2 +- statemachine/events.py | 8 +- statemachine/exceptions.py | 6 +- statemachine/io/__init__.py | 36 +++--- statemachine/io/scxml.py | 117 +++++++++++++----- statemachine/statemachine.py | 8 +- statemachine/transition.py | 4 + statemachine/transition_list.py | 4 + tests/w3c_tests/test_testcases.py | 18 ++- tests/w3c_tests/testcases/test144-ok.scxml | 4 +- .../{test145.scxml => test145-ok.scxml} | 0 tests/w3c_tests/testcases/test149-ok.scxml | 32 +++++ tests/w3c_tests/testcases/test150-ok.scxml | 46 +++++++ tests/w3c_tests/testcases/test151-ok.scxml | 46 +++++++ tests/w3c_tests/testcases/test152-ok.scxml | 52 ++++++++ 16 files changed, 325 insertions(+), 62 deletions(-) rename tests/w3c_tests/testcases/{test145.scxml => test145-ok.scxml} (100%) create mode 100644 tests/w3c_tests/testcases/test149-ok.scxml create mode 100644 tests/w3c_tests/testcases/test150-ok.scxml create mode 100644 tests/w3c_tests/testcases/test151-ok.scxml create mode 100644 tests/w3c_tests/testcases/test152-ok.scxml diff --git a/statemachine/engines/sync.py b/statemachine/engines/sync.py index b6de604b..b7a4c833 100644 --- a/statemachine/engines/sync.py +++ b/statemachine/engines/sync.py @@ -76,7 +76,7 @@ def processing_loop(self): self._processing.release() return first_result if first_result is not self._sentinel else None - def _trigger(self, trigger_data: TriggerData): + def _trigger(self, trigger_data: TriggerData): # noqa: C901 executed = False if trigger_data.event == "__initial__": transition = self._initial_transition(trigger_data) @@ -92,6 +92,8 @@ def _trigger(self, trigger_data: TriggerData): if not executed: continue + if self.sm.current_state.transitions.has_eventless_transition: + self.put(TriggerData(self.sm, event=None)) break else: if not self.sm.allow_event_without_transition: diff --git a/statemachine/event_data.py b/statemachine/event_data.py index 00eaa65e..8187e14b 100644 --- a/statemachine/event_data.py +++ b/statemachine/event_data.py @@ -14,7 +14,7 @@ class TriggerData: machine: "StateMachine" - event: "Event" + event: "Event | None" """The Event that was triggered.""" model: Any = field(init=False) diff --git a/statemachine/events.py b/statemachine/events.py index 052d053a..a05cd936 100644 --- a/statemachine/events.py +++ b/statemachine/events.py @@ -32,8 +32,14 @@ def add(self, events): return self def match(self, event: str): - return any(e == event for e in self) + if event is None and self.is_empty: + return True + return any(e == event or e == "*" for e in self) def _replace(self, old, new): self._items.remove(old) self._items.append(new) + + @property + def is_empty(self): + return len(self._items) == 0 diff --git a/statemachine/exceptions.py b/statemachine/exceptions.py index f91daddc..afeb0429 100644 --- a/statemachine/exceptions.py +++ b/statemachine/exceptions.py @@ -32,8 +32,10 @@ class AttrNotFound(InvalidDefinition): class TransitionNotAllowed(StateMachineError): "Raised when there's no transition that can run from the current :ref:`state`." - def __init__(self, event: "Event", state: "State"): + def __init__(self, event: "Event | None", state: "State"): self.event = event self.state = state - msg = _("Can't {} when in {}.").format(self.event.name, self.state.name) + msg = _("Can't {} when in {}.").format( + self.event and self.event.name or "transition", self.state.name + ) super().__init__(msg) diff --git a/statemachine/io/__init__.py b/statemachine/io/__init__.py index 060478ac..0edc69fe 100644 --- a/statemachine/io/__init__.py +++ b/statemachine/io/__init__.py @@ -6,7 +6,7 @@ from ..transition_list import TransitionList -def create_machine_class_from_definition(name: str, definition: dict) -> StateMachine: +def create_machine_class_from_definition(name: str, definition: dict) -> StateMachine: # noqa: C901 """ Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass. @@ -16,32 +16,30 @@ def create_machine_class_from_definition(name: str, definition: dict) -> StateMa ... "TrafficLightMachine", ... { ... "states": { - ... "green": {"initial": True}, - ... "yellow": {}, - ... "red": {}, - ... }, - ... "events": { - ... "change": [ - ... {"from": "green", "to": "yellow"}, - ... {"from": "yellow", "to": "red"}, - ... {"from": "red", "to": "green"}, - ... ] + ... "green": {"initial": True, "on": {"change": {"target": "yellow"}}}, + ... "yellow": {"on": {"change": {"target": "red"}}}, + ... "red": {"on": {"change": {"target": "green"}}}, ... }, ... } ... ) """ + states_instances: Dict[str, State] = {} + events_definitions: Dict[str, dict] = {} + + for state_id, state_kwargs in definition.pop("states").items(): + on_events = state_kwargs.pop("on", {}) + if on_events: + events_definitions[state_id] = on_events - states_instances = { - state_id: State(**state_kwargs) - for state_id, state_kwargs in definition.pop("states").items() - } + states_instances[state_id] = State(**state_kwargs) events: Dict[str, TransitionList] = {} - for event_name, transitions in definition.pop("events").items(): - for transition_data in transitions: - source = states_instances[transition_data["from"]] - target = states_instances[transition_data["to"]] + for state_id, state_events in events_definitions.items(): + for event_name, transition_data in state_events.items(): + source = states_instances[state_id] + + target = states_instances[transition_data["target"]] transition = source.to( target, diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index 3381c2c3..ef23f6e6 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -12,17 +12,17 @@ from statemachine.statemachine import StateMachine -def send_event(machine: StateMachine, event_to_send: str) -> None: - machine.send(event_to_send) - - def parse_onentry(element): """Parses the XML into a callable.""" actions = [parse_element(child) for child in element] def execute_block(*args, **kwargs): - for action in actions: - action(*args, **kwargs) + machine = kwargs["machine"] + try: + for action in actions: + action(*args, **kwargs) + except Exception: + machine.send("error.execution") return execute_block @@ -34,6 +34,8 @@ def parse_element(element): return parse_raise(element) elif tag == "assign": return parse_assign(element) + elif tag == "foreach": + return parse_foreach(element) elif tag == "log": return parse_log(element) elif tag == "if": @@ -80,6 +82,58 @@ def assign_action(*args, **kwargs): return assign_action +def parse_foreach(element): # noqa: C901 + """ + Parses the element into a callable. + + - `array`: The iterable collection (required). + - `item`: The variable name for the current item (required). + - `index`: The variable name for the current index (optional). + - Child elements are executed for each iteration. + """ + array_expr = element.attrib.get("array") + if not array_expr: + raise ValueError(" must have an 'array' attribute") + + item_var = element.attrib.get("item") + if not item_var: + raise ValueError(" must have an 'item' attribute") + + index_var = element.attrib.get("index") + child_actions = [parse_element(child) for child in element] + + def foreach_action(*args, **kwargs): # noqa: C901 + machine = kwargs["machine"] + context = {**machine.model.__dict__} # Shallow copy of the model's attributes + + try: + # Evaluate the array expression to get the iterable + array = eval(array_expr, {}, context) + if not hasattr(array, "__iter__"): + raise ValueError( + f" 'array' must evaluate to an iterable, got: {type(array).__name__}" + ) + except Exception as e: + raise ValueError(f"Error evaluating 'array' expression: {e}") from e + + if not item_var.isidentifier(): + raise ValueError( + f" 'item' must be a valid Python attribute name, got: {item_var}" + ) + # Iterate over the array + for index, item in enumerate(array): + # Assign the item and optionally the index + setattr(machine.model, item_var, item) + if index_var: + setattr(machine.model, index_var, index) + + # Execute child actions + for action in child_actions: + action(*args, **kwargs) + + return foreach_action + + def _normalize_cond(cond: "str | None") -> "str | None": """ Normalizes a JavaScript-like condition string to be compatible with Python's eval. @@ -108,6 +162,19 @@ def _normalize_cond(cond: "str | None") -> "str | None": return pattern.sub(lambda match: replacements[match.group(0)], cond) +def parse_cond(cond): + """Parses the element into a callable.""" + cond = _normalize_cond(cond) + if cond is None: + return None + + def cond_action(*args, **kwargs): + machine = kwargs["machine"] + return eval(cond, {}, {"machine": machine, **machine.model.__dict__}) + + return cond_action + + def parse_if(element): # noqa: C901 """Parses the element into a callable.""" branches = [] @@ -198,6 +265,8 @@ def parse_data(element): """ data_id = element.attrib["id"] expr = element.attrib.get("expr") + if not expr: + expr = element.text and element.text.strip() def data_initializer(model): # Evaluate the expression if provided, or set to None @@ -230,19 +299,8 @@ def parse_scxml(scxml_content: str) -> Dict[str, Any]: # noqa: C901 Parse SCXML content and return a dictionary definition compatible with create_machine_class_from_definition. - The returned dictionary has the format: - { - "states": { - "state_id": {"initial": True}, - ... - }, - "events": { - "event_name": [ - {"from": "source_state", "to": "target_state"}, - ... - ] - } - } + The returned dictionary has the format compatible with + :ref:`create_machine_class_from_definition`. """ # Parse XML content root = ET.fromstring(scxml_content) @@ -258,7 +316,6 @@ def parse_scxml(scxml_content: str) -> Dict[str, Any]: # noqa: C901 # Build states dictionary states = {} - events: Dict[str, List[Dict[str, str]]] = {} def _parse_state(state_elem, final=False): # noqa: C901 state_id = state_elem.get("id") @@ -272,21 +329,21 @@ def _parse_state(state_elem, final=False): # noqa: C901 for trans_elem in state_elem.findall("transition"): event = trans_elem.get("event") or None target = trans_elem.get("target") + cond = parse_cond(trans_elem.get("cond")) if target: - if event not in events: - events[event] = [] + state = states[state_id] + if "on" not in state: + state["on"] = {} + + if event not in state["on"]: + state["on"][event] = {"target": target} + if cond: + state["on"][event]["cond"] = cond if target not in states: states[target] = {} - events[event].append( - { - "from": state_id, - "to": target, - } - ) - for onentry_elem in state_elem.findall("onentry"): entry_action = parse_onentry(onentry_elem) state = states[state_id] @@ -316,4 +373,4 @@ def _parse_state(state_elem, final=False): # noqa: C901 first_state = next(iter(states)) states[first_state]["initial"] = True - return {"states": states, "events": events, **extra_data} + return {"states": states, **extra_data} diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 3c1254b3..852b43ea 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -82,7 +82,7 @@ def __init__( self._callbacks = CallbacksRegistry() self._states_for_instance: Dict[State, State] = {} - self._listeners: Dict[Any, Any] = {} + self._listeners: Dict[int, Any] = {} """Listeners that provides attributes to be used as callbacks.""" if self._abstract: @@ -182,7 +182,7 @@ def _add_listener(self, listeners: "Listeners", allowed_references: SpecReferenc return self def _register_callbacks(self, listeners: List[object]): - self._listeners.update({listener: None for listener in listeners}) + self._listeners.update({id(listener): listener for listener in listeners}) self._add_listener( Listeners.from_listeners( ( @@ -223,9 +223,9 @@ def add_listener(self, *listeners): :ref:`listeners`. """ - self._listeners.update({o: None for o in listeners}) + self._listeners.update({id(listener): listener for listener in listeners}) return self._add_listener( - Listeners.from_listeners(Listener.from_obj(o) for o in listeners), + Listeners.from_listeners(Listener.from_obj(listener) for listener in listeners), allowed_references=SPECS_SAFE, ) diff --git a/statemachine/transition.py b/statemachine/transition.py index a9044f0f..483c714d 100644 --- a/statemachine/transition.py +++ b/statemachine/transition.py @@ -145,3 +145,7 @@ def _copy_with_args(self, **kwargs): new_transition._specs.add(new_spec, new_spec.group) return new_transition + + @property + def is_eventless(self): + return self._events.is_empty diff --git a/statemachine/transition_list.py b/statemachine/transition_list.py index e1aa6504..db2e9759 100644 --- a/statemachine/transition_list.py +++ b/statemachine/transition_list.py @@ -122,3 +122,7 @@ def unique_events(self) -> List["Event"]: tmp_ordered_unique_events_as_keys_on_dict[event] = True return list(tmp_ordered_unique_events_as_keys_on_dict.keys()) + + @property + def has_eventless_transition(self): + return any(transition.is_eventless for transition in self.transitions) diff --git a/tests/w3c_tests/test_testcases.py b/tests/w3c_tests/test_testcases.py index 3ac3ca39..0fabb856 100644 --- a/tests/w3c_tests/test_testcases.py +++ b/tests/w3c_tests/test_testcases.py @@ -1,4 +1,9 @@ +from dataclasses import dataclass +from dataclasses import field + +from statemachine import State from statemachine import StateMachine +from statemachine.event import Event """ Test cases as defined by W3C SCXML Test Suite @@ -11,12 +16,21 @@ """ # noqa: E501 +@dataclass(frozen=True, unsafe_hash=True) +class DebugListener: + events: list = field(default_factory=list) + + def on_transition(self, event: Event, source: State, target: State): + self.events.append(f"{source and source.id} --({event and event.id})--> {target.id}") + + def test_usecase(testcase_path, sm_class): # from statemachine.contrib.diagram import DotGraphMachine # DotGraphMachine(sm_class).get_graph().write_png( # testcase_path.parent / f"{testcase_path.stem}.png" # ) - sm = sm_class() + debug = DebugListener() + sm = sm_class(listeners=[debug]) assert isinstance(sm, StateMachine) - assert sm.current_state.id == "pass" + assert sm.current_state.id == "pass", debug diff --git a/tests/w3c_tests/testcases/test144-ok.scxml b/tests/w3c_tests/testcases/test144-ok.scxml index 482ca62e..09c12be9 100644 --- a/tests/w3c_tests/testcases/test144-ok.scxml +++ b/tests/w3c_tests/testcases/test144-ok.scxml @@ -1,5 +1,5 @@ - diff --git a/tests/w3c_tests/testcases/test145.scxml b/tests/w3c_tests/testcases/test145-ok.scxml similarity index 100% rename from tests/w3c_tests/testcases/test145.scxml rename to tests/w3c_tests/testcases/test145-ok.scxml diff --git a/tests/w3c_tests/testcases/test149-ok.scxml b/tests/w3c_tests/testcases/test149-ok.scxml new file mode 100644 index 00000000..af93a973 --- /dev/null +++ b/tests/w3c_tests/testcases/test149-ok.scxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test150-ok.scxml b/tests/w3c_tests/testcases/test150-ok.scxml new file mode 100644 index 00000000..4b69b26a --- /dev/null +++ b/tests/w3c_tests/testcases/test150-ok.scxml @@ -0,0 +1,46 @@ + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test151-ok.scxml b/tests/w3c_tests/testcases/test151-ok.scxml new file mode 100644 index 00000000..a24cf681 --- /dev/null +++ b/tests/w3c_tests/testcases/test151-ok.scxml @@ -0,0 +1,46 @@ + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test152-ok.scxml b/tests/w3c_tests/testcases/test152-ok.scxml new file mode 100644 index 00000000..9f4385d7 --- /dev/null +++ b/tests/w3c_tests/testcases/test152-ok.scxml @@ -0,0 +1,52 @@ + + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6637692c21f1511869470432c08b58e2b19b69d3 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Tue, 26 Nov 2024 16:28:49 -0300 Subject: [PATCH 05/45] fix: Trigger eventless transition at startup --- statemachine/engines/sync.py | 2 + statemachine/factory.py | 12 ++---- statemachine/io/__init__.py | 49 +++++++++++----------- statemachine/io/scxml.py | 29 +++++++++---- tests/test_statemachine.py | 8 ++-- tests/w3c_tests/conftest.py | 2 +- tests/w3c_tests/testcases/test153-ok.scxml | 45 ++++++++++++++++++++ 7 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 tests/w3c_tests/testcases/test153-ok.scxml diff --git a/statemachine/engines/sync.py b/statemachine/engines/sync.py index b7a4c833..fe09678f 100644 --- a/statemachine/engines/sync.py +++ b/statemachine/engines/sync.py @@ -81,6 +81,8 @@ def _trigger(self, trigger_data: TriggerData): # noqa: C901 if trigger_data.event == "__initial__": transition = self._initial_transition(trigger_data) self._activate(trigger_data, transition) + if self.sm.current_state.transitions.has_eventless_transition: + self.put(TriggerData(self.sm, event=None)) return self._sentinel state = self.sm.current_state diff --git a/statemachine/factory.py b/statemachine/factory.py index e5428e4c..086388d7 100644 --- a/statemachine/factory.py +++ b/statemachine/factory.py @@ -61,20 +61,12 @@ def __getattr__(self, attribute: str) -> Any: ... def _check(cls): has_states = bool(cls.states) - has_events = bool(cls._events) - - cls._abstract = not has_states and not has_events + cls._abstract = not has_states # do not validate the base abstract classes if cls._abstract: return - if not has_states: - raise InvalidDefinition(_("There are no states.")) - - if not has_events: - raise InvalidDefinition(_("There are no events.")) - cls._check_initial_state() cls._check_final_states() cls._check_disconnected_state() @@ -90,6 +82,8 @@ def _check_initial_state(cls): "You currently have these: {!r}" ).format([s.id for s in initials]) ) + if not initials[0].transitions.transitions: + raise InvalidDefinition(_("There are no transitions.")) def _check_final_states(cls): final_state_with_invalid_transitions = [ diff --git a/statemachine/io/__init__.py b/statemachine/io/__init__.py index 0edc69fe..696642ad 100644 --- a/statemachine/io/__init__.py +++ b/statemachine/io/__init__.py @@ -6,7 +6,7 @@ from ..transition_list import TransitionList -def create_machine_class_from_definition(name: str, definition: dict) -> StateMachine: # noqa: C901 +def create_machine_class_from_definition(name: str, **definition) -> StateMachine: # noqa: C901 """ Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass. @@ -14,11 +14,11 @@ def create_machine_class_from_definition(name: str, definition: dict) -> StateMa >>> machine = create_machine_class_from_definition( ... "TrafficLightMachine", - ... { + ... **{ ... "states": { - ... "green": {"initial": True, "on": {"change": {"target": "yellow"}}}, - ... "yellow": {"on": {"change": {"target": "red"}}}, - ... "red": {"on": {"change": {"target": "green"}}}, + ... "green": {"initial": True, "on": {"change": [{"target": "yellow"}]}}, + ... "yellow": {"on": {"change": [{"target": "red"}]}}, + ... "red": {"on": {"change": [{"target": "green"}]}}, ... }, ... } ... ) @@ -36,25 +36,26 @@ def create_machine_class_from_definition(name: str, definition: dict) -> StateMa events: Dict[str, TransitionList] = {} for state_id, state_events in events_definitions.items(): - for event_name, transition_data in state_events.items(): - source = states_instances[state_id] - - target = states_instances[transition_data["target"]] - - transition = source.to( - target, - event=event_name, - cond=transition_data.get("cond"), - unless=transition_data.get("unless"), - on=transition_data.get("on"), - before=transition_data.get("before"), - after=transition_data.get("after"), - ) - - if event_name in events: - events[event_name] |= transition - elif event_name is not None: - events[event_name] = transition + for event_name, transitions_data in state_events.items(): + for trantion_data in transitions_data: + source = states_instances[state_id] + + target = states_instances[trantion_data["target"]] + + transition = source.to( + target, + event=event_name, + cond=trantion_data.get("cond"), + unless=trantion_data.get("unless"), + on=trantion_data.get("on"), + before=trantion_data.get("before"), + after=trantion_data.get("after"), + ) + + if event_name in events: + events[event_name] |= transition + elif event_name is not None: + events[event_name] = transition attrs_mapper = {**definition, **states_instances, **events} return StateMachineMetaclass(name, (StateMachine,), attrs_mapper) # type: ignore[return-value] diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index ef23f6e6..d34a7bd5 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -2,14 +2,15 @@ Simple SCXML parser that converts SCXML documents to state machine definitions. """ +import html import re import xml.etree.ElementTree as ET from typing import Any from typing import Dict from typing import List -from statemachine.model import Model -from statemachine.statemachine import StateMachine +from ..model import Model +from ..statemachine import StateMachine def parse_onentry(element): @@ -147,6 +148,9 @@ def _normalize_cond(cond: "str | None") -> "str | None": if cond is None: return None + # Decode HTML entities, to allow XML syntax like `Var1<Var2` + cond = html.unescape(cond) + replacements = { "true": "True", "false": "False", @@ -172,6 +176,8 @@ def cond_action(*args, **kwargs): machine = kwargs["machine"] return eval(cond, {}, {"machine": machine, **machine.model.__dict__}) + cond_action.cond = cond + return cond_action @@ -180,7 +186,7 @@ def parse_if(element): # noqa: C901 branches = [] else_branch = [] - current_cond = _normalize_cond(element.attrib.get("cond")) + current_cond = parse_cond(element.attrib.get("cond")) current_actions = [] for child in element: @@ -192,7 +198,7 @@ def parse_if(element): # noqa: C901 # Update for the new branch if tag == "elseif": - current_cond = _normalize_cond(child.attrib.get("cond")) + current_cond = parse_cond(child.attrib.get("cond")) current_actions = [] elif tag == "else": current_cond = None @@ -208,10 +214,9 @@ def parse_if(element): # noqa: C901 else_branch = current_actions def if_action(*args, **kwargs): - machine = kwargs["machine"] # Evaluate each branch in order for cond, actions in branches: - if eval(cond, {}, {"machine": machine, **machine.model.__dict__}): + if cond(*args, **kwargs): for action in actions: action(*args, **kwargs) return @@ -337,9 +342,15 @@ def _parse_state(state_elem, final=False): # noqa: C901 state["on"] = {} if event not in state["on"]: - state["on"][event] = {"target": target} - if cond: - state["on"][event]["cond"] = cond + state["on"][event] = [] + + transitions = state["on"][event] + + transition = {"target": target} + if cond: + transition["cond"] = cond + + transitions.append(transition) if target not in states: states[target] = {} diff --git a/tests/test_statemachine.py b/tests/test_statemachine.py index 9337e025..b5381872 100644 --- a/tests/test_statemachine.py +++ b/tests/test_statemachine.py @@ -349,10 +349,12 @@ class EmptyMachine(StateMachine): def test_should_not_create_instance_of_machine_without_states(): s1 = State() - with pytest.raises(exceptions.InvalidDefinition): - class OnlyTransitionMachine(StateMachine): - t1 = s1.to.itself() + class OnlyTransitionMachine(StateMachine): + t1 = s1.to.itself() + + with pytest.raises(exceptions.InvalidDefinition): + OnlyTransitionMachine() def test_should_not_create_instance_of_machine_without_transitions(): diff --git a/tests/w3c_tests/conftest.py b/tests/w3c_tests/conftest.py index a05a094b..bf86a99c 100644 --- a/tests/w3c_tests/conftest.py +++ b/tests/w3c_tests/conftest.py @@ -23,7 +23,7 @@ def sm_class(testcase_path: Path): # Create state machine class try: - return create_machine_class_from_definition(testcase_path.stem, definition) + return create_machine_class_from_definition(testcase_path.stem, **definition) except Exception as e: raise Exception( f"Failed to create state machine class: {e} from definition: {definition}" diff --git a/tests/w3c_tests/testcases/test153-ok.scxml b/tests/w3c_tests/testcases/test153-ok.scxml new file mode 100644 index 00000000..e58b0df8 --- /dev/null +++ b/tests/w3c_tests/testcases/test153-ok.scxml @@ -0,0 +1,45 @@ + + + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 4eefc414e703fae2f017935229b5296e321fdee3 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Wed, 27 Nov 2024 07:15:19 -0300 Subject: [PATCH 06/45] refac: Preserving original scxml file names for passing testcases --- tests/w3c_tests/conftest.py | 2 +- .../{test144-ok.scxml => test144.scxml} | 0 .../{test145-ok.scxml => test145.scxml} | 0 .../{test147-ok.scxml => test147.scxml} | 0 .../{test148-ok.scxml => test148.scxml} | 0 .../{test149-ok.scxml => test149.scxml} | 0 .../{test150-ok.scxml => test150.scxml} | 0 .../{test151-ok.scxml => test151.scxml} | 0 .../{test152-ok.scxml => test152.scxml} | 0 .../{test153-ok.scxml => test153.scxml} | 0 tests/w3c_tests/testcases/test155.scxml | 31 +++++++++++++++++++ 11 files changed, 32 insertions(+), 1 deletion(-) rename tests/w3c_tests/testcases/{test144-ok.scxml => test144.scxml} (100%) rename tests/w3c_tests/testcases/{test145-ok.scxml => test145.scxml} (100%) rename tests/w3c_tests/testcases/{test147-ok.scxml => test147.scxml} (100%) rename tests/w3c_tests/testcases/{test148-ok.scxml => test148.scxml} (100%) rename tests/w3c_tests/testcases/{test149-ok.scxml => test149.scxml} (100%) rename tests/w3c_tests/testcases/{test150-ok.scxml => test150.scxml} (100%) rename tests/w3c_tests/testcases/{test151-ok.scxml => test151.scxml} (100%) rename tests/w3c_tests/testcases/{test152-ok.scxml => test152.scxml} (100%) rename tests/w3c_tests/testcases/{test153-ok.scxml => test153.scxml} (100%) create mode 100644 tests/w3c_tests/testcases/test155.scxml diff --git a/tests/w3c_tests/conftest.py b/tests/w3c_tests/conftest.py index bf86a99c..c68792d3 100644 --- a/tests/w3c_tests/conftest.py +++ b/tests/w3c_tests/conftest.py @@ -42,7 +42,7 @@ def pytest_generate_tests(metafunc): pytest.param( testcase_path, id=str(testcase_path.name), - marks=fail_marks if "ok" not in testcase_path.name else [], + marks=fail_marks if "fail" in testcase_path.name else [], ) for testcase_path in TESTCASES_DIR.glob("**/*.scxml") ], diff --git a/tests/w3c_tests/testcases/test144-ok.scxml b/tests/w3c_tests/testcases/test144.scxml similarity index 100% rename from tests/w3c_tests/testcases/test144-ok.scxml rename to tests/w3c_tests/testcases/test144.scxml diff --git a/tests/w3c_tests/testcases/test145-ok.scxml b/tests/w3c_tests/testcases/test145.scxml similarity index 100% rename from tests/w3c_tests/testcases/test145-ok.scxml rename to tests/w3c_tests/testcases/test145.scxml diff --git a/tests/w3c_tests/testcases/test147-ok.scxml b/tests/w3c_tests/testcases/test147.scxml similarity index 100% rename from tests/w3c_tests/testcases/test147-ok.scxml rename to tests/w3c_tests/testcases/test147.scxml diff --git a/tests/w3c_tests/testcases/test148-ok.scxml b/tests/w3c_tests/testcases/test148.scxml similarity index 100% rename from tests/w3c_tests/testcases/test148-ok.scxml rename to tests/w3c_tests/testcases/test148.scxml diff --git a/tests/w3c_tests/testcases/test149-ok.scxml b/tests/w3c_tests/testcases/test149.scxml similarity index 100% rename from tests/w3c_tests/testcases/test149-ok.scxml rename to tests/w3c_tests/testcases/test149.scxml diff --git a/tests/w3c_tests/testcases/test150-ok.scxml b/tests/w3c_tests/testcases/test150.scxml similarity index 100% rename from tests/w3c_tests/testcases/test150-ok.scxml rename to tests/w3c_tests/testcases/test150.scxml diff --git a/tests/w3c_tests/testcases/test151-ok.scxml b/tests/w3c_tests/testcases/test151.scxml similarity index 100% rename from tests/w3c_tests/testcases/test151-ok.scxml rename to tests/w3c_tests/testcases/test151.scxml diff --git a/tests/w3c_tests/testcases/test152-ok.scxml b/tests/w3c_tests/testcases/test152.scxml similarity index 100% rename from tests/w3c_tests/testcases/test152-ok.scxml rename to tests/w3c_tests/testcases/test152.scxml diff --git a/tests/w3c_tests/testcases/test153-ok.scxml b/tests/w3c_tests/testcases/test153.scxml similarity index 100% rename from tests/w3c_tests/testcases/test153-ok.scxml rename to tests/w3c_tests/testcases/test153.scxml diff --git a/tests/w3c_tests/testcases/test155.scxml b/tests/w3c_tests/testcases/test155.scxml new file mode 100644 index 00000000..e671d177 --- /dev/null +++ b/tests/w3c_tests/testcases/test155.scxml @@ -0,0 +1,31 @@ + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + From 6a4f31ce342d863654b61e6e1cd8fd46cfe716e4 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Wed, 27 Nov 2024 08:22:20 -0300 Subject: [PATCH 07/45] fix: Allowing event without transition --- statemachine/io/scxml.py | 6 ++--- tests/w3c_tests/testcases/test156.scxml | 34 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 tests/w3c_tests/testcases/test156.scxml diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index d34a7bd5..9d60e545 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -241,7 +241,7 @@ def __init__( state_field: str = "state", start_value: Any = None, rtc: bool = True, - allow_event_without_transition: bool = False, + allow_event_without_transition: bool = True, listeners: "List[object] | None" = None, ): model = model if model else Model() @@ -370,9 +370,7 @@ def _parse_state(state_elem, final=False): # noqa: C901 for state_elem in scxml.findall(".//final"): _parse_state(state_elem, final=True) - extra_data = { - "allow_event_without_transition": True, - } + extra_data = {} # To initialize the data model, we override the SM __init__ method datamodel = scxml.find("datamodel") diff --git a/tests/w3c_tests/testcases/test156.scxml b/tests/w3c_tests/testcases/test156.scxml new file mode 100644 index 00000000..e9c584f4 --- /dev/null +++ b/tests/w3c_tests/testcases/test156.scxml @@ -0,0 +1,34 @@ + + + + + + + + [1,2,3] + + + + + + + + + + + + + + + + + + + + + + + + From 55bed8e98acf5a544225ebc0cb12e228ce793b58 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Wed, 27 Nov 2024 20:03:29 -0300 Subject: [PATCH 08/45] feat: Delayed events; Support for SCXML tag --- statemachine/engines/async_.py | 10 +- statemachine/engines/base.py | 7 +- statemachine/engines/sync.py | 12 +- statemachine/event.py | 35 ++-- statemachine/event_data.py | 34 +++- statemachine/io/scxml.py | 160 +++++++++++++++++-- statemachine/statemachine.py | 22 ++- tests/w3c_tests/test_testcases.py | 8 +- tests/w3c_tests/testcases/test158.scxml | 31 ++++ tests/w3c_tests/testcases/test159.scxml | 26 +++ tests/w3c_tests/testcases/test172.scxml | 25 +++ tests/w3c_tests/testcases/test173.scxml | 26 +++ tests/w3c_tests/testcases/test174.scxml | 26 +++ tests/w3c_tests/testcases/test175.scxml | 34 ++++ tests/w3c_tests/testcases/test176.scxml | 36 +++++ tests/w3c_tests/testcases/test179.scxml | 24 +++ tests/w3c_tests/testcases/test183.scxml | 26 +++ tests/w3c_tests/testcases/test185.scxml | 27 ++++ tests/w3c_tests/testcases/test186.scxml | 39 +++++ tests/w3c_tests/testcases/test187-fail.scxml | 40 +++++ tests/w3c_tests/testcases/test189-fail.scxml | 29 ++++ tests/w3c_tests/testcases/test190-fail.scxml | 45 ++++++ tests/w3c_tests/testcases/test191-fail.scxml | 40 +++++ tests/w3c_tests/testcases/test192-fail.scxml | 52 ++++++ 24 files changed, 772 insertions(+), 42 deletions(-) create mode 100644 tests/w3c_tests/testcases/test158.scxml create mode 100644 tests/w3c_tests/testcases/test159.scxml create mode 100644 tests/w3c_tests/testcases/test172.scxml create mode 100644 tests/w3c_tests/testcases/test173.scxml create mode 100644 tests/w3c_tests/testcases/test174.scxml create mode 100644 tests/w3c_tests/testcases/test175.scxml create mode 100644 tests/w3c_tests/testcases/test176.scxml create mode 100644 tests/w3c_tests/testcases/test179.scxml create mode 100644 tests/w3c_tests/testcases/test183.scxml create mode 100644 tests/w3c_tests/testcases/test185.scxml create mode 100644 tests/w3c_tests/testcases/test186.scxml create mode 100644 tests/w3c_tests/testcases/test187-fail.scxml create mode 100644 tests/w3c_tests/testcases/test189-fail.scxml create mode 100644 tests/w3c_tests/testcases/test190-fail.scxml create mode 100644 tests/w3c_tests/testcases/test191-fail.scxml create mode 100644 tests/w3c_tests/testcases/test192-fail.scxml diff --git a/statemachine/engines/async_.py b/statemachine/engines/async_.py index 9d2b3f9f..4e8fd05b 100644 --- a/statemachine/engines/async_.py +++ b/statemachine/engines/async_.py @@ -1,3 +1,6 @@ +import asyncio +import heapq +from time import time from typing import TYPE_CHECKING from ..event_data import EventData @@ -61,7 +64,12 @@ async def processing_loop(self): try: # Execute the triggers in the queue in FIFO order until the queue is empty while self._external_queue: - trigger_data = self._external_queue.popleft() + trigger_data = heapq.heappop(self._external_queue) + current_time = time() + if trigger_data.execution_time > current_time: + self.put(trigger_data) + await asyncio.sleep(0.001) + continue try: result = await self._trigger(trigger_data) if first_result is self._sentinel: diff --git a/statemachine/engines/base.py b/statemachine/engines/base.py index bb010599..fd05e812 100644 --- a/statemachine/engines/base.py +++ b/statemachine/engines/base.py @@ -1,4 +1,4 @@ -from collections import deque +import heapq from threading import Lock from typing import TYPE_CHECKING from weakref import proxy @@ -16,7 +16,7 @@ class BaseEngine: def __init__(self, sm: "StateMachine", rtc: bool = True): self.sm: StateMachine = proxy(sm) - self._external_queue: deque = deque() + self._external_queue: list = [] self._sentinel = object() self._rtc = rtc self._processing = Lock() @@ -26,7 +26,8 @@ def put(self, trigger_data: TriggerData): """Put the trigger on the queue without blocking the caller.""" if not self._running and not self.sm.allow_event_without_transition: raise TransitionNotAllowed(trigger_data.event, self.sm.current_state) - self._external_queue.append(trigger_data) + + heapq.heappush(self._external_queue, trigger_data) def start(self): if self.sm.current_state_value is not None: diff --git a/statemachine/engines/sync.py b/statemachine/engines/sync.py index fe09678f..89b8afb6 100644 --- a/statemachine/engines/sync.py +++ b/statemachine/engines/sync.py @@ -1,3 +1,6 @@ +import heapq +from time import sleep +from time import time from typing import TYPE_CHECKING from ..event_data import EventData @@ -47,7 +50,7 @@ def processing_loop(self): """ if not self._rtc: # The machine is in "synchronous" mode - trigger_data = self._external_queue.popleft() + trigger_data = heapq.heappop(self._external_queue) return self._trigger(trigger_data) # We make sure that only the first event enters the processing critical section, @@ -62,7 +65,12 @@ def processing_loop(self): try: # Execute the triggers in the queue in FIFO order until the queue is empty while self._running and self._external_queue: - trigger_data = self._external_queue.popleft() + trigger_data = heapq.heappop(self._external_queue) + current_time = time() + if trigger_data.execution_time > current_time: + self.put(trigger_data) + sleep(0.001) + continue try: result = self._trigger(trigger_data) if first_result is self._sentinel: diff --git a/statemachine/event.py b/statemachine/event.py index d8fa511d..e804a99c 100644 --- a/statemachine/event.py +++ b/statemachine/event.py @@ -1,4 +1,3 @@ -from inspect import isawaitable from typing import TYPE_CHECKING from typing import List from uuid import uuid4 @@ -8,7 +7,6 @@ from .exceptions import InvalidDefinition from .i18n import _ from .transition_mixin import AddCallbacksMixin -from .utils import run_async_from_sync if TYPE_CHECKING: from .statemachine import StateMachine @@ -44,6 +42,9 @@ class Event(AddCallbacksMixin, str): name: str """The event name.""" + delay: float = 0 + """The delay in milliseconds before the event is triggered. Default is 0.""" + _sm: "StateMachine | None" = None """The state machine instance.""" @@ -55,6 +56,7 @@ def __new__( transitions: "str | TransitionList | None" = None, id: "str | None" = None, name: "str | None" = None, + delay: float = 0, _sm: "StateMachine | None" = None, ): if isinstance(transitions, str): @@ -66,6 +68,7 @@ def __new__( instance = super().__new__(cls, id) instance.id = id + instance.delay = delay if name: instance.name = name elif _has_real_id: @@ -106,19 +109,13 @@ def __get__(self, instance, owner): """ if instance is None: return self - return BoundEvent(id=self.id, name=self.name, _sm=instance) + return BoundEvent(id=self.id, name=self.name, delay=self.delay, _sm=instance) - def __call__(self, *args, **kwargs): - """Send this event to the current state machine. - - Triggering an event on a state machine means invoking or sending a signal, initiating the - process that may result in executing a transition. - """ + def put(self, *args, machine: "StateMachine", **kwargs): # The `__call__` is declared here to help IDEs knowing that an `Event` # can be called as a method. But it is not meant to be called without # an SM instance. Such SM instance is provided by `__get__` method when # used as a property descriptor. - machine = self._sm if machine is None: raise RuntimeError(_("Event {} cannot be called without a SM instance").format(self)) @@ -130,10 +127,20 @@ def __call__(self, *args, **kwargs): kwargs=kwargs, ) machine._put_nonblocking(trigger_data) - result = machine._processing_loop() - if not isawaitable(result): - return result - return run_async_from_sync(result) + + def __call__(self, *args, **kwargs): + """Send this event to the current state machine. + + Triggering an event on a state machine means invoking or sending a signal, initiating the + process that may result in executing a transition. + """ + # The `__call__` is declared here to help IDEs knowing that an `Event` + # can be called as a method. But it is not meant to be called without + # an SM instance. Such SM instance is provided by `__get__` method when + # used as a property descriptor. + machine = self._sm + self.put(*args, machine=machine, **kwargs) + return machine._processing_loop() def split( # type: ignore[override] self, sep: "str | None" = None, maxsplit: int = -1 diff --git a/statemachine/event_data.py b/statemachine/event_data.py index 8187e14b..7b276004 100644 --- a/statemachine/event_data.py +++ b/statemachine/event_data.py @@ -1,5 +1,6 @@ from dataclasses import dataclass from dataclasses import field +from time import time from typing import TYPE_CHECKING from typing import Any @@ -11,23 +12,36 @@ @dataclass +class _Data: + kwargs: dict + + def __getattr__(self, name): + return self.kwargs.get(name, None) + + +@dataclass(order=True) class TriggerData: - machine: "StateMachine" + machine: "StateMachine" = field(compare=False) - event: "Event | None" + event: "Event | None" = field(compare=False) """The Event that was triggered.""" - model: Any = field(init=False) + execution_time: float = field(default=0.0) + """The time at which the :ref:`Event` should run.""" + + model: Any = field(init=False, compare=False) """A reference to the underlying model that holds the current :ref:`State`.""" - args: tuple = field(default_factory=tuple) + args: tuple = field(default_factory=tuple, compare=False) """All positional arguments provided on the :ref:`Event`.""" - kwargs: dict = field(default_factory=dict) + kwargs: dict = field(default_factory=dict, compare=False) """All keyword arguments provided on the :ref:`Event`.""" def __post_init__(self): self.model = self.machine.model + delay = self.event.delay if self.event and self.event.delay else 0 + self.execution_time = time() + (delay / 1000) @dataclass @@ -77,3 +91,13 @@ def extended_kwargs(self): kwargs["source"] = self.source kwargs["target"] = self.target return kwargs + + @property + def data(self): + "Property used by the SCXML namespace" + if self.trigger_data.kwargs: + return _Data(self.trigger_data.kwargs) + elif self.trigger_data.args and len(self.trigger_data.args) == 1: + return self.trigger_data.args[0] + else: + return self.trigger_data.args diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index 9d60e545..82f1e57d 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -8,13 +8,25 @@ from typing import Any from typing import Dict from typing import List +from uuid import uuid4 + +from statemachine.event import Event from ..model import Model from ..statemachine import StateMachine -def parse_onentry(element): - """Parses the XML into a callable.""" +def _eval(expr: str, **kwargs) -> Any: + if "machine" in kwargs: + kwargs.update(kwargs["machine"].model.__dict__) + if "event_data" in kwargs: + kwargs["_event"] = kwargs["event_data"] + + return eval(expr, {}, kwargs) + + +def parse_executable_content(element): + """Parses the children as content XML into a callable.""" actions = [parse_element(child) for child in element] def execute_block(*args, **kwargs): @@ -22,9 +34,13 @@ def execute_block(*args, **kwargs): try: for action in actions: action(*args, **kwargs) - except Exception: - machine.send("error.execution") + machine._processing_loop() + except Exception as e: + machine.send("error.execution", error=e) + + if not actions: + return None return execute_block @@ -41,6 +57,8 @@ def parse_element(element): return parse_log(element) elif tag == "if": return parse_if(element) + elif tag == "send": + return parse_send(element) else: raise ValueError(f"Unknown tag: {tag}") @@ -64,7 +82,7 @@ def parse_log(element): def raise_log(*args, **kwargs): machine = kwargs["machine"] kwargs.update(machine.model.__dict__) - value = eval(expr, {}, kwargs) + value = _eval(expr, **kwargs) print(f"{label}: {value!r}") return raise_log @@ -77,7 +95,7 @@ def parse_assign(element): def assign_action(*args, **kwargs): machine = kwargs["machine"] - value = eval(expr, {}, {"machine": machine, **machine.model.__dict__}) + value = _eval(expr, **kwargs) setattr(machine.model, location, value) return assign_action @@ -173,8 +191,7 @@ def parse_cond(cond): return None def cond_action(*args, **kwargs): - machine = kwargs["machine"] - return eval(cond, {}, {"machine": machine, **machine.model.__dict__}) + return _eval(cond, **kwargs) cond_action.cond = cond @@ -282,6 +299,124 @@ def data_initializer(model): return data_initializer +class ParseTime: + pattern = re.compile(r"(\d+)?(\.\d+)?(s|ms)") + + @classmethod + def replace(cls, expr: str) -> str: + def rep(match): + return str(cls.time_in_ms(match.group(0))) + + return cls.pattern.sub(rep, expr) + + @classmethod + def time_in_ms(cls, expr: str) -> float: + """ + Convert a CSS2 time expression to milliseconds. + + Args: + time (str): A string representing the time, e.g., '1.5s' or '150ms'. + + Returns: + float: The time in milliseconds. + + Raises: + ValueError: If the input is not a valid CSS2 time expression. + """ + if expr.endswith("ms"): + try: + return float(expr[:-2]) + except ValueError as e: + raise ValueError(f"Invalid time value: {expr}") from e + elif expr.endswith("s"): + try: + return float(expr[:-1]) * 1000 + except ValueError as e: + raise ValueError(f"Invalid time value: {expr}") from e + else: + try: + return float(expr) + except ValueError as e: + raise ValueError(f"Invalid time unit in: {expr}") from e + + +def parse_send(element): # noqa: C901 + """ + Parses the element into a callable that dispatches events. + + Attributes: + - `event`: The name of the event to send (required). + - `target`: The target to which the event is sent (optional). + - `type`: The type of the event (optional). + - `id`: A unique identifier for this send action (optional). + - `delay`: The delay before sending the event (optional). + - `namelist`: A space-separated list of data model variables to include in the event (optional) + - `params`: A dictionary of parameters to include in the event (optional). + - `content`: Content to include in the event (optional). + """ + event_attr = element.attrib.get("event") + event_expr = element.attrib.get("eventexpr") + if not (event_attr or event_expr): + raise ValueError(" must have an 'event' or `eventexpr` attribute") + + target_expr = element.attrib.get("target") + type_expr = element.attrib.get("type") + id_attr = element.attrib.get("id") + idlocation = element.attrib.get("idlocation") + delay_attr = element.attrib.get("delay") + delay_expr = element.attrib.get("delayexpr") + namelist_expr = element.attrib.get("namelist") + + # Parse and child elements + params = {} + content = () + for child in element: + if child.tag == "param": + name = child.attrib.get("name") + expr = child.attrib.get("expr") + if name and expr: + params[name] = expr + elif child.tag == "content": + content = (_eval(child.text),) + + def send_action(*args, **kwargs): + machine = kwargs["machine"] + context = {**machine.model.__dict__} + + # Evaluate expressions + event = event_attr or eval(event_expr, {}, context) + _target = eval(target_expr, {}, context) if target_expr else None + _event_type = eval(type_expr, {}, context) if type_expr else None + + if id_attr: + send_id = id_attr + else: + send_id = uuid4().hex + if idlocation: + setattr(machine.model, idlocation, send_id) + + if delay_attr: + delay = ParseTime.time_in_ms(delay_attr) + elif delay_expr: + delay_expr_expanded = ParseTime.replace(delay_expr) + delay = ParseTime.time_in_ms(eval(delay_expr_expanded, {}, context)) + else: + delay = 0 + + params_values = {} + if namelist_expr: + for name in namelist_expr.split(): + if name in context: + params_values[name] = context[name] + + for name, expr in params.items(): + params_values[name] = eval(expr, {}, context) + + Event(id=event, name=event, delay=delay).put(*content, machine=machine, **params_values) + + return send_action + + def strip_namespaces(tree): """Remove all namespaces from tags and attributes in place. @@ -335,9 +470,13 @@ def _parse_state(state_elem, final=False): # noqa: C901 event = trans_elem.get("event") or None target = trans_elem.get("target") cond = parse_cond(trans_elem.get("cond")) + content_action = parse_executable_content(trans_elem) if target: state = states[state_id] + + # This "on" represents the events handled by the state + # there's also a possibility of "on" as an action if "on" not in state: state["on"] = {} @@ -350,13 +489,16 @@ def _parse_state(state_elem, final=False): # noqa: C901 if cond: transition["cond"] = cond + if content_action: + transition["on"] = content_action + transitions.append(transition) if target not in states: states[target] = {} for onentry_elem in state_elem.findall("onentry"): - entry_action = parse_onentry(onentry_elem) + entry_action = parse_executable_content(onentry_elem) state = states[state_id] if "enter" not in state: state["enter"] = [] diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 852b43ea..0107923f 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -109,7 +109,10 @@ def activate_initial_state(self): return run_async_from_sync(result) def _processing_loop(self): - return self._engine.processing_loop() + result = self._engine.processing_loop() + if not isawaitable(result): + return result + return run_async_from_sync(result) def __init_subclass__(cls, strict_states: bool = False): cls._strict_states = strict_states @@ -298,17 +301,24 @@ def _put_nonblocking(self, trigger_data: TriggerData): """Put the trigger on the queue without blocking the caller.""" self._engine.put(trigger_data) - def send(self, event: str, *args, **kwargs): + def send(self, event: str, *args, delay: float = 0, **kwargs): """Send an :ref:`Event` to the state machine. + :param event: The trigger for the state machine, specified as an event id string. + :param args: Additional positional arguments to pass to the event. + :param delay: A time delay in milliseconds to process the event. Default is 0. + :param kwargs: Additional keyword arguments to pass to the event. + .. seealso:: See: :ref:`triggering events`. - """ - event_instance: BoundEvent = getattr( - self, event, BoundEvent(id=event, name=event, _sm=self) - ) + know_event = getattr(self, event, None) + event_name = know_event.name if know_event else event + delay = ( + delay if delay else know_event and know_event.delay or 0 + ) # first the param, then the event, or 0 + event_instance = BoundEvent(id=event, name=event_name, delay=delay, _sm=self) result = event_instance(*args, **kwargs) if not isawaitable(result): return result diff --git a/tests/w3c_tests/test_testcases.py b/tests/w3c_tests/test_testcases.py index 0fabb856..773487e1 100644 --- a/tests/w3c_tests/test_testcases.py +++ b/tests/w3c_tests/test_testcases.py @@ -20,8 +20,12 @@ class DebugListener: events: list = field(default_factory=list) - def on_transition(self, event: Event, source: State, target: State): - self.events.append(f"{source and source.id} --({event and event.id})--> {target.id}") + def on_transition(self, event: Event, source: State, target: State, event_data): + self.events.append( + f"{source and source.id} -- " + f"{event and event.id}{event_data.trigger_data.kwargs} --> " + f"{target.id}" + ) def test_usecase(testcase_path, sm_class): diff --git a/tests/w3c_tests/testcases/test158.scxml b/tests/w3c_tests/testcases/test158.scxml new file mode 100644 index 00000000..a989fc33 --- /dev/null +++ b/tests/w3c_tests/testcases/test158.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test159.scxml b/tests/w3c_tests/testcases/test159.scxml new file mode 100644 index 00000000..b17e5f56 --- /dev/null +++ b/tests/w3c_tests/testcases/test159.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test172.scxml b/tests/w3c_tests/testcases/test172.scxml new file mode 100644 index 00000000..5194a975 --- /dev/null +++ b/tests/w3c_tests/testcases/test172.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test173.scxml b/tests/w3c_tests/testcases/test173.scxml new file mode 100644 index 00000000..b3694a6f --- /dev/null +++ b/tests/w3c_tests/testcases/test173.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test174.scxml b/tests/w3c_tests/testcases/test174.scxml new file mode 100644 index 00000000..227b7875 --- /dev/null +++ b/tests/w3c_tests/testcases/test174.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test175.scxml b/tests/w3c_tests/testcases/test175.scxml new file mode 100644 index 00000000..c5ada221 --- /dev/null +++ b/tests/w3c_tests/testcases/test175.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test176.scxml b/tests/w3c_tests/testcases/test176.scxml new file mode 100644 index 00000000..f337561d --- /dev/null +++ b/tests/w3c_tests/testcases/test176.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test179.scxml b/tests/w3c_tests/testcases/test179.scxml new file mode 100644 index 00000000..64168fe6 --- /dev/null +++ b/tests/w3c_tests/testcases/test179.scxml @@ -0,0 +1,24 @@ + + + + + + + 123 + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test183.scxml b/tests/w3c_tests/testcases/test183.scxml new file mode 100644 index 00000000..ba28159a --- /dev/null +++ b/tests/w3c_tests/testcases/test183.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test185.scxml b/tests/w3c_tests/testcases/test185.scxml new file mode 100644 index 00000000..46bb4ebd --- /dev/null +++ b/tests/w3c_tests/testcases/test185.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test186.scxml b/tests/w3c_tests/testcases/test186.scxml new file mode 100644 index 00000000..395b177f --- /dev/null +++ b/tests/w3c_tests/testcases/test186.scxml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test187-fail.scxml b/tests/w3c_tests/testcases/test187-fail.scxml new file mode 100644 index 00000000..b6fa91b2 --- /dev/null +++ b/tests/w3c_tests/testcases/test187-fail.scxml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test189-fail.scxml b/tests/w3c_tests/testcases/test189-fail.scxml new file mode 100644 index 00000000..916a9cd1 --- /dev/null +++ b/tests/w3c_tests/testcases/test189-fail.scxml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test190-fail.scxml b/tests/w3c_tests/testcases/test190-fail.scxml new file mode 100644 index 00000000..c1728a64 --- /dev/null +++ b/tests/w3c_tests/testcases/test190-fail.scxml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test191-fail.scxml b/tests/w3c_tests/testcases/test191-fail.scxml new file mode 100644 index 00000000..50e226e3 --- /dev/null +++ b/tests/w3c_tests/testcases/test191-fail.scxml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test192-fail.scxml b/tests/w3c_tests/testcases/test192-fail.scxml new file mode 100644 index 00000000..e4458743 --- /dev/null +++ b/tests/w3c_tests/testcases/test192-fail.scxml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ca3ecf70aadb5e4b08bf97cc8c6a4702e0c76f20 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Sat, 30 Nov 2024 11:09:46 -0300 Subject: [PATCH 09/45] refac: Attempt to use PriorityQueue --- statemachine/engines/async_.py | 7 +++---- statemachine/engines/base.py | 38 +++++++++++++++++++++++++++++----- statemachine/engines/sync.py | 11 +++++----- statemachine/statemachine.py | 2 +- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/statemachine/engines/async_.py b/statemachine/engines/async_.py index 4e8fd05b..b147e260 100644 --- a/statemachine/engines/async_.py +++ b/statemachine/engines/async_.py @@ -1,5 +1,4 @@ import asyncio -import heapq from time import time from typing import TYPE_CHECKING @@ -63,8 +62,8 @@ async def processing_loop(self): first_result = self._sentinel try: # Execute the triggers in the queue in FIFO order until the queue is empty - while self._external_queue: - trigger_data = heapq.heappop(self._external_queue) + while self._running and not self.empty(): + trigger_data = self.pop() current_time = time() if trigger_data.execution_time > current_time: self.put(trigger_data) @@ -77,7 +76,7 @@ async def processing_loop(self): except Exception: # Whe clear the queue as we don't have an expected behavior # and cannot keep processing - self._external_queue.clear() + self.clear() raise finally: self._processing.release() diff --git a/statemachine/engines/base.py b/statemachine/engines/base.py index fd05e812..fb998136 100644 --- a/statemachine/engines/base.py +++ b/statemachine/engines/base.py @@ -1,4 +1,5 @@ -import heapq +from queue import PriorityQueue +from queue import Queue from threading import Lock from typing import TYPE_CHECKING from weakref import proxy @@ -15,19 +16,46 @@ class BaseEngine: def __init__(self, sm: "StateMachine", rtc: bool = True): - self.sm: StateMachine = proxy(sm) - self._external_queue: list = [] self._sentinel = object() self._rtc = rtc - self._processing = Lock() self._running = True + self._init(sm) + + def _init(self, sm: "StateMachine"): + self.sm: StateMachine = proxy(sm) + self._external_queue: Queue = PriorityQueue() + self._processing = Lock() + + def __getstate__(self) -> dict: + state = self.__dict__.copy() + del state["_external_queue"] + del state["_processing"] + del state["sm"] + return state + + def __setstate__(self, state: dict) -> None: + for attr, value in state.items(): + setattr(self, attr, value) + + def empty(self): + return self._external_queue.qsize() == 0 def put(self, trigger_data: TriggerData): """Put the trigger on the queue without blocking the caller.""" if not self._running and not self.sm.allow_event_without_transition: raise TransitionNotAllowed(trigger_data.event, self.sm.current_state) - heapq.heappush(self._external_queue, trigger_data) + self._external_queue.put(trigger_data) + + def pop(self): + try: + return self._external_queue.get(block=False) + except Exception: + return None + + def clear(self): + with self._external_queue.mutex: + self._external_queue.queue.clear() def start(self): if self.sm.current_state_value is not None: diff --git a/statemachine/engines/sync.py b/statemachine/engines/sync.py index 89b8afb6..2e24426a 100644 --- a/statemachine/engines/sync.py +++ b/statemachine/engines/sync.py @@ -1,4 +1,3 @@ -import heapq from time import sleep from time import time from typing import TYPE_CHECKING @@ -50,7 +49,7 @@ def processing_loop(self): """ if not self._rtc: # The machine is in "synchronous" mode - trigger_data = heapq.heappop(self._external_queue) + trigger_data = self.pop() return self._trigger(trigger_data) # We make sure that only the first event enters the processing critical section, @@ -64,8 +63,8 @@ def processing_loop(self): first_result = self._sentinel try: # Execute the triggers in the queue in FIFO order until the queue is empty - while self._running and self._external_queue: - trigger_data = heapq.heappop(self._external_queue) + while self._running and not self.empty(): + trigger_data = self.pop() current_time = time() if trigger_data.execution_time > current_time: self.put(trigger_data) @@ -78,7 +77,7 @@ def processing_loop(self): except Exception: # Whe clear the queue as we don't have an expected behavior # and cannot keep processing - self._external_queue.clear() + self.clear() raise finally: self._processing.release() @@ -137,7 +136,7 @@ def _activate(self, trigger_data: TriggerData, transition: "Transition"): # noq self.sm._callbacks.call(transition.after.key, *args, **kwargs) if target.final: - self._external_queue.clear() + self.clear() self._running = False if len(result) == 0: diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 0107923f..987b595d 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -148,7 +148,7 @@ def __setstate__(self, state): self._listeners: Dict[Any, Any] = {} self._register_callbacks([]) - self.add_listener(*listeners.keys()) + self.add_listener(*listeners.values()) self._engine = self._get_engine(rtc) def _get_initial_state(self): From ed8b63939501da65bf0f5f996680fbd73f9bad6a Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Sat, 30 Nov 2024 12:43:30 -0300 Subject: [PATCH 10/45] refac: Using get/set state for pickling --- statemachine/engines/base.py | 18 ++---------------- tests/test_copy.py | 4 ++-- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/statemachine/engines/base.py b/statemachine/engines/base.py index fb998136..a990bbf1 100644 --- a/statemachine/engines/base.py +++ b/statemachine/engines/base.py @@ -16,27 +16,13 @@ class BaseEngine: def __init__(self, sm: "StateMachine", rtc: bool = True): + self.sm: StateMachine = proxy(sm) + self._external_queue: Queue = PriorityQueue() self._sentinel = object() self._rtc = rtc self._running = True - self._init(sm) - - def _init(self, sm: "StateMachine"): - self.sm: StateMachine = proxy(sm) - self._external_queue: Queue = PriorityQueue() self._processing = Lock() - def __getstate__(self) -> dict: - state = self.__dict__.copy() - del state["_external_queue"] - del state["_processing"] - del state["sm"] - return state - - def __setstate__(self, state: dict) -> None: - for attr, value in state.items(): - setattr(self, attr, value) - def empty(self): return self._external_queue.qsize() == 0 diff --git a/tests/test_copy.py b/tests/test_copy.py index 2f5a981e..65579887 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -124,7 +124,7 @@ def assertions(sm, _reference): if not sm._listeners: pytest.fail("did not found any observer") - for listener in sm._listeners: + for listener in sm._listeners.values(): listener.let_me_be_visible = False with pytest.raises(TransitionNotAllowed): @@ -132,7 +132,7 @@ def assertions(sm, _reference): sm.model.let_me_be_visible = True - for listener in sm._listeners: + for listener in sm._listeners.values(): with pytest.raises(TransitionNotAllowed): sm.send("publish") From b069740e9a844d0fae69103c7df108522830eeca Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Sat, 30 Nov 2024 18:55:02 -0300 Subject: [PATCH 11/45] feat: Support for SCXML tag. Allow cancelling delayed events --- statemachine/engines/base.py | 18 ++++-- statemachine/event.py | 4 +- statemachine/event_data.py | 12 ++++ statemachine/io/scxml.py | 36 ++++++++++- statemachine/statemachine.py | 8 ++- tests/w3c_tests/testcases/test194.scxml | 26 ++++++++ tests/w3c_tests/testcases/test198.scxml | 26 ++++++++ tests/w3c_tests/testcases/test199.scxml | 23 +++++++ tests/w3c_tests/testcases/test200.scxml | 23 +++++++ tests/w3c_tests/testcases/test205.scxml | 36 +++++++++++ tests/w3c_tests/testcases/test207-fail.scxml | 63 ++++++++++++++++++++ tests/w3c_tests/testcases/test208.scxml | 26 ++++++++ 12 files changed, 290 insertions(+), 11 deletions(-) create mode 100644 tests/w3c_tests/testcases/test194.scxml create mode 100644 tests/w3c_tests/testcases/test198.scxml create mode 100644 tests/w3c_tests/testcases/test199.scxml create mode 100644 tests/w3c_tests/testcases/test200.scxml create mode 100644 tests/w3c_tests/testcases/test205.scxml create mode 100644 tests/w3c_tests/testcases/test207-fail.scxml create mode 100644 tests/w3c_tests/testcases/test208.scxml diff --git a/statemachine/engines/base.py b/statemachine/engines/base.py index a990bbf1..70b96f48 100644 --- a/statemachine/engines/base.py +++ b/statemachine/engines/base.py @@ -43,15 +43,23 @@ def clear(self): with self._external_queue.mutex: self._external_queue.queue.clear() + def cancel_event(self, send_id: str): + """Cancel the event with the given send_id.""" + + # We use the internal `queue` to make thins faster as the mutex + # is protecting the block below + with self._external_queue.mutex: + self._external_queue.queue = [ + trigger_data + for trigger_data in self._external_queue.queue + if trigger_data.send_id != send_id + ] + def start(self): if self.sm.current_state_value is not None: return - trigger_data = TriggerData( - machine=self.sm, - event=BoundEvent("__initial__", _sm=self.sm), - ) - self.put(trigger_data) + BoundEvent("__initial__", _sm=self.sm).put(machine=self.sm) def _initial_transition(self, trigger_data): transition = Transition(State(), self.sm._get_initial_state(), event="__initial__") diff --git a/statemachine/event.py b/statemachine/event.py index e804a99c..21013e36 100644 --- a/statemachine/event.py +++ b/statemachine/event.py @@ -111,7 +111,7 @@ def __get__(self, instance, owner): return self return BoundEvent(id=self.id, name=self.name, delay=self.delay, _sm=instance) - def put(self, *args, machine: "StateMachine", **kwargs): + def put(self, *args, machine: "StateMachine", send_id: "str | None" = None, **kwargs): # The `__call__` is declared here to help IDEs knowing that an `Event` # can be called as a method. But it is not meant to be called without # an SM instance. Such SM instance is provided by `__get__` method when @@ -123,10 +123,12 @@ def put(self, *args, machine: "StateMachine", **kwargs): trigger_data = TriggerData( machine=machine, event=self, + send_id=send_id, args=args, kwargs=kwargs, ) machine._put_nonblocking(trigger_data) + return trigger_data def __call__(self, *args, **kwargs): """Send this event to the current state machine. diff --git a/statemachine/event_data.py b/statemachine/event_data.py index 7b276004..2017e7a3 100644 --- a/statemachine/event_data.py +++ b/statemachine/event_data.py @@ -3,6 +3,7 @@ from time import time from typing import TYPE_CHECKING from typing import Any +from uuid import uuid4 if TYPE_CHECKING: from .event import Event @@ -26,6 +27,12 @@ class TriggerData: event: "Event | None" = field(compare=False) """The Event that was triggered.""" + send_id: "str | None" = field(compare=False, default=None) + """A string literal to be used as the id of this instance of :ref:`TriggerData`. + + Allow revoking a delayed :ref:`TriggerData` instance. + """ + execution_time: float = field(default=0.0) """The time at which the :ref:`Event` should run.""" @@ -42,6 +49,8 @@ def __post_init__(self): self.model = self.machine.model delay = self.event.delay if self.event and self.event.delay else 0 self.execution_time = time() + (delay / 1000) + if self.send_id is None: + self.send_id = uuid4().hex @dataclass @@ -65,6 +74,9 @@ class EventData: executed: bool = False + origintype: str = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor" + """The origintype of the :ref:`Event` as specified by the SCXML namespace.""" + def __post_init__(self): self.state = self.transition.source self.source = self.transition.source diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index 82f1e57d..e0969df1 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -59,6 +59,8 @@ def parse_element(element): return parse_if(element) elif tag == "send": return parse_send(element) + elif tag == "cancel": + return parse_cancel(element) else: raise ValueError(f"Unknown tag: {tag}") @@ -74,6 +76,26 @@ def raise_action(*args, **kwargs): return raise_action +def parse_cancel(element): + """Parses the element into a callable.""" + sendid = element.attrib.get("sendid") + sendidexpr = element.attrib.get("sendidexpr") + + def cancel(*args, **kwargs): + if sendid and sendidexpr: + raise ValueError(" cannot have both a 'sendid' and 'sendidexpr' attribute") + elif sendid: + send_id = sendid + elif sendidexpr: + send_id = _eval(sendidexpr, **kwargs) + else: + raise ValueError(" must have either a 'sendid' or 'sendidexpr' attribute") + machine = kwargs["machine"] + machine.cancel_event(send_id) + + return cancel + + def parse_log(element): """Parses the element into a callable.""" label = element.attrib["label"] @@ -360,7 +382,7 @@ def parse_send(element): # noqa: C901 raise ValueError(" must have an 'event' or `eventexpr` attribute") target_expr = element.attrib.get("target") - type_expr = element.attrib.get("type") + type_attr = element.attrib.get("type") id_attr = element.attrib.get("id") idlocation = element.attrib.get("idlocation") delay_attr = element.attrib.get("delay") @@ -386,7 +408,10 @@ def send_action(*args, **kwargs): # Evaluate expressions event = event_attr or eval(event_expr, {}, context) _target = eval(target_expr, {}, context) if target_expr else None - _event_type = eval(type_expr, {}, context) if type_expr else None + if type_attr and type_attr != "http://www.w3.org/TR/scxml/#SCXMLEventProcessor": + raise ValueError( + "Only 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor' event type is supported" + ) if id_attr: send_id = id_attr @@ -412,7 +437,12 @@ def send_action(*args, **kwargs): for name, expr in params.items(): params_values[name] = eval(expr, {}, context) - Event(id=event, name=event, delay=delay).put(*content, machine=machine, **params_values) + Event(id=event, name=event, delay=delay).put( + *content, + machine=machine, + send_id=send_id, + **params_values, + ) return send_action diff --git a/statemachine/statemachine.py b/statemachine/statemachine.py index 987b595d..2dc3b330 100644 --- a/statemachine/statemachine.py +++ b/statemachine/statemachine.py @@ -301,7 +301,7 @@ def _put_nonblocking(self, trigger_data: TriggerData): """Put the trigger on the queue without blocking the caller.""" self._engine.put(trigger_data) - def send(self, event: str, *args, delay: float = 0, **kwargs): + def send(self, event: str, *args, delay: float = 0, event_id: "str | None" = None, **kwargs): """Send an :ref:`Event` to the state machine. :param event: The trigger for the state machine, specified as an event id string. @@ -319,11 +319,15 @@ def send(self, event: str, *args, delay: float = 0, **kwargs): delay if delay else know_event and know_event.delay or 0 ) # first the param, then the event, or 0 event_instance = BoundEvent(id=event, name=event_name, delay=delay, _sm=self) - result = event_instance(*args, **kwargs) + result = event_instance(*args, event_id=event_id, **kwargs) if not isawaitable(result): return result return run_async_from_sync(result) + def cancel_event(self, send_id: str): + """Cancel all the delayed events with the given ``send_id``.""" + self._engine.cancel_event(send_id) + @property def is_terminated(self): return not self._engine._running diff --git a/tests/w3c_tests/testcases/test194.scxml b/tests/w3c_tests/testcases/test194.scxml new file mode 100644 index 00000000..b4a5a5a1 --- /dev/null +++ b/tests/w3c_tests/testcases/test194.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test198.scxml b/tests/w3c_tests/testcases/test198.scxml new file mode 100644 index 00000000..2c4e7352 --- /dev/null +++ b/tests/w3c_tests/testcases/test198.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test199.scxml b/tests/w3c_tests/testcases/test199.scxml new file mode 100644 index 00000000..17d31645 --- /dev/null +++ b/tests/w3c_tests/testcases/test199.scxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test200.scxml b/tests/w3c_tests/testcases/test200.scxml new file mode 100644 index 00000000..978ef9d1 --- /dev/null +++ b/tests/w3c_tests/testcases/test200.scxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test205.scxml b/tests/w3c_tests/testcases/test205.scxml new file mode 100644 index 00000000..25cd50f0 --- /dev/null +++ b/tests/w3c_tests/testcases/test205.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test207-fail.scxml b/tests/w3c_tests/testcases/test207-fail.scxml new file mode 100644 index 00000000..51861059 --- /dev/null +++ b/tests/w3c_tests/testcases/test207-fail.scxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/testcases/test208.scxml b/tests/w3c_tests/testcases/test208.scxml new file mode 100644 index 00000000..0e070326 --- /dev/null +++ b/tests/w3c_tests/testcases/test208.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + From f52cce68baab3610a51c490d51382b0e8db0d3cf Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Tue, 3 Dec 2024 00:12:39 -0300 Subject: [PATCH 12/45] feat: Support for SCXML + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test303.scxml b/tests/scxml/w3c/mandatory/test303.scxml new file mode 100644 index 00000000..c245732f --- /dev/null +++ b/tests/scxml/w3c/mandatory/test303.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test304.scxml b/tests/scxml/w3c/mandatory/test304.scxml new file mode 100644 index 00000000..208b36d3 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test304.scxml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test309-fail.scxml b/tests/scxml/w3c/mandatory/test309-fail.scxml new file mode 100644 index 00000000..54396083 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test309-fail.scxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test310-fail.scxml b/tests/scxml/w3c/mandatory/test310-fail.scxml new file mode 100644 index 00000000..11e4ae3a --- /dev/null +++ b/tests/scxml/w3c/mandatory/test310-fail.scxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test311-fail.scxml b/tests/scxml/w3c/mandatory/test311-fail.scxml new file mode 100644 index 00000000..c50e57b7 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test311-fail.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test312.scxml b/tests/scxml/w3c/mandatory/test312.scxml new file mode 100644 index 00000000..b9e51a55 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test312.scxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test318-fail.scxml b/tests/scxml/w3c/mandatory/test318-fail.scxml new file mode 100644 index 00000000..27f9836c --- /dev/null +++ b/tests/scxml/w3c/mandatory/test318-fail.scxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test319-fail.scxml b/tests/scxml/w3c/mandatory/test319-fail.scxml new file mode 100644 index 00000000..29746e96 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test319-fail.scxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test321-fail.scxml b/tests/scxml/w3c/mandatory/test321-fail.scxml new file mode 100644 index 00000000..8f01dc85 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test321-fail.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test322-fail.scxml b/tests/scxml/w3c/mandatory/test322-fail.scxml new file mode 100644 index 00000000..31c8e2cc --- /dev/null +++ b/tests/scxml/w3c/mandatory/test322-fail.scxml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test323-fail.scxml b/tests/scxml/w3c/mandatory/test323-fail.scxml new file mode 100644 index 00000000..5183cdf2 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test323-fail.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test324-fail.scxml b/tests/scxml/w3c/mandatory/test324-fail.scxml new file mode 100644 index 00000000..f763ceec --- /dev/null +++ b/tests/scxml/w3c/mandatory/test324-fail.scxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test325-fail.scxml b/tests/scxml/w3c/mandatory/test325-fail.scxml new file mode 100644 index 00000000..7159ae91 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test325-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test326-fail.scxml b/tests/scxml/w3c/mandatory/test326-fail.scxml new file mode 100644 index 00000000..5a56c01d --- /dev/null +++ b/tests/scxml/w3c/mandatory/test326-fail.scxml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test329-fail.scxml b/tests/scxml/w3c/mandatory/test329-fail.scxml new file mode 100644 index 00000000..603faa4b --- /dev/null +++ b/tests/scxml/w3c/mandatory/test329-fail.scxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test330-fail.scxml b/tests/scxml/w3c/mandatory/test330-fail.scxml new file mode 100644 index 00000000..7f7a68de --- /dev/null +++ b/tests/scxml/w3c/mandatory/test330-fail.scxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test331-fail.scxml b/tests/scxml/w3c/mandatory/test331-fail.scxml new file mode 100644 index 00000000..6394f587 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test331-fail.scxml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test332-fail.scxml b/tests/scxml/w3c/mandatory/test332-fail.scxml new file mode 100644 index 00000000..fc32fba1 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test332-fail.scxml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test333-fail.scxml b/tests/scxml/w3c/mandatory/test333-fail.scxml new file mode 100644 index 00000000..ea92ef05 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test333-fail.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test335.scxml b/tests/scxml/w3c/mandatory/test335.scxml new file mode 100644 index 00000000..bbeb4601 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test335.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test336.scxml b/tests/scxml/w3c/mandatory/test336.scxml new file mode 100644 index 00000000..78d2a06a --- /dev/null +++ b/tests/scxml/w3c/mandatory/test336.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test337-fail.scxml b/tests/scxml/w3c/mandatory/test337-fail.scxml new file mode 100644 index 00000000..47709e63 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test337-fail.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test338-fail.scxml b/tests/scxml/w3c/mandatory/test338-fail.scxml new file mode 100644 index 00000000..b91e0815 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test338-fail.scxml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test339-fail.scxml b/tests/scxml/w3c/mandatory/test339-fail.scxml new file mode 100644 index 00000000..58ca6cea --- /dev/null +++ b/tests/scxml/w3c/mandatory/test339-fail.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test342-fail.scxml b/tests/scxml/w3c/mandatory/test342-fail.scxml new file mode 100644 index 00000000..41755839 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test342-fail.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test343-fail.scxml b/tests/scxml/w3c/mandatory/test343-fail.scxml new file mode 100644 index 00000000..3ccc31a1 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test343-fail.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test344-fail.scxml b/tests/scxml/w3c/mandatory/test344-fail.scxml new file mode 100644 index 00000000..d4519bda --- /dev/null +++ b/tests/scxml/w3c/mandatory/test344-fail.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test346-fail.scxml b/tests/scxml/w3c/mandatory/test346-fail.scxml new file mode 100644 index 00000000..f7dfc2dc --- /dev/null +++ b/tests/scxml/w3c/mandatory/test346-fail.scxml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test347-fail.scxml b/tests/scxml/w3c/mandatory/test347-fail.scxml new file mode 100644 index 00000000..6b77af2c --- /dev/null +++ b/tests/scxml/w3c/mandatory/test347-fail.scxml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test348.scxml b/tests/scxml/w3c/mandatory/test348.scxml new file mode 100644 index 00000000..f08c5544 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test348.scxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test349.scxml b/tests/scxml/w3c/mandatory/test349.scxml new file mode 100644 index 00000000..3c68245d --- /dev/null +++ b/tests/scxml/w3c/mandatory/test349.scxml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test350-fail.scxml b/tests/scxml/w3c/mandatory/test350-fail.scxml new file mode 100644 index 00000000..d456cd09 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test350-fail.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test351-fail.scxml b/tests/scxml/w3c/mandatory/test351-fail.scxml new file mode 100644 index 00000000..6d9c4969 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test351-fail.scxml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test352-fail.scxml b/tests/scxml/w3c/mandatory/test352-fail.scxml new file mode 100644 index 00000000..32ef2768 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test352-fail.scxml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test354.scxml b/tests/scxml/w3c/mandatory/test354.scxml new file mode 100644 index 00000000..ac4e8842 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test354.scxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + foo + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test355-fail.scxml b/tests/scxml/w3c/mandatory/test355-fail.scxml new file mode 100644 index 00000000..1601eeb8 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test355-fail.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test364-fail.scxml b/tests/scxml/w3c/mandatory/test364-fail.scxml new file mode 100644 index 00000000..0a3e5469 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test364-fail.scxml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test372-fail.scxml b/tests/scxml/w3c/mandatory/test372-fail.scxml new file mode 100644 index 00000000..e7cf923d --- /dev/null +++ b/tests/scxml/w3c/mandatory/test372-fail.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test375.scxml b/tests/scxml/w3c/mandatory/test375.scxml new file mode 100644 index 00000000..c4612ab3 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test375.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test376.scxml b/tests/scxml/w3c/mandatory/test376.scxml new file mode 100644 index 00000000..60d0c1ad --- /dev/null +++ b/tests/scxml/w3c/mandatory/test376.scxml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test377-fail.scxml b/tests/scxml/w3c/mandatory/test377-fail.scxml new file mode 100644 index 00000000..7ed4f73e --- /dev/null +++ b/tests/scxml/w3c/mandatory/test377-fail.scxml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test378-fail.scxml b/tests/scxml/w3c/mandatory/test378-fail.scxml new file mode 100644 index 00000000..7a48ad34 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test378-fail.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test387-fail.scxml b/tests/scxml/w3c/mandatory/test387-fail.scxml new file mode 100644 index 00000000..1ece9493 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test387-fail.scxml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test388-fail.scxml b/tests/scxml/w3c/mandatory/test388-fail.scxml new file mode 100644 index 00000000..1fb1153d --- /dev/null +++ b/tests/scxml/w3c/mandatory/test388-fail.scxml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test396-fail.scxml b/tests/scxml/w3c/mandatory/test396-fail.scxml new file mode 100644 index 00000000..a8aeda66 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test396-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test399-fail.scxml b/tests/scxml/w3c/mandatory/test399-fail.scxml new file mode 100644 index 00000000..566dd43a --- /dev/null +++ b/tests/scxml/w3c/mandatory/test399-fail.scxml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test401-fail.scxml b/tests/scxml/w3c/mandatory/test401-fail.scxml new file mode 100644 index 00000000..ac3b2229 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test401-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test402-fail.scxml b/tests/scxml/w3c/mandatory/test402-fail.scxml new file mode 100644 index 00000000..56e997b7 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test402-fail.scxml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test403a-fail.scxml b/tests/scxml/w3c/mandatory/test403a-fail.scxml new file mode 100644 index 00000000..771ca16a --- /dev/null +++ b/tests/scxml/w3c/mandatory/test403a-fail.scxml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test403b-fail.scxml b/tests/scxml/w3c/mandatory/test403b-fail.scxml new file mode 100644 index 00000000..15b354a5 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test403b-fail.scxml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test403c-fail.scxml b/tests/scxml/w3c/mandatory/test403c-fail.scxml new file mode 100644 index 00000000..e3ce184a --- /dev/null +++ b/tests/scxml/w3c/mandatory/test403c-fail.scxml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test404-fail.scxml b/tests/scxml/w3c/mandatory/test404-fail.scxml new file mode 100644 index 00000000..7c9ccb76 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test404-fail.scxml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test405-fail.scxml b/tests/scxml/w3c/mandatory/test405-fail.scxml new file mode 100644 index 00000000..49146384 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test405-fail.scxml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test406-fail.scxml b/tests/scxml/w3c/mandatory/test406-fail.scxml new file mode 100644 index 00000000..7d8862a2 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test406-fail.scxml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test407-fail.scxml b/tests/scxml/w3c/mandatory/test407-fail.scxml new file mode 100644 index 00000000..0e001288 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test407-fail.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test409-fail.scxml b/tests/scxml/w3c/mandatory/test409-fail.scxml new file mode 100644 index 00000000..5b7ddd5e --- /dev/null +++ b/tests/scxml/w3c/mandatory/test409-fail.scxml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test411-fail.scxml b/tests/scxml/w3c/mandatory/test411-fail.scxml new file mode 100644 index 00000000..ae92d718 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test411-fail.scxml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test412-fail.scxml b/tests/scxml/w3c/mandatory/test412-fail.scxml new file mode 100644 index 00000000..ce12d843 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test412-fail.scxml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test413-fail.scxml b/tests/scxml/w3c/mandatory/test413-fail.scxml new file mode 100644 index 00000000..6b0f1db3 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test413-fail.scxml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test416-fail.scxml b/tests/scxml/w3c/mandatory/test416-fail.scxml new file mode 100644 index 00000000..9892ebe9 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test416-fail.scxml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test417-fail.scxml b/tests/scxml/w3c/mandatory/test417-fail.scxml new file mode 100644 index 00000000..d114256b --- /dev/null +++ b/tests/scxml/w3c/mandatory/test417-fail.scxml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test419-fail.scxml b/tests/scxml/w3c/mandatory/test419-fail.scxml new file mode 100644 index 00000000..9d0b527b --- /dev/null +++ b/tests/scxml/w3c/mandatory/test419-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test421-fail.scxml b/tests/scxml/w3c/mandatory/test421-fail.scxml new file mode 100644 index 00000000..c50581aa --- /dev/null +++ b/tests/scxml/w3c/mandatory/test421-fail.scxml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test422-fail.scxml b/tests/scxml/w3c/mandatory/test422-fail.scxml new file mode 100644 index 00000000..667e398b --- /dev/null +++ b/tests/scxml/w3c/mandatory/test422-fail.scxml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test423-fail.scxml b/tests/scxml/w3c/mandatory/test423-fail.scxml new file mode 100644 index 00000000..6d79f169 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test423-fail.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test487-fail.scxml b/tests/scxml/w3c/mandatory/test487-fail.scxml new file mode 100644 index 00000000..4fd6e270 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test487-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test488-fail.scxml b/tests/scxml/w3c/mandatory/test488-fail.scxml new file mode 100644 index 00000000..ebb5b96f --- /dev/null +++ b/tests/scxml/w3c/mandatory/test488-fail.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test495-fail.scxml b/tests/scxml/w3c/mandatory/test495-fail.scxml new file mode 100644 index 00000000..fefbdeec --- /dev/null +++ b/tests/scxml/w3c/mandatory/test495-fail.scxml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test496-fail.scxml b/tests/scxml/w3c/mandatory/test496-fail.scxml new file mode 100644 index 00000000..2f848784 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test496-fail.scxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test500-fail.scxml b/tests/scxml/w3c/mandatory/test500-fail.scxml new file mode 100644 index 00000000..c6baa107 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test500-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test501-fail.scxml b/tests/scxml/w3c/mandatory/test501-fail.scxml new file mode 100644 index 00000000..59641b39 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test501-fail.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test503-fail.scxml b/tests/scxml/w3c/mandatory/test503-fail.scxml new file mode 100644 index 00000000..f5e57bc3 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test503-fail.scxml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test504-fail.scxml b/tests/scxml/w3c/mandatory/test504-fail.scxml new file mode 100644 index 00000000..305c04e1 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test504-fail.scxml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test505-fail.scxml b/tests/scxml/w3c/mandatory/test505-fail.scxml new file mode 100644 index 00000000..db1926f2 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test505-fail.scxml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test506-fail.scxml b/tests/scxml/w3c/mandatory/test506-fail.scxml new file mode 100644 index 00000000..4a478e7d --- /dev/null +++ b/tests/scxml/w3c/mandatory/test506-fail.scxml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test521-fail.scxml b/tests/scxml/w3c/mandatory/test521-fail.scxml new file mode 100644 index 00000000..569938ee --- /dev/null +++ b/tests/scxml/w3c/mandatory/test521-fail.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test525-fail.scxml b/tests/scxml/w3c/mandatory/test525-fail.scxml new file mode 100644 index 00000000..9ab1c012 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test525-fail.scxml @@ -0,0 +1,31 @@ + + + + [1, 2, 3] + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test527-fail.scxml b/tests/scxml/w3c/mandatory/test527-fail.scxml new file mode 100644 index 00000000..37e5984c --- /dev/null +++ b/tests/scxml/w3c/mandatory/test527-fail.scxml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test528-fail.scxml b/tests/scxml/w3c/mandatory/test528-fail.scxml new file mode 100644 index 00000000..947ef0f5 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test528-fail.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test529-fail.scxml b/tests/scxml/w3c/mandatory/test529-fail.scxml new file mode 100644 index 00000000..9012d26a --- /dev/null +++ b/tests/scxml/w3c/mandatory/test529-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + 21 + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test530-fail.scxml b/tests/scxml/w3c/mandatory/test530-fail.scxml new file mode 100644 index 00000000..30a3254b --- /dev/null +++ b/tests/scxml/w3c/mandatory/test530-fail.scxml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test533-fail.scxml b/tests/scxml/w3c/mandatory/test533-fail.scxml new file mode 100644 index 00000000..9fa6faef --- /dev/null +++ b/tests/scxml/w3c/mandatory/test533-fail.scxml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test550.scxml b/tests/scxml/w3c/mandatory/test550.scxml new file mode 100644 index 00000000..d4874242 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test550.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test551.scxml b/tests/scxml/w3c/mandatory/test551.scxml new file mode 100644 index 00000000..a84190a1 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test551.scxml @@ -0,0 +1,28 @@ + + + + + 123 + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test552-fail.scxml b/tests/scxml/w3c/mandatory/test552-fail.scxml new file mode 100644 index 00000000..e46f6543 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test552-fail.scxml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test552.txt b/tests/scxml/w3c/mandatory/test552.txt new file mode 100644 index 00000000..af801f43 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test552.txt @@ -0,0 +1 @@ + diff --git a/tests/scxml/w3c/mandatory/test553-fail.scxml b/tests/scxml/w3c/mandatory/test553-fail.scxml new file mode 100644 index 00000000..68c8c366 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test553-fail.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test554-fail.scxml b/tests/scxml/w3c/mandatory/test554-fail.scxml new file mode 100644 index 00000000..fa370e25 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test554-fail.scxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test570-fail.scxml b/tests/scxml/w3c/mandatory/test570-fail.scxml new file mode 100644 index 00000000..81723b27 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test570-fail.scxml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test576-fail.scxml b/tests/scxml/w3c/mandatory/test576-fail.scxml new file mode 100644 index 00000000..e2ae3371 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test576-fail.scxml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test579-fail.scxml b/tests/scxml/w3c/mandatory/test579-fail.scxml new file mode 100644 index 00000000..12fa1952 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test579-fail.scxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/mandatory/test580-fail.scxml b/tests/scxml/w3c/mandatory/test580-fail.scxml new file mode 100644 index 00000000..d8a61af8 --- /dev/null +++ b/tests/scxml/w3c/mandatory/test580-fail.scxml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test193.scxml b/tests/scxml/w3c/optional/test193.scxml new file mode 100644 index 00000000..d9496c19 --- /dev/null +++ b/tests/scxml/w3c/optional/test193.scxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test201-fail.scxml b/tests/scxml/w3c/optional/test201-fail.scxml new file mode 100644 index 00000000..de31c22e --- /dev/null +++ b/tests/scxml/w3c/optional/test201-fail.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test278.scxml b/tests/scxml/w3c/optional/test278.scxml new file mode 100644 index 00000000..81f8ec26 --- /dev/null +++ b/tests/scxml/w3c/optional/test278.scxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test444.scxml b/tests/scxml/w3c/optional/test444.scxml new file mode 100644 index 00000000..1d45b46b --- /dev/null +++ b/tests/scxml/w3c/optional/test444.scxml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test445.scxml b/tests/scxml/w3c/optional/test445.scxml new file mode 100644 index 00000000..90fad6e4 --- /dev/null +++ b/tests/scxml/w3c/optional/test445.scxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test446-fail.scxml b/tests/scxml/w3c/optional/test446-fail.scxml new file mode 100644 index 00000000..55ed6677 --- /dev/null +++ b/tests/scxml/w3c/optional/test446-fail.scxml @@ -0,0 +1,28 @@ + + + + + [1, 2, 3] + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test446.txt b/tests/scxml/w3c/optional/test446.txt new file mode 100644 index 00000000..3cc0ecbe --- /dev/null +++ b/tests/scxml/w3c/optional/test446.txt @@ -0,0 +1 @@ +[1,2,3] diff --git a/tests/scxml/w3c/optional/test448-fail.scxml b/tests/scxml/w3c/optional/test448-fail.scxml new file mode 100644 index 00000000..183b8965 --- /dev/null +++ b/tests/scxml/w3c/optional/test448-fail.scxml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test449.scxml b/tests/scxml/w3c/optional/test449.scxml new file mode 100644 index 00000000..8bfea009 --- /dev/null +++ b/tests/scxml/w3c/optional/test449.scxml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test451-fail.scxml b/tests/scxml/w3c/optional/test451-fail.scxml new file mode 100644 index 00000000..beaca3e4 --- /dev/null +++ b/tests/scxml/w3c/optional/test451-fail.scxml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test452.scxml b/tests/scxml/w3c/optional/test452.scxml new file mode 100644 index 00000000..60d81470 --- /dev/null +++ b/tests/scxml/w3c/optional/test452.scxml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test453.scxml b/tests/scxml/w3c/optional/test453.scxml new file mode 100644 index 00000000..8040cb84 --- /dev/null +++ b/tests/scxml/w3c/optional/test453.scxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test456.scxml b/tests/scxml/w3c/optional/test456.scxml new file mode 100644 index 00000000..2683ba9a --- /dev/null +++ b/tests/scxml/w3c/optional/test456.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test457.scxml b/tests/scxml/w3c/optional/test457.scxml new file mode 100644 index 00000000..bbe09a7d --- /dev/null +++ b/tests/scxml/w3c/optional/test457.scxml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test459.scxml b/tests/scxml/w3c/optional/test459.scxml new file mode 100644 index 00000000..9b278951 --- /dev/null +++ b/tests/scxml/w3c/optional/test459.scxml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test460.scxml b/tests/scxml/w3c/optional/test460.scxml new file mode 100644 index 00000000..ad1aed1d --- /dev/null +++ b/tests/scxml/w3c/optional/test460.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test509-fail.scxml b/tests/scxml/w3c/optional/test509-fail.scxml new file mode 100644 index 00000000..f8e13dc5 --- /dev/null +++ b/tests/scxml/w3c/optional/test509-fail.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test510-fail.scxml b/tests/scxml/w3c/optional/test510-fail.scxml new file mode 100644 index 00000000..052761d0 --- /dev/null +++ b/tests/scxml/w3c/optional/test510-fail.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test518-fail.scxml b/tests/scxml/w3c/optional/test518-fail.scxml new file mode 100644 index 00000000..3291f888 --- /dev/null +++ b/tests/scxml/w3c/optional/test518-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test519-fail.scxml b/tests/scxml/w3c/optional/test519-fail.scxml new file mode 100644 index 00000000..e13def86 --- /dev/null +++ b/tests/scxml/w3c/optional/test519-fail.scxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test520-fail.scxml b/tests/scxml/w3c/optional/test520-fail.scxml new file mode 100644 index 00000000..04af8bce --- /dev/null +++ b/tests/scxml/w3c/optional/test520-fail.scxml @@ -0,0 +1,31 @@ + + + + + + + + this is some content + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test522.scxml b/tests/scxml/w3c/optional/test522.scxml new file mode 100644 index 00000000..d1d22262 --- /dev/null +++ b/tests/scxml/w3c/optional/test522.scxml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test531-fail.scxml b/tests/scxml/w3c/optional/test531-fail.scxml new file mode 100644 index 00000000..38d30dd7 --- /dev/null +++ b/tests/scxml/w3c/optional/test531-fail.scxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test532-fail.scxml b/tests/scxml/w3c/optional/test532-fail.scxml new file mode 100644 index 00000000..20872c36 --- /dev/null +++ b/tests/scxml/w3c/optional/test532-fail.scxml @@ -0,0 +1,28 @@ + + + + + + + + + some content + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test534-fail.scxml b/tests/scxml/w3c/optional/test534-fail.scxml new file mode 100644 index 00000000..f3079185 --- /dev/null +++ b/tests/scxml/w3c/optional/test534-fail.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test557-fail.scxml b/tests/scxml/w3c/optional/test557-fail.scxml new file mode 100644 index 00000000..379113a2 --- /dev/null +++ b/tests/scxml/w3c/optional/test557-fail.scxml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test557.txt b/tests/scxml/w3c/optional/test557.txt new file mode 100644 index 00000000..1344d3aa --- /dev/null +++ b/tests/scxml/w3c/optional/test557.txt @@ -0,0 +1,4 @@ + + + + diff --git a/tests/scxml/w3c/optional/test558-fail.scxml b/tests/scxml/w3c/optional/test558-fail.scxml new file mode 100644 index 00000000..231d345a --- /dev/null +++ b/tests/scxml/w3c/optional/test558-fail.scxml @@ -0,0 +1,33 @@ + + + + + this is + a string + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test558.txt b/tests/scxml/w3c/optional/test558.txt new file mode 100644 index 00000000..fcbd22ab --- /dev/null +++ b/tests/scxml/w3c/optional/test558.txt @@ -0,0 +1,3 @@ + +this is +a string diff --git a/tests/scxml/w3c/optional/test560.scxml b/tests/scxml/w3c/optional/test560.scxml new file mode 100644 index 00000000..fa9b3075 --- /dev/null +++ b/tests/scxml/w3c/optional/test560.scxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test561-fail.scxml b/tests/scxml/w3c/optional/test561-fail.scxml new file mode 100644 index 00000000..050919fd --- /dev/null +++ b/tests/scxml/w3c/optional/test561-fail.scxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test562.scxml b/tests/scxml/w3c/optional/test562.scxml new file mode 100644 index 00000000..58cf99dd --- /dev/null +++ b/tests/scxml/w3c/optional/test562.scxml @@ -0,0 +1,28 @@ + + + + + + + this is a + string + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test567-fail.scxml b/tests/scxml/w3c/optional/test567-fail.scxml new file mode 100644 index 00000000..d25c0b2d --- /dev/null +++ b/tests/scxml/w3c/optional/test567-fail.scxml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test569.scxml b/tests/scxml/w3c/optional/test569.scxml new file mode 100644 index 00000000..9291e845 --- /dev/null +++ b/tests/scxml/w3c/optional/test569.scxml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test577-fail.scxml b/tests/scxml/w3c/optional/test577-fail.scxml new file mode 100644 index 00000000..678b5f07 --- /dev/null +++ b/tests/scxml/w3c/optional/test577-fail.scxml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/scxml/w3c/optional/test578.scxml b/tests/scxml/w3c/optional/test578.scxml new file mode 100644 index 00000000..e6302f07 --- /dev/null +++ b/tests/scxml/w3c/optional/test578.scxml @@ -0,0 +1,25 @@ + + + + + + { "productName" : "bar", "size" : 27 } + + + + + + + + + + + + + + + + diff --git a/tests/w3c_tests/conftest.py b/tests/w3c_tests/conftest.py deleted file mode 100644 index c68792d3..00000000 --- a/tests/w3c_tests/conftest.py +++ /dev/null @@ -1,49 +0,0 @@ -from pathlib import Path - -import pytest - -CURRENT_DIR = Path(__file__).parent -TESTCASES_DIR = CURRENT_DIR / "testcases" -SUPPORTED_EXTENSIONS = "scxml" - - -@pytest.fixture() -def sm_class(testcase_path: Path): - """ - Construct a StateMachine class from the SCXML file - """ - from statemachine.io import create_machine_class_from_definition - from statemachine.io.scxml import parse_scxml - - # Read SCXML content - scxml_content = testcase_path.read_text() - - # Parse SCXML into dictionary format - definition = parse_scxml(scxml_content) - - # Create state machine class - try: - return create_machine_class_from_definition(testcase_path.stem, **definition) - except Exception as e: - raise Exception( - f"Failed to create state machine class: {e} from definition: {definition}" - ) from e - - -def pytest_generate_tests(metafunc): - if "testcase_path" not in metafunc.fixturenames: - return - - fail_marks = [pytest.mark.xfail] - - metafunc.parametrize( - "testcase_path", - [ - pytest.param( - testcase_path, - id=str(testcase_path.name), - marks=fail_marks if "fail" in testcase_path.name else [], - ) - for testcase_path in TESTCASES_DIR.glob("**/*.scxml") - ], - ) From 7664c1e7d465acbd6abac6935c33c98fa4420f49 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Tue, 3 Dec 2024 00:27:36 -0300 Subject: [PATCH 13/45] feat: Support for SCXML <_event.name> --- statemachine/io/scxml.py | 4 ++++ .../scxml/w3c/mandatory/{test318-fail.scxml => test318.scxml} | 0 .../scxml/w3c/mandatory/{test342-fail.scxml => test342.scxml} | 0 .../scxml/w3c/mandatory/{test396-fail.scxml => test396.scxml} | 0 4 files changed, 4 insertions(+) rename tests/scxml/w3c/mandatory/{test318-fail.scxml => test318.scxml} (100%) rename tests/scxml/w3c/mandatory/{test342-fail.scxml => test342.scxml} (100%) rename tests/scxml/w3c/mandatory/{test396-fail.scxml => test396.scxml} (100%) diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py index 9b215c69..5bcddf11 100644 --- a/statemachine/io/scxml.py +++ b/statemachine/io/scxml.py @@ -41,6 +41,10 @@ def __init__(self, event_data): def __getattr__(self, name): return getattr(self.event_data, name) + @property + def name(self): + return self.event_data.event + @property def data(self): "Property used by the SCXML namespace" diff --git a/tests/scxml/w3c/mandatory/test318-fail.scxml b/tests/scxml/w3c/mandatory/test318.scxml similarity index 100% rename from tests/scxml/w3c/mandatory/test318-fail.scxml rename to tests/scxml/w3c/mandatory/test318.scxml diff --git a/tests/scxml/w3c/mandatory/test342-fail.scxml b/tests/scxml/w3c/mandatory/test342.scxml similarity index 100% rename from tests/scxml/w3c/mandatory/test342-fail.scxml rename to tests/scxml/w3c/mandatory/test342.scxml diff --git a/tests/scxml/w3c/mandatory/test396-fail.scxml b/tests/scxml/w3c/mandatory/test396.scxml similarity index 100% rename from tests/scxml/w3c/mandatory/test396-fail.scxml rename to tests/scxml/w3c/mandatory/test396.scxml From d9024aff1e14aece08ec29c2e2554230cfda45c8 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Tue, 3 Dec 2024 09:23:52 -0300 Subject: [PATCH 14/45] chore: Drop support for Python3.7 and 3.8 due to the lack of support for TypedDict and | operator --- .github/ISSUE_TEMPLATE.md | 2 + .github/workflows/python-package.yml | 6 +- pyproject.toml | 22 +- statemachine/io/__init__.py | 48 +++- uv.lock | 348 +++++++-------------------- 5 files changed, 148 insertions(+), 278 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 74705aa7..ab560ec6 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -13,3 +13,5 @@ Tell us what happened, what went wrong, and what you expected to happen. Paste the command(s) you ran and the output. If there was a crash, please include the traceback here. ``` + +If you're reporting a bug, consider providing a complete example that can be used directly in the automated tests. We allways write tests to reproduce the issue in order to avoid future regressions. diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index fdc758d6..4fd41910 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 @@ -33,10 +33,6 @@ jobs: cache-suffix: "python${{ matrix.python-version }}" - name: Install the project run: uv sync --all-extras --dev - - name: Install old pydot for 3.7 only - if: matrix.python-version == 3.7 - run: | - uv pip install pydot==2.0.0 #---------------------------------------------- # run ruff #---------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 29ba42d9..2f4a5b75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,13 +17,11 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Topic :: Home Automation", "Topic :: Software Development :: Libraries", ] -requires-python = ">=3.7" +requires-python = ">=3.9" [project.urls] homepage = "https://github.com/fgmacedo/python-statemachine" @@ -45,15 +43,15 @@ dev = [ "pydot", "pydot", "django >=5.0.8; python_version >='3.10'", - "pytest-django >=4.8.0; python_version >'3.8'", - "Sphinx; python_version >'3.8'", - "sphinx-gallery; python_version >'3.8'", - "myst-parser; python_version >'3.8'", - "pillow; python_version >'3.8'", - "sphinx-autobuild; python_version >'3.8'", - "furo >=2024.5.6; python_version >'3.8'", - "sphinx-copybutton >=0.5.2; python_version >'3.8'", - "pdbr>=0.8.9; python_version >='3.8'", + "pytest-django >=4.8.0", + "Sphinx", + "sphinx-gallery", + "myst-parser", + "pillow", + "sphinx-autobuild", + "furo >=2024.5.6", + "sphinx-copybutton >=0.5.2", + "pdbr>=0.8.9", ] [build-system] diff --git a/statemachine/io/__init__.py b/statemachine/io/__init__.py index 696642ad..14c06d38 100644 --- a/statemachine/io/__init__.py +++ b/statemachine/io/__init__.py @@ -1,12 +1,50 @@ +from typing import Any +from typing import Callable from typing import Dict +from typing import List +from typing import Mapping +from typing import TypedDict +from typing import cast from ..factory import StateMachineMetaclass from ..state import State from ..statemachine import StateMachine from ..transition_list import TransitionList +CallbacksType = str | Callable | List[str] | List[Callable] -def create_machine_class_from_definition(name: str, **definition) -> StateMachine: # noqa: C901 + +class TransitionDict(TypedDict, total=False): + target: str + event: str + internal: bool + validators: bool + cond: CallbacksType + unless: CallbacksType + on: CallbacksType + before: CallbacksType + after: CallbacksType + + +class StateDict(TypedDict, total=False): + name: str + value: Any + initial: bool + final: bool + enter: CallbacksType + exit: CallbacksType + + +class StateWithTransitionsDict(StateDict, total=False): + on: Dict[str, List[TransitionDict]] + + +StateOptions = StateDict | StateWithTransitionsDict + + +def create_machine_class_from_definition( + name: str, states: Mapping[str, StateOptions], **definition +) -> StateMachine: # noqa: C901 """ Creates a StateMachine class from a dictionary definition, using the StateMachineMetaclass. @@ -27,10 +65,10 @@ def create_machine_class_from_definition(name: str, **definition) -> StateMachin states_instances: Dict[str, State] = {} events_definitions: Dict[str, dict] = {} - for state_id, state_kwargs in definition.pop("states").items(): - on_events = state_kwargs.pop("on", {}) - if on_events: - events_definitions[state_id] = on_events + for state_id, state_kwargs in states.items(): + transition_definitions = cast(StateWithTransitionsDict, state_kwargs).pop("on", {}) + if transition_definitions: + events_definitions[state_id] = transition_definitions states_instances[state_id] = State(**state_kwargs) diff --git a/uv.lock b/uv.lock index 9f04324f..2410d2fd 100644 --- a/uv.lock +++ b/uv.lock @@ -1,11 +1,8 @@ version = 1 -requires-python = ">=3.7" +requires-python = ">=3.9" resolution-markers = [ - "python_full_version < '3.8'", - "python_full_version == '3.8.*'", - "python_full_version == '3.9.*'", - "python_full_version == '3.10.*'", - "python_full_version >= '3.11'", + "python_full_version < '3.10'", + "python_full_version >= '3.10'", ] [[package]] @@ -22,10 +19,10 @@ name = "anyio" version = "4.6.2.post1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, - { name = "idna", marker = "python_full_version >= '3.9'" }, - { name = "sniffio", marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/09/45b9b7a6d4e45c6bcb5bf61d19e3ab87df68e0601fa8c5293de3542546cc/anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", size = 173422 } wheels = [ @@ -58,7 +55,7 @@ name = "beautifulsoup4" version = "4.12.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "soupsieve", marker = "python_full_version >= '3.9'" }, + { name = "soupsieve" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/ca/824b1195773ce6166d388573fc106ce56d4a805bd7427b624e063596ec58/beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051", size = 581181 } wheels = [ @@ -149,34 +146,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d8/90/6af4cd042066a4adad58ae25648a12c09c879efa4849c705719ba1b23d8c/charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482", size = 144970 }, { url = "https://files.pythonhosted.org/packages/cc/67/e5e7e0cbfefc4ca79025238b43cdf8a2037854195b37d6417f3d0895c4c2/charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", size = 94973 }, { url = "https://files.pythonhosted.org/packages/65/97/fc9bbc54ee13d33dc54a7fcf17b26368b18505500fc01e228c27b5222d80/charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", size = 102308 }, - { url = "https://files.pythonhosted.org/packages/28/9b/64f11b42d34a9f1fcd05827dd695e91e0b30ac35a9a7aaeb93e84d9f8c76/charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2", size = 121758 }, - { url = "https://files.pythonhosted.org/packages/1f/18/0fc3d61a244ffdee01374b751387f9154ecb8a4d5f931227ecfd31ab46f0/charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7", size = 134949 }, - { url = "https://files.pythonhosted.org/packages/3f/b5/354d544f60614aeb6bf73d3b6c955933e0af5eeaf2eec8c0637293a995bc/charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51", size = 144221 }, - { url = "https://files.pythonhosted.org/packages/93/5f/a2acc6e2a47d053760caece2d7b7194e9949945091eff452019765b87146/charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574", size = 137301 }, - { url = "https://files.pythonhosted.org/packages/27/9f/68c828438af904d830e680a8d2f6182be97f3205d6d62edfeb4a029b4192/charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf", size = 138257 }, - { url = "https://files.pythonhosted.org/packages/27/4b/522e1c868960b6be2f88cd407a284f99801421a6c5ae214f0c33de131fde/charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455", size = 140933 }, - { url = "https://files.pythonhosted.org/packages/03/f8/f9b90f5aed190d63e620d9f61db1cef5f30dbb19075e5c114329483d069a/charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6", size = 134954 }, - { url = "https://files.pythonhosted.org/packages/0f/8e/44cde4d583038cbe37867efe7af4699212e6104fca0e7fc010e5f3d4a5c9/charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748", size = 142158 }, - { url = "https://files.pythonhosted.org/packages/28/2c/c6c5b3d70a9e09fcde6b0901789d8c3c2f44ef12abae070a33a342d239a9/charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62", size = 145701 }, - { url = "https://files.pythonhosted.org/packages/1c/9d/fb7f6b68f88e8becca86eb7cba1d5a5429fbfaaa6dd7a3a9f62adaee44d3/charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4", size = 144846 }, - { url = "https://files.pythonhosted.org/packages/b2/8d/fb3d3d3d5a09202d7ef1983848b41a5928b0c907e5692a8d13b1c07a10de/charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621", size = 138254 }, - { url = "https://files.pythonhosted.org/packages/28/d3/efc854ab04626167ad1709e527c4f2a01f5e5cd9c1d5691094d1b7d49154/charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149", size = 93163 }, - { url = "https://files.pythonhosted.org/packages/b6/33/cf8f2602715863219804c1790374b611f08be515176229de078f807d71e3/charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee", size = 99861 }, - { url = "https://files.pythonhosted.org/packages/86/f4/ccab93e631e7293cca82f9f7ba39783c967f823a0000df2d8dd743cad74f/charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578", size = 193961 }, - { url = "https://files.pythonhosted.org/packages/94/d4/2b21cb277bac9605026d2d91a4a8872bc82199ed11072d035dc674c27223/charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6", size = 124507 }, - { url = "https://files.pythonhosted.org/packages/9a/e0/a7c1fcdff20d9c667342e0391cfeb33ab01468d7d276b2c7914b371667cc/charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417", size = 119298 }, - { url = "https://files.pythonhosted.org/packages/70/de/1538bb2f84ac9940f7fa39945a5dd1d22b295a89c98240b262fc4b9fcfe0/charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51", size = 139328 }, - { url = "https://files.pythonhosted.org/packages/e9/ca/288bb1a6bc2b74fb3990bdc515012b47c4bc5925c8304fc915d03f94b027/charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41", size = 149368 }, - { url = "https://files.pythonhosted.org/packages/aa/75/58374fdaaf8406f373e508dab3486a31091f760f99f832d3951ee93313e8/charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f", size = 141944 }, - { url = "https://files.pythonhosted.org/packages/32/c8/0bc558f7260db6ffca991ed7166494a7da4fda5983ee0b0bfc8ed2ac6ff9/charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8", size = 143326 }, - { url = "https://files.pythonhosted.org/packages/0e/dd/7f6fec09a1686446cee713f38cf7d5e0669e0bcc8288c8e2924e998cf87d/charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab", size = 146171 }, - { url = "https://files.pythonhosted.org/packages/4c/a8/440f1926d6d8740c34d3ca388fbd718191ec97d3d457a0677eb3aa718fce/charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12", size = 139711 }, - { url = "https://files.pythonhosted.org/packages/e9/7f/4b71e350a3377ddd70b980bea1e2cc0983faf45ba43032b24b2578c14314/charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19", size = 148348 }, - { url = "https://files.pythonhosted.org/packages/1e/70/17b1b9202531a33ed7ef41885f0d2575ae42a1e330c67fddda5d99ad1208/charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea", size = 151290 }, - { url = "https://files.pythonhosted.org/packages/44/30/574b5b5933d77ecb015550aafe1c7d14a8cd41e7e6c4dcea5ae9e8d496c3/charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858", size = 149114 }, - { url = "https://files.pythonhosted.org/packages/0b/11/ca7786f7e13708687443082af20d8341c02e01024275a28bc75032c5ce5d/charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654", size = 143856 }, - { url = "https://files.pythonhosted.org/packages/f9/c2/1727c1438256c71ed32753b23ec2e6fe7b6dff66a598f6566cfe8139305e/charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613", size = 94333 }, - { url = "https://files.pythonhosted.org/packages/09/c8/0e17270496a05839f8b500c1166e3261d1226e39b698a735805ec206967b/charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade", size = 101454 }, { url = "https://files.pythonhosted.org/packages/54/2f/28659eee7f5d003e0f5a3b572765bf76d6e0fe6601ab1f1b1dd4cba7e4f1/charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa", size = 196326 }, { url = "https://files.pythonhosted.org/packages/d1/18/92869d5c0057baa973a3ee2af71573be7b084b3c3d428fe6463ce71167f8/charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a", size = 125614 }, { url = "https://files.pythonhosted.org/packages/d6/27/327904c5a54a7796bb9f36810ec4173d2df5d88b401d2b95ef53111d214e/charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0", size = 120450 }, @@ -200,7 +169,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.9' and platform_system == 'Windows'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -260,25 +229,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/5c/d9760ac497c41f9c4841f5972d0edf05d50cad7814e86ee7d133ec4a0ac8/coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d", size = 239833 }, { url = "https://files.pythonhosted.org/packages/69/8c/26a95b08059db1cbb01e4b0e6d40f2e9debb628c6ca86b78f625ceaf9bab/coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511", size = 203463 }, { url = "https://files.pythonhosted.org/packages/b7/00/14b00a0748e9eda26e97be07a63cc911108844004687321ddcc213be956c/coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3", size = 204347 }, - { url = "https://files.pythonhosted.org/packages/80/d7/67937c80b8fd4c909fdac29292bc8b35d9505312cff6bcab41c53c5b1df6/coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f", size = 200580 }, - { url = "https://files.pythonhosted.org/packages/7a/05/084864fa4bbf8106f44fb72a56e67e0cd372d3bf9d893be818338c81af5d/coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb", size = 226237 }, - { url = "https://files.pythonhosted.org/packages/67/a2/6fa66a50e6e894286d79a3564f42bd54a9bd27049dc0a63b26d9924f0aa3/coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9", size = 224256 }, - { url = "https://files.pythonhosted.org/packages/e2/c0/73f139794c742840b9ab88e2e17fe14a3d4668a166ff95d812ac66c0829d/coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd", size = 225550 }, - { url = "https://files.pythonhosted.org/packages/03/ec/6f30b4e0c96ce03b0e64aec46b4af2a8c49b70d1b5d0d69577add757b946/coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a", size = 232440 }, - { url = "https://files.pythonhosted.org/packages/22/c1/2f6c1b6f01a0996c9e067a9c780e1824351dbe17faae54388a4477e6d86f/coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959", size = 230897 }, - { url = "https://files.pythonhosted.org/packages/8d/d6/53e999ec1bf7498ca4bc5f3b8227eb61db39068d2de5dcc359dec5601b5a/coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02", size = 232024 }, - { url = "https://files.pythonhosted.org/packages/e9/40/383305500d24122dbed73e505a4d6828f8f3356d1f68ab6d32c781754b81/coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f", size = 203293 }, - { url = "https://files.pythonhosted.org/packages/0e/bc/7e3a31534fabb043269f14fb64e2bb2733f85d4cf39e5bbc71357c57553a/coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0", size = 204040 }, - { url = "https://files.pythonhosted.org/packages/c6/fc/be19131010930a6cf271da48202c8cc1d3f971f68c02fb2d3a78247f43dc/coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5", size = 200689 }, - { url = "https://files.pythonhosted.org/packages/28/d7/9a8de57d87f4bbc6f9a6a5ded1eaac88a89bf71369bb935dac3c0cf2893e/coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5", size = 200986 }, - { url = "https://files.pythonhosted.org/packages/c8/e4/e6182e4697665fb594a7f4e4f27cb3a4dd00c2e3d35c5c706765de8c7866/coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9", size = 230648 }, - { url = "https://files.pythonhosted.org/packages/7b/e3/f552d5871943f747165b92a924055c5d6daa164ae659a13f9018e22f3990/coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6", size = 228511 }, - { url = "https://files.pythonhosted.org/packages/44/55/49f65ccdd4dfd6d5528e966b28c37caec64170c725af32ab312889d2f857/coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e", size = 229852 }, - { url = "https://files.pythonhosted.org/packages/0d/31/340428c238eb506feb96d4fb5c9ea614db1149517f22cc7ab8c6035ef6d9/coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050", size = 235578 }, - { url = "https://files.pythonhosted.org/packages/dd/ce/97c1dd6592c908425622fe7f31c017d11cf0421729b09101d4de75bcadc8/coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5", size = 234079 }, - { url = "https://files.pythonhosted.org/packages/de/a3/5a98dc9e239d0dc5f243ef5053d5b1bdcaa1dee27a691dfc12befeccf878/coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f", size = 234991 }, - { url = "https://files.pythonhosted.org/packages/4a/fb/78986d3022e5ccf2d4370bc43a5fef8374f092b3c21d32499dee8e30b7b6/coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e", size = 203160 }, - { url = "https://files.pythonhosted.org/packages/c3/1c/6b3c9c363fb1433c79128e0d692863deb761b1b78162494abb9e5c328bc0/coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c", size = 204085 }, { url = "https://files.pythonhosted.org/packages/88/da/495944ebf0ad246235a6bd523810d9f81981f9b81c6059ba1f56e943abe0/coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9", size = 200725 }, { url = "https://files.pythonhosted.org/packages/ca/0c/3dfeeb1006c44b911ee0ed915350db30325d01808525ae7cc8d57643a2ce/coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2", size = 201022 }, { url = "https://files.pythonhosted.org/packages/61/af/5964b8d7d9a5c767785644d9a5a63cacba9a9c45cc42ba06d25895ec87be/coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7", size = 229102 }, @@ -352,10 +302,11 @@ name = "furo" version = "2024.8.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "beautifulsoup4", marker = "python_full_version >= '3.9'" }, - { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "sphinx", marker = "python_full_version >= '3.9'" }, - { name = "sphinx-basic-ng", marker = "python_full_version >= '3.9'" }, + { name = "beautifulsoup4" }, + { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "sphinx" }, + { name = "sphinx-basic-ng" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a0/e2/d351d69a9a9e4badb4a5be062c2d0e87bd9e6c23b5e57337fef14bef34c8/furo-2024.8.6.tar.gz", hash = "sha256:b63e4cee8abfc3136d3bc03a3d45a76a850bada4d6374d24c1716b0e01394a01", size = 1661506 } wheels = [ @@ -403,8 +354,7 @@ name = "importlib-metadata" version = "6.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.8'" }, - { name = "zipp", marker = "python_full_version < '3.8' or python_full_version == '3.9.*'" }, + { name = "zipp", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } wheels = [ @@ -425,7 +375,7 @@ name = "jinja2" version = "3.1.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", marker = "python_full_version >= '3.9'" }, + { name = "markupsafe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } wheels = [ @@ -437,7 +387,7 @@ name = "markdown-it-py" version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "mdurl", marker = "python_full_version >= '3.9'" }, + { name = "mdurl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } wheels = [ @@ -517,7 +467,7 @@ name = "mdit-py-plugins" version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown-it-py", marker = "python_full_version >= '3.9'" }, + { name = "markdown-it-py" }, ] sdist = { url = "https://files.pythonhosted.org/packages/19/03/a2ecab526543b152300717cf232bb4bb8605b6edb946c845016fa9c9c9fd/mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5", size = 43542 } wheels = [ @@ -540,7 +490,6 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typed-ast", marker = "python_full_version < '3.8'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/28/d8a8233ff167d06108e53b7aefb4a8d7350adbbf9d7abd980f17fdb7a3a6/mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b", size = 2855162 } @@ -555,15 +504,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/73/72/dfc0b46e6905eafd598e7c48c0c4f2e232647e4e36547425c64e6c850495/mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2", size = 11855450 }, { url = "https://files.pythonhosted.org/packages/66/f4/60739a2d336f3adf5628e7c9b920d16e8af6dc078550d615e4ba2a1d7759/mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7", size = 11928679 }, { url = "https://files.pythonhosted.org/packages/8c/26/6ff2b55bf8b605a4cc898883654c2ca4dd4feedf0bb04ecaacf60d165cde/mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01", size = 8831134 }, - { url = "https://files.pythonhosted.org/packages/95/47/fb69dad9634af9f1dab69f8b4031d674592384b59c7171852b1fbed6de15/mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b", size = 10101278 }, - { url = "https://files.pythonhosted.org/packages/65/f7/77339904a3415cadca5551f2ea0c74feefc9b7187636a292690788f4d4b3/mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b", size = 11643877 }, - { url = "https://files.pythonhosted.org/packages/f5/93/ae39163ae84266d24d1fcf8ee1e2db1e0346e09de97570dd101a07ccf876/mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7", size = 11702718 }, - { url = "https://files.pythonhosted.org/packages/13/3b/3b7de921626547b36c34b91c74cfbda260210df7c49bd3d315015cfd6005/mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9", size = 8551181 }, - { url = "https://files.pythonhosted.org/packages/49/7d/63bab763e4d44e1a7c341fb64496ddf20970780935596ffed9ed2d85eae7/mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042", size = 10390236 }, - { url = "https://files.pythonhosted.org/packages/23/3f/54a87d933440416a1efd7a42b45f8cf22e353efe889eb3903cc34177ab44/mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3", size = 9496760 }, - { url = "https://files.pythonhosted.org/packages/4e/89/26230b46e27724bd54f76cd73a2759eaaf35292b32ba64f36c7c47836d4b/mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6", size = 11927489 }, - { url = "https://files.pythonhosted.org/packages/64/7d/156e721376951c449554942eedf4d53e9ca2a57e94bf0833ad2821d59bfa/mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f", size = 11990009 }, - { url = "https://files.pythonhosted.org/packages/27/ab/21230851e8137c9ef9a095cc8cb70d8ff8cac21014e4b249ac7a9eae7df9/mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc", size = 8816535 }, { url = "https://files.pythonhosted.org/packages/1d/1b/9050b5c444ef82c3d59bdbf21f91b259cf20b2ac1df37d55bc6b91d609a1/mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828", size = 10447897 }, { url = "https://files.pythonhosted.org/packages/da/00/ac2b58b321d85cac25be0dcd1bc2427dfc6cf403283fc205a0031576f14b/mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3", size = 9534091 }, { url = "https://files.pythonhosted.org/packages/c4/10/26240f14e854a95af87d577b288d607ebe0ccb75cb37052f6386402f022d/mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816", size = 11970165 }, @@ -586,12 +526,12 @@ name = "myst-parser" version = "3.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docutils", marker = "python_full_version >= '3.9'" }, - { name = "jinja2", marker = "python_full_version >= '3.9'" }, - { name = "markdown-it-py", marker = "python_full_version >= '3.9'" }, - { name = "mdit-py-plugins", marker = "python_full_version >= '3.9'" }, - { name = "pyyaml", marker = "python_full_version >= '3.9'" }, - { name = "sphinx", marker = "python_full_version >= '3.9'" }, + { name = "docutils" }, + { name = "jinja2" }, + { name = "markdown-it-py" }, + { name = "mdit-py-plugins" }, + { name = "pyyaml" }, + { name = "sphinx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/49/64/e2f13dac02f599980798c01156393b781aec983b52a6e4057ee58f07c43a/myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87", size = 92392 } wheels = [ @@ -621,8 +561,8 @@ name = "pdbr" version = "0.8.9" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pyreadline3", marker = "python_full_version >= '3.8' and sys_platform == 'win32'" }, - { name = "rich", marker = "python_full_version >= '3.8'" }, + { name = "pyreadline3", marker = "sys_platform == 'win32'" }, + { name = "rich" }, ] sdist = { url = "https://files.pythonhosted.org/packages/29/1d/40420fda7c53fd071d8f62dcdb550c9f82fee54c2fda6842337890d87334/pdbr-0.8.9.tar.gz", hash = "sha256:3e0e1fb78761402bcfc0713a9c73acc2f639406b1b8da7233c442b965eee009d", size = 15942 } wheels = [ @@ -715,9 +655,6 @@ wheels = [ name = "platformdirs" version = "4.0.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.8'" }, -] sdist = { url = "https://files.pythonhosted.org/packages/31/28/e40d24d2e2eb23135f8533ad33d582359c7825623b1e022f9d460def7c05/platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731", size = 19914 } wheels = [ { url = "https://files.pythonhosted.org/packages/31/16/70be3b725073035aa5fc3229321d06e22e73e3e09f6af78dcfdf16c7636c/platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", size = 17562 }, @@ -728,12 +665,7 @@ name = "pluggy" version = "1.2.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.8'", - "python_full_version == '3.8.*'", - "python_full_version == '3.9.*'", -] -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.8'" }, + "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/8a/42/8f2833655a29c4e9cb52ee8a2be04ceac61bcff4a680fb338cbd3d1e322d/pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3", size = 61613 } wheels = [ @@ -745,8 +677,7 @@ name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.10.*'", - "python_full_version >= '3.11'", + "python_full_version >= '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } wheels = [ @@ -760,7 +691,6 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, { name = "identify" }, - { name = "importlib-metadata", marker = "python_full_version < '3.8'" }, { name = "nodeenv" }, { name = "pyyaml" }, { name = "virtualenv" }, @@ -796,7 +726,7 @@ name = "pygments" version = "2.17.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.8.*'", + "python_full_version < '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/55/59/8bccf4157baf25e4aa5a0bb7fa3ba8600907de105ebc22b0c78cfbf6f565/pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367", size = 4827772 } wheels = [ @@ -808,9 +738,7 @@ name = "pygments" version = "2.18.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.9.*'", - "python_full_version == '3.10.*'", - "python_full_version >= '3.11'", + "python_full_version >= '3.10'", ] sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } wheels = [ @@ -849,14 +777,11 @@ name = "pytest" version = "7.4.4" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.8'", - "python_full_version == '3.8.*'", - "python_full_version == '3.9.*'", + "python_full_version < '3.10'", ] dependencies = [ { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.8'" }, { name = "iniconfig", marker = "python_full_version < '3.10'" }, { name = "packaging", marker = "python_full_version < '3.10'" }, { name = "pluggy", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -872,8 +797,7 @@ name = "pytest" version = "8.3.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.10.*'", - "python_full_version >= '3.11'", + "python_full_version >= '3.10'", ] dependencies = [ { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, @@ -895,7 +819,6 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "typing-extensions", marker = "python_full_version < '3.8'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ae/53/57663d99acaac2fcdafdc697e52a9b1b7d6fcf36616281ff9768a44e7ff3/pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45", size = 30656 } wheels = [ @@ -907,9 +830,7 @@ name = "pytest-benchmark" version = "4.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.8'", - "python_full_version == '3.8.*'", - "python_full_version == '3.9.*'", + "python_full_version < '3.10'", ] dependencies = [ { name = "py-cpuinfo", marker = "python_full_version < '3.10'" }, @@ -925,8 +846,7 @@ name = "pytest-benchmark" version = "5.1.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.10.*'", - "python_full_version >= '3.11'", + "python_full_version >= '3.10'", ] dependencies = [ { name = "py-cpuinfo", marker = "python_full_version >= '3.10'" }, @@ -956,7 +876,7 @@ name = "pytest-django" version = "4.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/02/c0/43c8b2528c24d7f1a48a47e3f7381f5ab2ae8c64634b0c3f4bd843063955/pytest_django-4.9.0.tar.gz", hash = "sha256:8bf7bc358c9ae6f6fc51b6cebb190fe20212196e6807121f11bd6a3b03428314", size = 84067 } @@ -1005,11 +925,11 @@ diagrams = [ [package.dev-dependencies] dev = [ { name = "django", marker = "python_full_version >= '3.10'" }, - { name = "furo", marker = "python_full_version >= '3.9'" }, + { name = "furo" }, { name = "mypy" }, - { name = "myst-parser", marker = "python_full_version >= '3.9'" }, - { name = "pdbr", marker = "python_full_version >= '3.8'" }, - { name = "pillow", marker = "python_full_version >= '3.9'" }, + { name = "myst-parser" }, + { name = "pdbr" }, + { name = "pillow" }, { name = "pre-commit" }, { name = "pydot" }, { name = "pydot" }, @@ -1019,14 +939,14 @@ dev = [ { name = "pytest-benchmark", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "pytest-benchmark", version = "5.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytest-cov" }, - { name = "pytest-django", marker = "python_full_version >= '3.9'" }, + { name = "pytest-django" }, { name = "pytest-mock" }, { name = "pytest-sugar" }, { name = "ruff" }, - { name = "sphinx", marker = "python_full_version >= '3.9'" }, - { name = "sphinx-autobuild", marker = "python_full_version >= '3.9'" }, - { name = "sphinx-copybutton", marker = "python_full_version >= '3.9'" }, - { name = "sphinx-gallery", marker = "python_full_version >= '3.9'" }, + { name = "sphinx" }, + { name = "sphinx-autobuild" }, + { name = "sphinx-copybutton" }, + { name = "sphinx-gallery" }, ] [package.metadata] @@ -1035,11 +955,11 @@ requires-dist = [{ name = "pydot", marker = "extra == 'diagrams'", specifier = " [package.metadata.requires-dev] dev = [ { name = "django", marker = "python_full_version >= '3.10'", specifier = ">=5.0.8" }, - { name = "furo", marker = "python_full_version >= '3.9'", specifier = ">=2024.5.6" }, + { name = "furo", specifier = ">=2024.5.6" }, { name = "mypy" }, - { name = "myst-parser", marker = "python_full_version >= '3.9'" }, - { name = "pdbr", marker = "python_full_version >= '3.8'", specifier = ">=0.8.9" }, - { name = "pillow", marker = "python_full_version >= '3.9'" }, + { name = "myst-parser" }, + { name = "pdbr", specifier = ">=0.8.9" }, + { name = "pillow" }, { name = "pre-commit" }, { name = "pydot" }, { name = "pydot" }, @@ -1047,7 +967,7 @@ dev = [ { name = "pytest-asyncio" }, { name = "pytest-benchmark", specifier = ">=4.0.0" }, { name = "pytest-cov" }, - { name = "pytest-django", marker = "python_full_version >= '3.9'", specifier = ">=4.8.0" }, + { name = "pytest-django", specifier = ">=4.8.0" }, { name = "pytest-mock", specifier = ">=3.10.0" }, { name = "pytest-sugar", specifier = ">=1.0.0" }, { name = "ruff", specifier = ">=0.8.1" }, @@ -1086,19 +1006,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/78/77b40157b6cb5f2d3d31a3d9b2efd1ba3505371f76730d267e8b32cf4b7f/PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", size = 712604 }, { url = "https://files.pythonhosted.org/packages/2e/97/3e0e089ee85e840f4b15bfa00e4e63d84a3691ababbfea92d6f820ea6f21/PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", size = 126098 }, { url = "https://files.pythonhosted.org/packages/2b/9f/fbade56564ad486809c27b322d0f7e6a89c01f6b4fe208402e90d4443a99/PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", size = 138675 }, - { url = "https://files.pythonhosted.org/packages/c7/d1/02baa09d39b1bb1ebaf0d850d106d1bdcb47c91958557f471153c49dc03b/PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", size = 189627 }, - { url = "https://files.pythonhosted.org/packages/e5/31/ba812efa640a264dbefd258986a5e4e786230cb1ee4a9f54eb28ca01e14a/PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", size = 658438 }, - { url = "https://files.pythonhosted.org/packages/4d/f1/08f06159739254c8947899c9fc901241614195db15ba8802ff142237664c/PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", size = 680304 }, - { url = "https://files.pythonhosted.org/packages/d7/8f/db62b0df635b9008fe90aa68424e99cee05e68b398740c8a666a98455589/PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", size = 670140 }, - { url = "https://files.pythonhosted.org/packages/cc/5c/fcabd17918348c7db2eeeb0575705aaf3f7ab1657f6ce29b2e31737dd5d1/PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", size = 137577 }, - { url = "https://files.pythonhosted.org/packages/1e/ae/964ccb88a938f20ece5754878f182cfbd846924930d02d29d06af8d4c69e/PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", size = 153248 }, - { url = "https://files.pythonhosted.org/packages/7f/5d/2779ea035ba1e533c32ed4a249b4e0448f583ba10830b21a3cddafe11a4e/PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", size = 191734 }, - { url = "https://files.pythonhosted.org/packages/e1/a1/27bfac14b90adaaccf8c8289f441e9f76d94795ec1e7a8f134d9f2cb3d0b/PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", size = 723767 }, - { url = "https://files.pythonhosted.org/packages/c1/39/47ed4d65beec9ce07267b014be85ed9c204fa373515355d3efa62d19d892/PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", size = 749067 }, - { url = "https://files.pythonhosted.org/packages/c8/6b/6600ac24725c7388255b2f5add93f91e58a5d7efaf4af244fdbcc11a541b/PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", size = 736569 }, - { url = "https://files.pythonhosted.org/packages/0d/46/62ae77677e532c0af6c81ddd6f3dbc16bdcc1208b077457354442d220bfb/PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", size = 787738 }, - { url = "https://files.pythonhosted.org/packages/d6/6a/439d1a6f834b9a9db16332ce16c4a96dd0e3970b65fe08cbecd1711eeb77/PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", size = 139797 }, - { url = "https://files.pythonhosted.org/packages/29/0f/9782fa5b10152abf033aec56a601177ead85ee03b57781f2d9fced09eefc/PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", size = 157350 }, { url = "https://files.pythonhosted.org/packages/57/c5/5d09b66b41d549914802f482a2118d925d876dc2a35b2d127694c1345c34/PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", size = 197846 }, { url = "https://files.pythonhosted.org/packages/0e/88/21b2f16cb2123c1e9375f2c93486e35fdc86e63f02e274f0e99c589ef153/PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", size = 174396 }, { url = "https://files.pythonhosted.org/packages/ac/6c/967d91a8edf98d2b2b01d149bd9e51b8f9fb527c98d80ebb60c6b21d60c4/PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", size = 731824 }, @@ -1114,10 +1021,10 @@ name = "requests" version = "2.32.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "certifi", marker = "python_full_version >= '3.9'" }, - { name = "charset-normalizer", marker = "python_full_version >= '3.9'" }, - { name = "idna", marker = "python_full_version >= '3.9'" }, - { name = "urllib3", marker = "python_full_version >= '3.9'" }, + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } wheels = [ @@ -1129,10 +1036,10 @@ name = "rich" version = "10.16.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.8'" }, - { name = "commonmark", marker = "python_full_version >= '3.8'" }, - { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.8.*'" }, - { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "colorama" }, + { name = "commonmark" }, + { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/74/c3/e55ebdd66540503cee29cd3bb18a90bcfd5587a0cf3680173c368be56093/rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b", size = 197585 } wheels = [ @@ -1196,24 +1103,25 @@ name = "sphinx" version = "7.4.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "alabaster", marker = "python_full_version >= '3.9'" }, - { name = "babel", marker = "python_full_version >= '3.9'" }, - { name = "colorama", marker = "python_full_version >= '3.9' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version >= '3.9'" }, - { name = "imagesize", marker = "python_full_version >= '3.9'" }, - { name = "importlib-metadata", marker = "python_full_version == '3.9.*'" }, - { name = "jinja2", marker = "python_full_version >= '3.9'" }, - { name = "packaging", marker = "python_full_version >= '3.9'" }, - { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "requests", marker = "python_full_version >= '3.9'" }, - { name = "snowballstemmer", marker = "python_full_version >= '3.9'" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.9'" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.9'" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.9'" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.9'" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.9'" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "requests" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911 } wheels = [ @@ -1225,12 +1133,12 @@ name = "sphinx-autobuild" version = "2024.10.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.9'" }, - { name = "sphinx", marker = "python_full_version >= '3.9'" }, - { name = "starlette", marker = "python_full_version >= '3.9'" }, - { name = "uvicorn", marker = "python_full_version >= '3.9'" }, - { name = "watchfiles", marker = "python_full_version >= '3.9'" }, - { name = "websockets", marker = "python_full_version >= '3.9'" }, + { name = "colorama" }, + { name = "sphinx" }, + { name = "starlette" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a5/2c/155e1de2c1ba96a72e5dba152c509a8b41e047ee5c2def9e9f0d812f8be7/sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1", size = 14023 } wheels = [ @@ -1242,7 +1150,7 @@ name = "sphinx-basic-ng" version = "1.0.0b2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", marker = "python_full_version >= '3.9'" }, + { name = "sphinx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/0b/a866924ded68efec7a1759587a4e478aec7559d8165fac8b2ad1c0e774d6/sphinx_basic_ng-1.0.0b2.tar.gz", hash = "sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9", size = 20736 } wheels = [ @@ -1254,7 +1162,7 @@ name = "sphinx-copybutton" version = "0.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", marker = "python_full_version >= '3.9'" }, + { name = "sphinx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fc/2b/a964715e7f5295f77509e59309959f4125122d648f86b4fe7d70ca1d882c/sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd", size = 23039 } wheels = [ @@ -1266,8 +1174,8 @@ name = "sphinx-gallery" version = "0.18.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pillow", marker = "python_full_version >= '3.9'" }, - { name = "sphinx", marker = "python_full_version >= '3.9'" }, + { name = "pillow" }, + { name = "sphinx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ac/84/e4b4cde6ea2f3a1dd7d523dcf28260e93999b4882cc352f8bc6a14cbd848/sphinx_gallery-0.18.0.tar.gz", hash = "sha256:4b5b5bc305348c01d00cf66ad852cfd2dd8b67f7f32ae3e2820c01557b3f92f9", size = 466371 } wheels = [ @@ -1342,8 +1250,8 @@ name = "starlette" version = "0.41.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", marker = "python_full_version == '3.9.*'" }, + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3e/da/1fb4bdb72ae12b834becd7e1e7e47001d32f91ec0ce8d7bc1b618d9f0bd9/starlette-0.41.2.tar.gz", hash = "sha256:9834fd799d1a87fd346deb76158668cfa0b0d56f85caefe8268e2d97c3468b62", size = 2573867 } wheels = [ @@ -1368,48 +1276,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757 }, ] -[[package]] -name = "typed-ast" -version = "1.5.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/7e/a424029f350aa8078b75fd0d360a787a273ca753a678d1104c5fa4f3072a/typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd", size = 252841 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/07/5defe18d4fc16281cd18c4374270abc430c3d852d8ac29b5db6599d45cfe/typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b", size = 223267 }, - { url = "https://files.pythonhosted.org/packages/a0/5c/e379b00028680bfcd267d845cf46b60e76d8ac6f7009fd440d6ce030cc92/typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686", size = 208260 }, - { url = "https://files.pythonhosted.org/packages/3b/99/5cc31ef4f3c80e1ceb03ed2690c7085571e3fbf119cbd67a111ec0b6622f/typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769", size = 842272 }, - { url = "https://files.pythonhosted.org/packages/e2/ed/b9b8b794b37b55c9247b1e8d38b0361e8158795c181636d34d6c11b506e7/typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04", size = 824651 }, - { url = "https://files.pythonhosted.org/packages/ca/59/dbbbe5a0e91c15d14a0896b539a5ed01326b0d468e75c1a33274d128d2d1/typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d", size = 854960 }, - { url = "https://files.pythonhosted.org/packages/90/f0/0956d925f87bd81f6e0f8cf119eac5e5c8f4da50ca25bb9f5904148d4611/typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d", size = 839321 }, - { url = "https://files.pythonhosted.org/packages/43/17/4bdece9795da6f3345c4da5667ac64bc25863617f19c28d81f350f515be6/typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02", size = 139380 }, - { url = "https://files.pythonhosted.org/packages/75/53/b685e10da535c7b3572735f8bea0d4abb35a04722a7d44ca9c163a0cf822/typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee", size = 223264 }, - { url = "https://files.pythonhosted.org/packages/96/fd/fc8ccf19fc16a40a23e7c7802d0abc78c1f38f1abb6e2447c474f8a076d8/typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18", size = 208158 }, - { url = "https://files.pythonhosted.org/packages/bf/9a/598e47f2c3ecd19d7f1bb66854d0d3ba23ffd93c846448790a92524b0a8d/typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88", size = 878366 }, - { url = "https://files.pythonhosted.org/packages/60/ca/765e8bf8b24d0ed7b9fc669f6826c5bc3eb7412fc765691f59b83ae195b2/typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2", size = 860314 }, - { url = "https://files.pythonhosted.org/packages/d9/3c/4af750e6c673a0dd6c7b9f5b5e5ed58ec51a2e4e744081781c664d369dfa/typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9", size = 898108 }, - { url = "https://files.pythonhosted.org/packages/03/8d/d0a4d1e060e1e8dda2408131a0cc7633fc4bc99fca5941dcb86c461dfe01/typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8", size = 881971 }, - { url = "https://files.pythonhosted.org/packages/90/83/f28d2c912cd010a09b3677ac69d23181045eb17e358914ab739b7fdee530/typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b", size = 139286 }, - { url = "https://files.pythonhosted.org/packages/d5/00/635353c31b71ed307ab020eff6baed9987da59a1b2ba489f885ecbe293b8/typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e", size = 222315 }, - { url = "https://files.pythonhosted.org/packages/01/95/11be104446bb20212a741d30d40eab52a9cfc05ea34efa074ff4f7c16983/typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e", size = 793541 }, - { url = "https://files.pythonhosted.org/packages/32/f1/75bd58fb1410cb72fbc6e8adf163015720db2c38844b46a9149c5ff6bf38/typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311", size = 778348 }, - { url = "https://files.pythonhosted.org/packages/47/97/0bb4dba688a58ff9c08e63b39653e4bcaa340ce1bb9c1d58163e5c2c66f1/typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2", size = 809447 }, - { url = "https://files.pythonhosted.org/packages/a8/cd/9a867f5a96d83a9742c43914e10d3a2083d8fe894ab9bf60fd467c6c497f/typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4", size = 796707 }, - { url = "https://files.pythonhosted.org/packages/eb/06/73ca55ee5303b41d08920de775f02d2a3e1e59430371f5adf7fbb1a21127/typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431", size = 138403 }, - { url = "https://files.pythonhosted.org/packages/19/e3/88b65e46643006592f39e0fdef3e29454244a9fdaa52acfb047dc68cae6a/typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a", size = 222951 }, - { url = "https://files.pythonhosted.org/packages/15/e0/182bdd9edb6c6a1c068cecaa87f58924a817f2807a0b0d940f578b3328df/typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437", size = 208247 }, - { url = "https://files.pythonhosted.org/packages/8d/09/bba083f2c11746288eaf1859e512130420405033de84189375fe65d839ba/typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede", size = 861010 }, - { url = "https://files.pythonhosted.org/packages/31/f3/38839df509b04fb54205e388fc04b47627377e0ad628870112086864a441/typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4", size = 840026 }, - { url = "https://files.pythonhosted.org/packages/45/1e/aa5f1dae4b92bc665ae9a655787bb2fe007a881fa2866b0408ce548bb24c/typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6", size = 875615 }, - { url = "https://files.pythonhosted.org/packages/94/88/71a1c249c01fbbd66f9f28648f8249e737a7fe19056c1a78e7b3b9250eb1/typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4", size = 858320 }, - { url = "https://files.pythonhosted.org/packages/12/1e/19f53aad3984e351e6730e4265fde4b949a66c451e10828fdbc4dfb050f1/typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b", size = 139414 }, - { url = "https://files.pythonhosted.org/packages/b1/88/6e7f36f5fab6fbf0586a2dd866ac337924b7d4796a4d1b2b04443a864faf/typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10", size = 223329 }, - { url = "https://files.pythonhosted.org/packages/71/30/09d27e13824495547bcc665bd07afc593b22b9484f143b27565eae4ccaac/typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814", size = 208314 }, - { url = "https://files.pythonhosted.org/packages/07/3d/564308b7a432acb1f5399933cbb1b376a1a64d2544b90f6ba91894674260/typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8", size = 840900 }, - { url = "https://files.pythonhosted.org/packages/ea/f4/262512d14f777ea3666a089e2675a9b1500a85b8329a36de85d63433fb0e/typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274", size = 823435 }, - { url = "https://files.pythonhosted.org/packages/a1/25/b3ccb948166d309ab75296ac9863ebe2ff209fbc063f1122a2d3979e47c3/typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a", size = 853125 }, - { url = "https://files.pythonhosted.org/packages/1c/09/012da182242f168bb5c42284297dcc08dc0a1b3668db5b3852aec467f56f/typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba", size = 837280 }, - { url = "https://files.pythonhosted.org/packages/30/bd/c815051404c4293265634d9d3e292f04fcf681d0502a9484c38b8f224d04/typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155", size = 139486 }, -] - [[package]] name = "typing-extensions" version = "4.7.1" @@ -1442,9 +1308,9 @@ name = "uvicorn" version = "0.32.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", marker = "python_full_version >= '3.9'" }, - { name = "h11", marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e0/fc/1d785078eefd6945f3e5bab5c076e4230698046231eb0f3747bc5c8fa992/uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e", size = 77564 } wheels = [ @@ -1458,7 +1324,6 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, - { name = "importlib-metadata", marker = "python_full_version < '3.8'" }, { name = "platformdirs" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3f/40/abc5a766da6b0b2457f819feab8e9203cbeae29327bd241359f866a3da9d/virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48", size = 9372482 } @@ -1471,7 +1336,7 @@ name = "watchfiles" version = "0.24.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.9'" }, + { name = "anyio" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c8/27/2ba23c8cc85796e2d41976439b08d52f691655fdb9401362099502d1f0cf/watchfiles-0.24.0.tar.gz", hash = "sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1", size = 37870 } wheels = [ @@ -1525,18 +1390,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6d/d5/b96eeb9fe3fda137200dd2f31553670cbc731b1e13164fd69b49870b76ec/watchfiles-0.24.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:edf71b01dec9f766fb285b73930f95f730bb0943500ba0566ae234b5c1618c18", size = 593625 }, { url = "https://files.pythonhosted.org/packages/c1/e5/c326fe52ee0054107267608d8cea275e80be4455b6079491dfd9da29f46f/watchfiles-0.24.0-cp313-none-win32.whl", hash = "sha256:f4c96283fca3ee09fb044f02156d9570d156698bc3734252175a38f0e8975f07", size = 263899 }, { url = "https://files.pythonhosted.org/packages/a6/8b/8a7755c5e7221bb35fe4af2dc44db9174f90ebf0344fd5e9b1e8b42d381e/watchfiles-0.24.0-cp313-none-win_amd64.whl", hash = "sha256:a974231b4fdd1bb7f62064a0565a6b107d27d21d9acb50c484d2cdba515b9366", size = 276622 }, - { url = "https://files.pythonhosted.org/packages/17/1c/c0b5f4347011b60e2dbde671a5050944f3aaf0eb2ffc0fb5c7adf2516229/watchfiles-0.24.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ee82c98bed9d97cd2f53bdb035e619309a098ea53ce525833e26b93f673bc318", size = 375982 }, - { url = "https://files.pythonhosted.org/packages/c5/b2/d417b982be5ace395f1aad32cd8e0dcf194e431dfbfeee88941b6da6735a/watchfiles-0.24.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fd92bbaa2ecdb7864b7600dcdb6f2f1db6e0346ed425fbd01085be04c63f0b05", size = 369757 }, - { url = "https://files.pythonhosted.org/packages/68/27/f3a1147af79085da95a879d7e6f953380da17a90b50d990749ae287550ca/watchfiles-0.24.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f83df90191d67af5a831da3a33dd7628b02a95450e168785586ed51e6d28943c", size = 439397 }, - { url = "https://files.pythonhosted.org/packages/31/de/4a677766880efee555cc56a4c6bf6993a7748901243cd2511419acc37a6c/watchfiles-0.24.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fca9433a45f18b7c779d2bae7beeec4f740d28b788b117a48368d95a3233ed83", size = 433878 }, - { url = "https://files.pythonhosted.org/packages/f4/7f/30fbf661dea01cf3d5ab4962ee4b52854b9fbbd7fe4918bc60c212bb5b60/watchfiles-0.24.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b995bfa6bf01a9e09b884077a6d37070464b529d8682d7691c2d3b540d357a0c", size = 451495 }, - { url = "https://files.pythonhosted.org/packages/c8/65/cda4b9ed13087d57f78ed386c4bdc2369c114dd871a32fa6e2419f6e81b8/watchfiles-0.24.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed9aba6e01ff6f2e8285e5aa4154e2970068fe0fc0998c4380d0e6278222269b", size = 470115 }, - { url = "https://files.pythonhosted.org/packages/4c/72/9b2ba3bb3a7233fb3d21900cd3f9005cfaa53884f496239541ec885b9861/watchfiles-0.24.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5171ef898299c657685306d8e1478a45e9303ddcd8ac5fed5bd52ad4ae0b69b", size = 476814 }, - { url = "https://files.pythonhosted.org/packages/3d/78/90a881916a4a3bafd5e82202d51406444d3720cfc03b326427a8e455d89d/watchfiles-0.24.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4933a508d2f78099162da473841c652ad0de892719043d3f07cc83b33dfd9d91", size = 426747 }, - { url = "https://files.pythonhosted.org/packages/56/52/5a2c6e0694013a53f596d4a66642de48dc1a53a635ad61bc6504abf5c87c/watchfiles-0.24.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95cf3b95ea665ab03f5a54765fa41abf0529dbaf372c3b83d91ad2cfa695779b", size = 613135 }, - { url = "https://files.pythonhosted.org/packages/fc/dc/8f177e6074e756d961d5dcb5ef65528b02ab09028d0380db4579a30af78f/watchfiles-0.24.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:01def80eb62bd5db99a798d5e1f5f940ca0a05986dcfae21d833af7a46f7ee22", size = 596318 }, - { url = "https://files.pythonhosted.org/packages/e6/16/d89e06188ed6672dc69eeef7af2ea158328bd59d45032a94daaaed2a6516/watchfiles-0.24.0-cp38-none-win32.whl", hash = "sha256:4d28cea3c976499475f5b7a2fec6b3a36208656963c1a856d328aeae056fc5c1", size = 264384 }, - { url = "https://files.pythonhosted.org/packages/e6/cc/2f2f27fc403193bedaaae5485cd04fd31064f5cdec885162bd0e390be68a/watchfiles-0.24.0-cp38-none-win_amd64.whl", hash = "sha256:21ab23fdc1208086d99ad3f69c231ba265628014d4aed31d4e8746bd59e88cd1", size = 277740 }, { url = "https://files.pythonhosted.org/packages/93/90/15b3b1cc19799c217e4369ca15dbf9ba1d0f821d61b27173a54800002478/watchfiles-0.24.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b665caeeda58625c3946ad7308fbd88a086ee51ccb706307e5b1fa91556ac886", size = 375920 }, { url = "https://files.pythonhosted.org/packages/74/e2/ec7766a5b20ba5e37397ef8d32ff39a90daf7e4677410efe077c386338b6/watchfiles-0.24.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c51749f3e4e269231510da426ce4a44beb98db2dce9097225c338f815b05d4f", size = 369382 }, { url = "https://files.pythonhosted.org/packages/a2/82/915b3a3295292f860181dc9c7d922834ac7265c8915052d396d40ccf4617/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b2509f08761f29a0fdad35f7e1638b8ab1adfa2666d41b794090361fb8b855", size = 438556 }, @@ -1609,17 +1462,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/6e/66b6b756aebbd680b934c8bdbb6dcb9ce45aad72cde5f8a7208dbb00dd36/websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6", size = 164732 }, { url = "https://files.pythonhosted.org/packages/35/c6/12e3aab52c11aeb289e3dbbc05929e7a9d90d7a9173958477d3ef4f8ce2d/websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d", size = 158709 }, { url = "https://files.pythonhosted.org/packages/41/d8/63d6194aae711d7263df4498200c690a9c39fb437ede10f3e157a6343e0d/websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2", size = 159144 }, - { url = "https://files.pythonhosted.org/packages/83/69/59872420e5bce60db166d6fba39ee24c719d339fb0ae48cb2ce580129882/websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d", size = 157811 }, - { url = "https://files.pythonhosted.org/packages/bb/f7/0610032e0d3981758fdd6ee7c68cc02ebf668a762c5178d3d91748228849/websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23", size = 155471 }, - { url = "https://files.pythonhosted.org/packages/55/2f/c43173a72ea395263a427a36d25bce2675f41c809424466a13c61a9a2d61/websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c", size = 155713 }, - { url = "https://files.pythonhosted.org/packages/92/7e/8fa930c6426a56c47910792717787640329e4a0e37cdfda20cf89da67126/websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea", size = 164995 }, - { url = "https://files.pythonhosted.org/packages/27/29/50ed4c68a3f606565a2db4b13948ae7b6f6c53aa9f8f258d92be6698d276/websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7", size = 164057 }, - { url = "https://files.pythonhosted.org/packages/3c/0e/60da63b1c53c47f389f79312b3356cb305600ffad1274d7ec473128d4e6b/websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54", size = 164340 }, - { url = "https://files.pythonhosted.org/packages/20/ef/d87c5fc0aa7fafad1d584b6459ddfe062edf0d0dd64800a02e67e5de048b/websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db", size = 164222 }, - { url = "https://files.pythonhosted.org/packages/f2/c4/7916e1f6b5252d3dcb9121b67d7fdbb2d9bf5067a6d8c88885ba27a9e69c/websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295", size = 163647 }, - { url = "https://files.pythonhosted.org/packages/de/df/2ebebb807f10993c35c10cbd3628a7944b66bd5fb6632a561f8666f3a68e/websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96", size = 163590 }, - { url = "https://files.pythonhosted.org/packages/b5/82/d48911f56bb993c11099a1ff1d4041d9d1481d50271100e8ee62bc28f365/websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf", size = 158701 }, - { url = "https://files.pythonhosted.org/packages/8b/b3/945aacb21fc89ad150403cbaa974c9e846f098f16d9f39a3dd6094f9beb1/websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6", size = 159146 }, { url = "https://files.pythonhosted.org/packages/61/26/5f7a7fb03efedb4f90ed61968338bfe7c389863b0ceda239b94ae61c5ae4/websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d", size = 157810 }, { url = "https://files.pythonhosted.org/packages/0e/d4/9b4814a07dffaa7a79d71b4944d10836f9adbd527a113f6675734ef3abed/websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7", size = 155467 }, { url = "https://files.pythonhosted.org/packages/1a/1a/2abdc7ce3b56429ae39d6bfb48d8c791f5a26bbcb6f44aabcf71ffc3fda2/websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a", size = 155714 }, @@ -1637,12 +1479,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/f5/6652fb82440813822022a9301a30afde85e5ff3fb2aebb77f34aabe2b4e8/websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6", size = 156701 }, { url = "https://files.pythonhosted.org/packages/67/33/ae82a7b860fa8a08aba68818bdf7ff61f04598aa5ab96df4cd5a3e418ca4/websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a", size = 156654 }, { url = "https://files.pythonhosted.org/packages/63/0b/a1b528d36934f833e20f6da1032b995bf093d55cb416b9f2266f229fb237/websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23", size = 159192 }, - { url = "https://files.pythonhosted.org/packages/5e/a1/5ae6d0ef2e61e2b77b3b4678949a634756544186620a728799acdf5c3482/websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b", size = 155433 }, - { url = "https://files.pythonhosted.org/packages/0d/2f/addd33f85600d210a445f817ff0d79d2b4d0eb6f3c95b9f35531ebf8f57c/websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51", size = 155733 }, - { url = "https://files.pythonhosted.org/packages/74/0b/f8ec74ac3b14a983289a1b42dc2c518a0e2030b486d0549d4f51ca11e7c9/websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7", size = 157093 }, - { url = "https://files.pythonhosted.org/packages/ad/4c/aa5cc2f718ee4d797411202f332c8281f04c42d15f55b02f7713320f7a03/websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d", size = 156701 }, - { url = "https://files.pythonhosted.org/packages/1f/4b/7c5b2d0d0f0f1a54f27c60107cf1f201bee1f88c5508f87408b470d09a9c/websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027", size = 156648 }, - { url = "https://files.pythonhosted.org/packages/f3/63/35f3fb073884a9fd1ce5413b2dcdf0d9198b03dac6274197111259cbde06/websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978", size = 159188 }, { url = "https://files.pythonhosted.org/packages/59/fd/e4bf9a7159dba6a16c59ae9e670e3e8ad9dcb6791bc0599eb86de32d50a9/websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e", size = 155499 }, { url = "https://files.pythonhosted.org/packages/74/42/d48ede93cfe0c343f3b552af08efc60778d234989227b16882eed1b8b189/websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09", size = 155731 }, { url = "https://files.pythonhosted.org/packages/f6/f2/2ef6bff1c90a43b80622a17c0852b48c09d3954ab169266ad7b15e17cdcb/websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842", size = 157093 }, From 2bcd05474bc3c1e4dd2d2737801589ef19ecf73b Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Wed, 4 Dec 2024 12:28:49 -0300 Subject: [PATCH 15/45] fix: Fix merge with develop --- pyproject.toml | 15 - uv.lock | 853 ++++++++++++++++++++++++------------------------- 2 files changed, 413 insertions(+), 455 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2f4a5b75..745fdcd2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,21 +77,6 @@ addopts = [ "--benchmark-group-by=name", "--pdbcls=pdbr:RichPdb", ] -addopts = [ - "--ignore=docs/conf.py", - "--ignore=docs/auto_examples/", - "--ignore=docs/_build/", - "--ignore=tests/examples/", - "--cov", - "--cov-config", - ".coveragerc", - "--doctest-glob=*.md", - "--doctest-modules", - "--doctest-continue-on-failure", - "--benchmark-autosave", - "--benchmark-group-by=name", - "--pdbcls=pdbr:RichPdb", -] doctest_optionflags = "ELLIPSIS IGNORE_EXCEPTION_DETAIL NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL" asyncio_mode = "auto" markers = [ diff --git a/uv.lock b/uv.lock index 2410d2fd..81c1dd3d 100644 --- a/uv.lock +++ b/uv.lock @@ -73,11 +73,11 @@ wheels = [ [[package]] name = "cfgv" -version = "3.3.1" +version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c4/bf/d0d622b660d414a47dc7f0d303791a627663f554345b21250e39e7acb48b/cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736", size = 7864 } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/82/0a0ebd35bae9981dea55c06f8e6aaf44a49171ad798795c72c6f64cba4c2/cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426", size = 7312 }, + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, ] [[package]] @@ -185,61 +185,73 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] -[[package]] -name = "commonmark" -version = "0.9.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/60/48/a60f593447e8f0894ebb7f6e6c1f25dafc5e89c5879fdc9360ae93ff83f0/commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", size = 95764 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/92/dfd892312d822f36c55366118b95d914e5f16de11044a27cf10a7d71bbbf/commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9", size = 51068 }, -] - [[package]] name = "coverage" -version = "7.2.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/45/8b/421f30467e69ac0e414214856798d4bc32da1336df745e49e49ae5c1e2a8/coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59", size = 762575 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/01/24/be01e62a7bce89bcffe04729c540382caa5a06bee45ae42136c93e2499f5/coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8", size = 200724 }, - { url = "https://files.pythonhosted.org/packages/3d/80/7060a445e1d2c9744b683dc935248613355657809d6c6b2716cdf4ca4766/coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb", size = 201024 }, - { url = "https://files.pythonhosted.org/packages/b8/9d/926fce7e03dbfc653104c2d981c0fa71f0572a9ebd344d24c573bd6f7c4f/coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6", size = 229528 }, - { url = "https://files.pythonhosted.org/packages/d1/3a/67f5d18f911abf96857f6f7e4df37ca840e38179e2cc9ab6c0b9c3380f19/coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2", size = 227842 }, - { url = "https://files.pythonhosted.org/packages/b4/bd/1b2331e3a04f4cc9b7b332b1dd0f3a1261dfc4114f8479bebfcc2afee9e8/coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063", size = 228717 }, - { url = "https://files.pythonhosted.org/packages/2b/86/3dbf9be43f8bf6a5ca28790a713e18902b2d884bc5fa9512823a81dff601/coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1", size = 234632 }, - { url = "https://files.pythonhosted.org/packages/91/e8/469ed808a782b9e8305a08bad8c6fa5f8e73e093bda6546c5aec68275bff/coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353", size = 232875 }, - { url = "https://files.pythonhosted.org/packages/29/8f/4fad1c2ba98104425009efd7eaa19af9a7c797e92d40cd2ec026fa1f58cb/coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495", size = 234094 }, - { url = "https://files.pythonhosted.org/packages/94/4e/d4e46a214ae857be3d7dc5de248ba43765f60daeb1ab077cb6c1536c7fba/coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818", size = 203184 }, - { url = "https://files.pythonhosted.org/packages/1f/e9/d6730247d8dec2a3dddc520ebe11e2e860f0f98cee3639e23de6cf920255/coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850", size = 204096 }, - { url = "https://files.pythonhosted.org/packages/c6/fa/529f55c9a1029c840bcc9109d5a15ff00478b7ff550a1ae361f8745f8ad5/coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f", size = 200895 }, - { url = "https://files.pythonhosted.org/packages/67/d7/cd8fe689b5743fffac516597a1222834c42b80686b99f5b44ef43ccc2a43/coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe", size = 201120 }, - { url = "https://files.pythonhosted.org/packages/8c/95/16eed713202406ca0a37f8ac259bbf144c9d24f9b8097a8e6ead61da2dbb/coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3", size = 233178 }, - { url = "https://files.pythonhosted.org/packages/c1/49/4d487e2ad5d54ed82ac1101e467e8994c09d6123c91b2a962145f3d262c2/coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f", size = 230754 }, - { url = "https://files.pythonhosted.org/packages/a7/cd/3ce94ad9d407a052dc2a74fbeb1c7947f442155b28264eb467ee78dea812/coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb", size = 232558 }, - { url = "https://files.pythonhosted.org/packages/8f/a8/12cc7b261f3082cc299ab61f677f7e48d93e35ca5c3c2f7241ed5525ccea/coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833", size = 241509 }, - { url = "https://files.pythonhosted.org/packages/04/fa/43b55101f75a5e9115259e8be70ff9279921cb6b17f04c34a5702ff9b1f7/coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97", size = 239924 }, - { url = "https://files.pythonhosted.org/packages/68/5f/d2bd0f02aa3c3e0311986e625ccf97fdc511b52f4f1a063e4f37b624772f/coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a", size = 240977 }, - { url = "https://files.pythonhosted.org/packages/ba/92/69c0722882643df4257ecc5437b83f4c17ba9e67f15dc6b77bad89b6982e/coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a", size = 203168 }, - { url = "https://files.pythonhosted.org/packages/b1/96/c12ed0dfd4ec587f3739f53eb677b9007853fd486ccb0e7d5512a27bab2e/coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562", size = 204185 }, - { url = "https://files.pythonhosted.org/packages/ff/d5/52fa1891d1802ab2e1b346d37d349cb41cdd4fd03f724ebbf94e80577687/coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4", size = 201020 }, - { url = "https://files.pythonhosted.org/packages/24/df/6765898d54ea20e3197a26d26bb65b084deefadd77ce7de946b9c96dfdc5/coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4", size = 233994 }, - { url = "https://files.pythonhosted.org/packages/15/81/b108a60bc758b448c151e5abceed027ed77a9523ecbc6b8a390938301841/coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01", size = 231358 }, - { url = "https://files.pythonhosted.org/packages/61/90/c76b9462f39897ebd8714faf21bc985b65c4e1ea6dff428ea9dc711ed0dd/coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6", size = 233316 }, - { url = "https://files.pythonhosted.org/packages/04/d6/8cba3bf346e8b1a4fb3f084df7d8cea25a6b6c56aaca1f2e53829be17e9e/coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d", size = 240159 }, - { url = "https://files.pythonhosted.org/packages/6e/ea/4a252dc77ca0605b23d477729d139915e753ee89e4c9507630e12ad64a80/coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de", size = 238127 }, - { url = "https://files.pythonhosted.org/packages/9f/5c/d9760ac497c41f9c4841f5972d0edf05d50cad7814e86ee7d133ec4a0ac8/coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d", size = 239833 }, - { url = "https://files.pythonhosted.org/packages/69/8c/26a95b08059db1cbb01e4b0e6d40f2e9debb628c6ca86b78f625ceaf9bab/coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511", size = 203463 }, - { url = "https://files.pythonhosted.org/packages/b7/00/14b00a0748e9eda26e97be07a63cc911108844004687321ddcc213be956c/coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3", size = 204347 }, - { url = "https://files.pythonhosted.org/packages/88/da/495944ebf0ad246235a6bd523810d9f81981f9b81c6059ba1f56e943abe0/coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9", size = 200725 }, - { url = "https://files.pythonhosted.org/packages/ca/0c/3dfeeb1006c44b911ee0ed915350db30325d01808525ae7cc8d57643a2ce/coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2", size = 201022 }, - { url = "https://files.pythonhosted.org/packages/61/af/5964b8d7d9a5c767785644d9a5a63cacba9a9c45cc42ba06d25895ec87be/coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7", size = 229102 }, - { url = "https://files.pythonhosted.org/packages/d9/1d/cd467fceb62c371f9adb1d739c92a05d4e550246daa90412e711226bd320/coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e", size = 227441 }, - { url = "https://files.pythonhosted.org/packages/fe/57/e4f8ad64d84ca9e759d783a052795f62a9f9111585e46068845b1cb52c2b/coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1", size = 228265 }, - { url = "https://files.pythonhosted.org/packages/88/8b/b0d9fe727acae907fa7f1c8194ccb6fe9d02e1c3e9001ecf74c741f86110/coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9", size = 234217 }, - { url = "https://files.pythonhosted.org/packages/66/2e/c99fe1f6396d93551aa352c75410686e726cd4ea104479b9af1af22367ce/coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250", size = 232466 }, - { url = "https://files.pythonhosted.org/packages/bb/e9/88747b40c8fb4a783b40222510ce6d66170217eb05d7f46462c36b4fa8cc/coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2", size = 233669 }, - { url = "https://files.pythonhosted.org/packages/b1/d5/a8e276bc005e42114468d4fe03e0a9555786bc51cbfe0d20827a46c1565a/coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb", size = 203199 }, - { url = "https://files.pythonhosted.org/packages/a9/0c/4a848ae663b47f1195abcb09a951751dd61f80b503303b9b9d768e0fd321/coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27", size = 204109 }, - { url = "https://files.pythonhosted.org/packages/67/fb/b3b1d7887e1ea25a9608b0776e480e4bbc303ca95a31fd585555ec4fff5a/coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d", size = 193207 }, +version = "7.6.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ab/75/aecfd0a3adbec6e45753976bc2a9fed62b42cea9a206d10fd29244a77953/coverage-7.6.8.tar.gz", hash = "sha256:8b2b8503edb06822c86d82fa64a4a5cb0760bb8f31f26e138ec743f422f37cfc", size = 801425 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/86/6ed22e101badc8eedf181f0c2f65500df5929c44c79991cf45b9bf741424/coverage-7.6.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b39e6011cd06822eb964d038d5dff5da5d98652b81f5ecd439277b32361a3a50", size = 206988 }, + { url = "https://files.pythonhosted.org/packages/3b/04/16853c58bacc02b3ff5405193dfc6c66632442d931b23dd7b9452dc55cf3/coverage-7.6.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63c19702db10ad79151a059d2d6336fe0c470f2e18d0d4d1a57f7f9713875dcf", size = 207418 }, + { url = "https://files.pythonhosted.org/packages/f8/eb/8a91520d04215eb549d6a7d7d3a79cbb1d78b5dd0814f4b23bf97521d580/coverage-7.6.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3985b9be361d8fb6b2d1adc9924d01dec575a1d7453a14cccd73225cb79243ee", size = 235860 }, + { url = "https://files.pythonhosted.org/packages/00/10/bf1ede5b54ae1bbf39921a5dd4cc84aee79041ed301ec8955064785ddb90/coverage-7.6.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:644ec81edec0f4ad17d51c838a7d01e42811054543b76d4ba2c5d6af741ce2a6", size = 233766 }, + { url = "https://files.pythonhosted.org/packages/5c/ea/741d9233eb502906e0d18ccf4c15c4fb74ff0e85fd8ee967590194b889a1/coverage-7.6.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f188a2402f8359cf0c4b1fe89eea40dc13b52e7b4fd4812450da9fcd210181d", size = 234924 }, + { url = "https://files.pythonhosted.org/packages/18/43/b2cfd4413a5b64ab27c289228b0c45b4527d1b99381cc9d6a00bfd515da4/coverage-7.6.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19122296822deafce89a0c5e8685704c067ae65d45e79718c92df7b3ec3d331", size = 234019 }, + { url = "https://files.pythonhosted.org/packages/8e/95/8b2fbb9d1a79277963b6095cd51a90fb7088cd3618faf75550038331f78b/coverage-7.6.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13618bed0c38acc418896005732e565b317aa9e98d855a0e9f211a7ffc2d6638", size = 232481 }, + { url = "https://files.pythonhosted.org/packages/4d/d7/9e939508a39ef67605b715ca89c6522214aceb27c2db9152ae3ae1cf8626/coverage-7.6.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:193e3bffca48ad74b8c764fb4492dd875038a2f9925530cb094db92bb5e47bed", size = 233609 }, + { url = "https://files.pythonhosted.org/packages/ba/e2/1c5fb52eafcffeebaa9db084bff47e7c3cf4f97db752226c232cee4d530b/coverage-7.6.8-cp310-cp310-win32.whl", hash = "sha256:3988665ee376abce49613701336544041f2117de7b7fbfe91b93d8ff8b151c8e", size = 209669 }, + { url = "https://files.pythonhosted.org/packages/31/31/6a56469609a252549dd4b090815428d5521edd4642440d987573a450c069/coverage-7.6.8-cp310-cp310-win_amd64.whl", hash = "sha256:f56f49b2553d7dd85fd86e029515a221e5c1f8cb3d9c38b470bc38bde7b8445a", size = 210509 }, + { url = "https://files.pythonhosted.org/packages/ab/9f/e98211980f6e2f439e251737482aa77906c9b9c507824c71a2ce7eea0402/coverage-7.6.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:86cffe9c6dfcfe22e28027069725c7f57f4b868a3f86e81d1c62462764dc46d4", size = 207093 }, + { url = "https://files.pythonhosted.org/packages/fd/c7/8bab83fb9c20f7f8163c5a20dcb62d591b906a214a6dc6b07413074afc80/coverage-7.6.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d82ab6816c3277dc962cfcdc85b1efa0e5f50fb2c449432deaf2398a2928ab94", size = 207536 }, + { url = "https://files.pythonhosted.org/packages/1e/d6/00243df625f1b282bb25c83ce153ae2c06f8e7a796a8d833e7235337b4d9/coverage-7.6.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13690e923a3932e4fad4c0ebfb9cb5988e03d9dcb4c5150b5fcbf58fd8bddfc4", size = 239482 }, + { url = "https://files.pythonhosted.org/packages/1e/07/faf04b3eeb55ffc2a6f24b65dffe6e0359ec3b283e6efb5050ea0707446f/coverage-7.6.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be32da0c3827ac9132bb488d331cb32e8d9638dd41a0557c5569d57cf22c9c1", size = 236886 }, + { url = "https://files.pythonhosted.org/packages/43/23/c79e497bf4d8fcacd316bebe1d559c765485b8ec23ac4e23025be6bfce09/coverage-7.6.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44e6c85bbdc809383b509d732b06419fb4544dca29ebe18480379633623baafb", size = 238749 }, + { url = "https://files.pythonhosted.org/packages/b5/e5/791bae13be3c6451e32ef7af1192e711c6a319f3c597e9b218d148fd0633/coverage-7.6.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:768939f7c4353c0fac2f7c37897e10b1414b571fd85dd9fc49e6a87e37a2e0d8", size = 237679 }, + { url = "https://files.pythonhosted.org/packages/05/c6/bbfdfb03aada601fb8993ced17468c8c8e0b4aafb3097026e680fabb7ce1/coverage-7.6.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e44961e36cb13c495806d4cac67640ac2866cb99044e210895b506c26ee63d3a", size = 236317 }, + { url = "https://files.pythonhosted.org/packages/67/f9/f8e5a4b2ce96d1b0e83ae6246369eb8437001dc80ec03bb51c87ff557cd8/coverage-7.6.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ea8bb1ab9558374c0ab591783808511d135a833c3ca64a18ec927f20c4030f0", size = 237084 }, + { url = "https://files.pythonhosted.org/packages/f0/70/b05328901e4debe76e033717e1452d00246c458c44e9dbd893e7619c2967/coverage-7.6.8-cp311-cp311-win32.whl", hash = "sha256:629a1ba2115dce8bf75a5cce9f2486ae483cb89c0145795603d6554bdc83e801", size = 209638 }, + { url = "https://files.pythonhosted.org/packages/70/55/1efa24f960a2fa9fbc44a9523d3f3c50ceb94dd1e8cd732168ab2dc41b07/coverage-7.6.8-cp311-cp311-win_amd64.whl", hash = "sha256:fb9fc32399dca861584d96eccd6c980b69bbcd7c228d06fb74fe53e007aa8ef9", size = 210506 }, + { url = "https://files.pythonhosted.org/packages/76/ce/3edf581c8fe429ed8ced6e6d9ac693c25975ef9093413276dab6ed68a80a/coverage-7.6.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e683e6ecc587643f8cde8f5da6768e9d165cd31edf39ee90ed7034f9ca0eefee", size = 207285 }, + { url = "https://files.pythonhosted.org/packages/09/9c/cf102ab046c9cf8895c3f7aadcde6f489a4b2ec326757e8c6e6581829b5e/coverage-7.6.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1defe91d41ce1bd44b40fabf071e6a01a5aa14de4a31b986aa9dfd1b3e3e414a", size = 207522 }, + { url = "https://files.pythonhosted.org/packages/39/06/42aa6dd13dbfca72e1fd8ffccadbc921b6e75db34545ebab4d955d1e7ad3/coverage-7.6.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7ad66e8e50225ebf4236368cc43c37f59d5e6728f15f6e258c8639fa0dd8e6d", size = 240543 }, + { url = "https://files.pythonhosted.org/packages/a0/20/2932971dc215adeca8eeff446266a7fef17a0c238e881ffedebe7bfa0669/coverage-7.6.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fe47da3e4fda5f1abb5709c156eca207eacf8007304ce3019eb001e7a7204cb", size = 237577 }, + { url = "https://files.pythonhosted.org/packages/ac/85/4323ece0cd5452c9522f4b6e5cc461e6c7149a4b1887c9e7a8b1f4e51146/coverage-7.6.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:202a2d645c5a46b84992f55b0a3affe4f0ba6b4c611abec32ee88358db4bb649", size = 239646 }, + { url = "https://files.pythonhosted.org/packages/77/52/b2537487d8f36241e518e84db6f79e26bc3343b14844366e35b090fae0d4/coverage-7.6.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4674f0daa1823c295845b6a740d98a840d7a1c11df00d1fd62614545c1583787", size = 239128 }, + { url = "https://files.pythonhosted.org/packages/7c/99/7f007762012186547d0ecc3d328da6b6f31a8c99f05dc1e13dcd929918cd/coverage-7.6.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:74610105ebd6f33d7c10f8907afed696e79c59e3043c5f20eaa3a46fddf33b4c", size = 237434 }, + { url = "https://files.pythonhosted.org/packages/97/53/e9b5cf0682a1cab9352adfac73caae0d77ae1d65abc88975d510f7816389/coverage-7.6.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37cda8712145917105e07aab96388ae76e787270ec04bcb9d5cc786d7cbb8443", size = 239095 }, + { url = "https://files.pythonhosted.org/packages/0c/50/054f0b464fbae0483217186478eefa2e7df3a79917ed7f1d430b6da2cf0d/coverage-7.6.8-cp312-cp312-win32.whl", hash = "sha256:9e89d5c8509fbd6c03d0dd1972925b22f50db0792ce06324ba069f10787429ad", size = 209895 }, + { url = "https://files.pythonhosted.org/packages/df/d0/09ba870360a27ecf09e177ca2ff59d4337fc7197b456f22ceff85cffcfa5/coverage-7.6.8-cp312-cp312-win_amd64.whl", hash = "sha256:379c111d3558272a2cae3d8e57e6b6e6f4fe652905692d54bad5ea0ca37c5ad4", size = 210684 }, + { url = "https://files.pythonhosted.org/packages/9a/84/6f0ccf94a098ac3d6d6f236bd3905eeac049a9e0efcd9a63d4feca37ac4b/coverage-7.6.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b0c69f4f724c64dfbfe79f5dfb503b42fe6127b8d479b2677f2b227478db2eb", size = 207313 }, + { url = "https://files.pythonhosted.org/packages/db/2b/e3b3a3a12ebec738c545897ac9f314620470fcbc368cdac88cf14974ba20/coverage-7.6.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c15b32a7aca8038ed7644f854bf17b663bc38e1671b5d6f43f9a2b2bd0c46f63", size = 207574 }, + { url = "https://files.pythonhosted.org/packages/db/c0/5bf95d42b6a8d21dfce5025ce187f15db57d6460a59b67a95fe8728162f1/coverage-7.6.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63068a11171e4276f6ece913bde059e77c713b48c3a848814a6537f35afb8365", size = 240090 }, + { url = "https://files.pythonhosted.org/packages/57/b8/d6fd17d1a8e2b0e1a4e8b9cb1f0f261afd422570735899759c0584236916/coverage-7.6.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4548c5ead23ad13fb7a2c8ea541357474ec13c2b736feb02e19a3085fac002", size = 237237 }, + { url = "https://files.pythonhosted.org/packages/d4/e4/a91e9bb46809c8b63e68fc5db5c4d567d3423b6691d049a4f950e38fbe9d/coverage-7.6.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4b4299dd0d2c67caaaf286d58aef5e75b125b95615dda4542561a5a566a1e3", size = 239225 }, + { url = "https://files.pythonhosted.org/packages/31/9c/9b99b0591ec4555b7292d271e005f27b465388ce166056c435b288db6a69/coverage-7.6.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9ebfb2507751f7196995142f057d1324afdab56db1d9743aab7f50289abd022", size = 238888 }, + { url = "https://files.pythonhosted.org/packages/a6/85/285c2df9a04bc7c31f21fd9d4a24d19e040ec5e2ff06e572af1f6514c9e7/coverage-7.6.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c1b4474beee02ede1eef86c25ad4600a424fe36cff01a6103cb4533c6bf0169e", size = 236974 }, + { url = "https://files.pythonhosted.org/packages/cb/a1/95ec8522206f76cdca033bf8bb61fff56429fb414835fc4d34651dfd29fc/coverage-7.6.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9fd2547e6decdbf985d579cf3fc78e4c1d662b9b0ff7cc7862baaab71c9cc5b", size = 238815 }, + { url = "https://files.pythonhosted.org/packages/8d/ac/687e9ba5e6d0979e9dab5c02e01c4f24ac58260ef82d88d3b433b3f84f1e/coverage-7.6.8-cp313-cp313-win32.whl", hash = "sha256:8aae5aea53cbfe024919715eca696b1a3201886ce83790537d1c3668459c7146", size = 209957 }, + { url = "https://files.pythonhosted.org/packages/2f/a3/b61cc8e3fcf075293fb0f3dee405748453c5ba28ac02ceb4a87f52bdb105/coverage-7.6.8-cp313-cp313-win_amd64.whl", hash = "sha256:ae270e79f7e169ccfe23284ff5ea2d52a6f401dc01b337efb54b3783e2ce3f28", size = 210711 }, + { url = "https://files.pythonhosted.org/packages/ee/4b/891c8b9acf1b62c85e4a71dac142ab9284e8347409b7355de02e3f38306f/coverage-7.6.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de38add67a0af869b0d79c525d3e4588ac1ffa92f39116dbe0ed9753f26eba7d", size = 208053 }, + { url = "https://files.pythonhosted.org/packages/18/a9/9e330409b291cc002723d339346452800e78df1ce50774ca439ade1d374f/coverage-7.6.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b07c25d52b1c16ce5de088046cd2432b30f9ad5e224ff17c8f496d9cb7d1d451", size = 208329 }, + { url = "https://files.pythonhosted.org/packages/9c/0d/33635fd429f6589c6e1cdfc7bf581aefe4c1792fbff06383f9d37f59db60/coverage-7.6.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62a66ff235e4c2e37ed3b6104d8b478d767ff73838d1222132a7a026aa548764", size = 251052 }, + { url = "https://files.pythonhosted.org/packages/23/32/8a08da0e46f3830bbb9a5b40614241b2e700f27a9c2889f53122486443ed/coverage-7.6.8-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09b9f848b28081e7b975a3626e9081574a7b9196cde26604540582da60235fdf", size = 246765 }, + { url = "https://files.pythonhosted.org/packages/56/3f/3b86303d2c14350fdb1c6c4dbf9bc76000af2382f42ca1d4d99c6317666e/coverage-7.6.8-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:093896e530c38c8e9c996901858ac63f3d4171268db2c9c8b373a228f459bbc5", size = 249125 }, + { url = "https://files.pythonhosted.org/packages/36/cb/c4f081b9023f9fd8646dbc4ef77be0df090263e8f66f4ea47681e0dc2cff/coverage-7.6.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a7b8ac36fd688c8361cbc7bf1cb5866977ece6e0b17c34aa0df58bda4fa18a4", size = 248615 }, + { url = "https://files.pythonhosted.org/packages/32/ee/53bdbf67760928c44b57b2c28a8c0a4bf544f85a9ee129a63ba5c78fdee4/coverage-7.6.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:38c51297b35b3ed91670e1e4efb702b790002e3245a28c76e627478aa3c10d83", size = 246507 }, + { url = "https://files.pythonhosted.org/packages/57/49/5a57910bd0af6d8e802b4ca65292576d19b54b49f81577fd898505dee075/coverage-7.6.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2e4e0f60cb4bd7396108823548e82fdab72d4d8a65e58e2c19bbbc2f1e2bfa4b", size = 247785 }, + { url = "https://files.pythonhosted.org/packages/bd/37/e450c9f6b297c79bb9858407396ed3e084dcc22990dd110ab01d5ceb9770/coverage-7.6.8-cp313-cp313t-win32.whl", hash = "sha256:6535d996f6537ecb298b4e287a855f37deaf64ff007162ec0afb9ab8ba3b8b71", size = 210605 }, + { url = "https://files.pythonhosted.org/packages/44/79/7d0c7dd237c6905018e2936cd1055fe1d42e7eba2ebab3c00f4aad2a27d7/coverage-7.6.8-cp313-cp313t-win_amd64.whl", hash = "sha256:c79c0685f142ca53256722a384540832420dff4ab15fec1863d7e5bc8691bdcc", size = 211777 }, + { url = "https://files.pythonhosted.org/packages/2e/db/5c7008bcd8858c2dea02702ef0fee761f23780a6be7cd1292840f3e165b1/coverage-7.6.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ac47fa29d8d41059ea3df65bd3ade92f97ee4910ed638e87075b8e8ce69599e", size = 206983 }, + { url = "https://files.pythonhosted.org/packages/1c/30/e1be5b6802baa55967e83bdf57bd51cd2763b72cdc591a90aa0b465fffee/coverage-7.6.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24eda3a24a38157eee639ca9afe45eefa8d2420d49468819ac5f88b10de84f4c", size = 207422 }, + { url = "https://files.pythonhosted.org/packages/f6/df/19c0e12f9f7b976cd7b92ae8200d26f5b6cd3f322d17ac7b08d48fbf5bc5/coverage-7.6.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4c81ed2820b9023a9a90717020315e63b17b18c274a332e3b6437d7ff70abe0", size = 235455 }, + { url = "https://files.pythonhosted.org/packages/e8/7a/a80b0c4fb48e8bce92bcfe3908e47e6c7607fb8f618a4e0de78218e42d9b/coverage-7.6.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd55f8fc8fa494958772a2a7302b0354ab16e0b9272b3c3d83cdb5bec5bd1779", size = 233376 }, + { url = "https://files.pythonhosted.org/packages/8c/0e/1a4ecee734d70b78fc458ff611707f804605721467ef45fc1f1a684772ad/coverage-7.6.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f39e2f3530ed1626c66e7493be7a8423b023ca852aacdc91fb30162c350d2a92", size = 234509 }, + { url = "https://files.pythonhosted.org/packages/24/42/6eadd73adc0163cb18dee4fef80baefeb3faa11a1e217a2db80e274e784d/coverage-7.6.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:716a78a342679cd1177bc8c2fe957e0ab91405bd43a17094324845200b2fddf4", size = 233659 }, + { url = "https://files.pythonhosted.org/packages/68/5f/10b825f39ecfe6fc5ee3120205daaa0950443948f0d0a538430f386fdf58/coverage-7.6.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:177f01eeaa3aee4a5ffb0d1439c5952b53d5010f86e9d2667963e632e30082cc", size = 232138 }, + { url = "https://files.pythonhosted.org/packages/56/72/ad92bdad934de103e19a128a349ef4a0560892fd33d62becb1140885e44c/coverage-7.6.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:912e95017ff51dc3d7b6e2be158dedc889d9a5cc3382445589ce554f1a34c0ea", size = 233131 }, + { url = "https://files.pythonhosted.org/packages/f4/1d/d61d9b2d17628c4db834e9650b776663535b4258d0dc204ec475188b5b2a/coverage-7.6.8-cp39-cp39-win32.whl", hash = "sha256:4db3ed6a907b555e57cc2e6f14dc3a4c2458cdad8919e40b5357ab9b6db6c43e", size = 209695 }, + { url = "https://files.pythonhosted.org/packages/0f/d1/ef43852a998c41183dbffed4ab0dd658f9975d570c6106ea43fdcb5dcbf4/coverage-7.6.8-cp39-cp39-win_amd64.whl", hash = "sha256:428ac484592f780e8cd7b6b14eb568f7c85460c92e2a37cb0c0e5186e1a0d076", size = 210475 }, + { url = "https://files.pythonhosted.org/packages/32/df/0d2476121cd0bfb9ca2413efe02289c474b82c4b134863bef4b89ec7bcfa/coverage-7.6.8-pp39.pp310-none-any.whl", hash = "sha256:5c52a036535d12590c32c49209e79cabaad9f9ad8aa4cbd875b68c4d67a9cbce", size = 199230 }, ] [package.optional-dependencies] @@ -258,16 +270,16 @@ wheels = [ [[package]] name = "django" -version = "5.1.3" +version = "5.1.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asgiref", marker = "python_full_version >= '3.10'" }, { name = "sqlparse", marker = "python_full_version >= '3.10'" }, { name = "tzdata", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/85/ba2c2b83ba8b95354f99ed8344405d9571109ce0175028876209d6b93fba/Django-5.1.3.tar.gz", hash = "sha256:c0fa0e619c39325a169208caef234f90baa925227032ad3f44842ba14d75234a", size = 10698518 } +sdist = { url = "https://files.pythonhosted.org/packages/d3/e8/536555596dbb79f6e77418aeb40bdc1758c26725aba31919ba449e6d5e6a/Django-5.1.4.tar.gz", hash = "sha256:de450c09e91879fa5a307f696e57c851955c910a438a35e6b4c895e86bedc82a", size = 10716397 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/f6/88ed57e1b3ed54ff18c1da352aecbd6f51784c3e642d97586b61f050f5b1/Django-5.1.3-py3-none-any.whl", hash = "sha256:8b38a9a12da3ae00cb0ba72da985ec4b14de6345046b1e174b1fd7254398f818", size = 8276180 }, + { url = "https://files.pythonhosted.org/packages/58/0b/8a4ab2c02982df4ed41e29f28f189459a7eba37899438e6bea7f39db793b/Django-5.1.4-py3-none-any.whl", hash = "sha256:236e023f021f5ce7dee5779de7b286565fdea5f4ab86bae5338e3f7b69896cf0", size = 8276471 }, ] [[package]] @@ -290,11 +302,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.12.2" +version = "3.16.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/00/0b/c506e9e44e4c4b6c89fcecda23dc115bf8e7ff7eb127e0cb9c114cbc9a15/filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81", size = 12441 } +sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/45/ec3407adf6f6b5bf867a4462b2b0af27597a26bd3cd6e2534cb6ab029938/filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec", size = 10923 }, + { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, ] [[package]] @@ -303,8 +315,7 @@ version = "2024.8.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "beautifulsoup4" }, - { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pygments" }, { name = "sphinx" }, { name = "sphinx-basic-ng" }, ] @@ -324,11 +335,11 @@ wheels = [ [[package]] name = "identify" -version = "2.5.24" +version = "2.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c4/f8/498e13e408d25ee6ff04aa0acbf91ad8e9caae74be91720fc0e811e649b7/identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4", size = 98886 } +sdist = { url = "https://files.pythonhosted.org/packages/1a/5f/05f0d167be94585d502b4adf8c7af31f1dc0b1c7e14f9938a88fdbbcf4a7/identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02", size = 99179 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/fd/2c46fba2bc032ba4c970bb8de59d25187087d7138a0ebf7c1dcc91d94f01/identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d", size = 98826 }, + { url = "https://files.pythonhosted.org/packages/c9/f5/09644a3ad803fae9eca8efa17e1f2aef380c7f0b02f7ec4e8d446e51d64a/identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd", size = 99049 }, ] [[package]] @@ -351,14 +362,14 @@ wheels = [ [[package]] name = "importlib-metadata" -version = "6.7.0" +version = "8.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a3/82/f6e29c8d5c098b6be61460371c2c5591f4a335923639edec43b3830650a4/importlib_metadata-6.7.0.tar.gz", hash = "sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4", size = 53569 } +sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/94/64287b38c7de4c90683630338cf28f129decbba0a44f0c6db35a873c73c4/importlib_metadata-6.7.0-py3-none-any.whl", hash = "sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5", size = 22934 }, + { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, ] [[package]] @@ -485,31 +496,41 @@ wheels = [ [[package]] name = "mypy" -version = "1.4.1" +version = "1.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b3/28/d8a8233ff167d06108e53b7aefb4a8d7350adbbf9d7abd980f17fdb7a3a6/mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b", size = 2855162 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/3b/1c7363863b56c059f60a1dfdca9ac774a22ba64b7a4da0ee58ee53e5243f/mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8", size = 10451043 }, - { url = "https://files.pythonhosted.org/packages/a7/24/6f0df1874118839db1155fed62a4bd7e80c181367ff8ea07d40fbaffcfb4/mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878", size = 9542079 }, - { url = "https://files.pythonhosted.org/packages/04/5c/deeac94fcccd11aa621e6b350df333e1b809b11443774ea67582cc0205da/mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd", size = 11974913 }, - { url = "https://files.pythonhosted.org/packages/e5/2f/de3c455c54e8cf5e37ea38705c1920f2df470389f8fc051084d2dd8c9c59/mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc", size = 12044492 }, - { url = "https://files.pythonhosted.org/packages/e7/d3/6f65357dcb68109946de70cd55bd2e60f10114f387471302f48d54ff5dae/mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1", size = 8831655 }, - { url = "https://files.pythonhosted.org/packages/94/01/e34e37a044325af4d4af9825c15e8a0d26d89b5a9624b4d0908449d3411b/mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462", size = 10338636 }, - { url = "https://files.pythonhosted.org/packages/92/58/ccc0b714ecbd1a64b34d8ce1c38763ff6431de1d82551904ecc3711fbe05/mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258", size = 9444172 }, - { url = "https://files.pythonhosted.org/packages/73/72/dfc0b46e6905eafd598e7c48c0c4f2e232647e4e36547425c64e6c850495/mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2", size = 11855450 }, - { url = "https://files.pythonhosted.org/packages/66/f4/60739a2d336f3adf5628e7c9b920d16e8af6dc078550d615e4ba2a1d7759/mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7", size = 11928679 }, - { url = "https://files.pythonhosted.org/packages/8c/26/6ff2b55bf8b605a4cc898883654c2ca4dd4feedf0bb04ecaacf60d165cde/mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01", size = 8831134 }, - { url = "https://files.pythonhosted.org/packages/1d/1b/9050b5c444ef82c3d59bdbf21f91b259cf20b2ac1df37d55bc6b91d609a1/mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828", size = 10447897 }, - { url = "https://files.pythonhosted.org/packages/da/00/ac2b58b321d85cac25be0dcd1bc2427dfc6cf403283fc205a0031576f14b/mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3", size = 9534091 }, - { url = "https://files.pythonhosted.org/packages/c4/10/26240f14e854a95af87d577b288d607ebe0ccb75cb37052f6386402f022d/mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816", size = 11970165 }, - { url = "https://files.pythonhosted.org/packages/b7/34/a3edaec8762181bfe97439c7e094f4c2f411ed9b79ac8f4d72156e88d5ce/mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c", size = 12040792 }, - { url = "https://files.pythonhosted.org/packages/d1/f3/0d0622d5a83859a992b01741a7b97949d6fb9efc9f05f20a09f0df10dc1e/mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f", size = 8831367 }, - { url = "https://files.pythonhosted.org/packages/3d/9a/e13addb8d652cb068f835ac2746d9d42f85b730092f581bb17e2059c28f1/mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4", size = 2451741 }, +sdist = { url = "https://files.pythonhosted.org/packages/e8/21/7e9e523537991d145ab8a0a2fd98548d67646dc2aaaf6091c31ad883e7c1/mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e", size = 3152532 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/8c/206de95a27722b5b5a8c85ba3100467bd86299d92a4f71c6b9aa448bfa2f/mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a", size = 11020731 }, + { url = "https://files.pythonhosted.org/packages/ab/bb/b31695a29eea76b1569fd28b4ab141a1adc9842edde080d1e8e1776862c7/mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80", size = 10184276 }, + { url = "https://files.pythonhosted.org/packages/a5/2d/4a23849729bb27934a0e079c9c1aad912167d875c7b070382a408d459651/mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7", size = 12587706 }, + { url = "https://files.pythonhosted.org/packages/5c/c3/d318e38ada50255e22e23353a469c791379825240e71b0ad03e76ca07ae6/mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f", size = 13105586 }, + { url = "https://files.pythonhosted.org/packages/4a/25/3918bc64952370c3dbdbd8c82c363804678127815febd2925b7273d9482c/mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372", size = 9632318 }, + { url = "https://files.pythonhosted.org/packages/d0/19/de0822609e5b93d02579075248c7aa6ceaddcea92f00bf4ea8e4c22e3598/mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d", size = 10939027 }, + { url = "https://files.pythonhosted.org/packages/c8/71/6950fcc6ca84179137e4cbf7cf41e6b68b4a339a1f5d3e954f8c34e02d66/mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d", size = 10108699 }, + { url = "https://files.pythonhosted.org/packages/26/50/29d3e7dd166e74dc13d46050b23f7d6d7533acf48f5217663a3719db024e/mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b", size = 12506263 }, + { url = "https://files.pythonhosted.org/packages/3f/1d/676e76f07f7d5ddcd4227af3938a9c9640f293b7d8a44dd4ff41d4db25c1/mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73", size = 12984688 }, + { url = "https://files.pythonhosted.org/packages/9c/03/5a85a30ae5407b1d28fab51bd3e2103e52ad0918d1e68f02a7778669a307/mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca", size = 9626811 }, + { url = "https://files.pythonhosted.org/packages/fb/31/c526a7bd2e5c710ae47717c7a5f53f616db6d9097caf48ad650581e81748/mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5", size = 11077900 }, + { url = "https://files.pythonhosted.org/packages/83/67/b7419c6b503679d10bd26fc67529bc6a1f7a5f220bbb9f292dc10d33352f/mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e", size = 10074818 }, + { url = "https://files.pythonhosted.org/packages/ba/07/37d67048786ae84e6612575e173d713c9a05d0ae495dde1e68d972207d98/mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2", size = 12589275 }, + { url = "https://files.pythonhosted.org/packages/1f/17/b1018c6bb3e9f1ce3956722b3bf91bff86c1cefccca71cec05eae49d6d41/mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0", size = 13037783 }, + { url = "https://files.pythonhosted.org/packages/cb/32/cd540755579e54a88099aee0287086d996f5a24281a673f78a0e14dba150/mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2", size = 9726197 }, + { url = "https://files.pythonhosted.org/packages/11/bb/ab4cfdc562cad80418f077d8be9b4491ee4fb257440da951b85cbb0a639e/mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7", size = 11069721 }, + { url = "https://files.pythonhosted.org/packages/59/3b/a393b1607cb749ea2c621def5ba8c58308ff05e30d9dbdc7c15028bca111/mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62", size = 10063996 }, + { url = "https://files.pythonhosted.org/packages/d1/1f/6b76be289a5a521bb1caedc1f08e76ff17ab59061007f201a8a18cc514d1/mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8", size = 12584043 }, + { url = "https://files.pythonhosted.org/packages/a6/83/5a85c9a5976c6f96e3a5a7591aa28b4a6ca3a07e9e5ba0cec090c8b596d6/mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7", size = 13036996 }, + { url = "https://files.pythonhosted.org/packages/b4/59/c39a6f752f1f893fccbcf1bdd2aca67c79c842402b5283563d006a67cf76/mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc", size = 9737709 }, + { url = "https://files.pythonhosted.org/packages/5f/d4/b33ddd40dad230efb317898a2d1c267c04edba73bc5086bf77edeb410fb2/mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc", size = 11013906 }, + { url = "https://files.pythonhosted.org/packages/f4/e6/f414bca465b44d01cd5f4a82761e15044bedd1bf8025c5af3cc64518fac5/mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732", size = 10180657 }, + { url = "https://files.pythonhosted.org/packages/38/e9/fc3865e417722f98d58409770be01afb961e2c1f99930659ff4ae7ca8b7e/mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc", size = 12586394 }, + { url = "https://files.pythonhosted.org/packages/2e/35/f4d8b6d2cb0b3dad63e96caf159419dda023f45a358c6c9ac582ccaee354/mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d", size = 13103591 }, + { url = "https://files.pythonhosted.org/packages/22/1d/80594aef135f921dd52e142fa0acd19df197690bd0cde42cea7b88cf5aa2/mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24", size = 9634690 }, + { url = "https://files.pythonhosted.org/packages/3b/86/72ce7f57431d87a7ff17d442f521146a6585019eb8f4f31b7c02801f78ad/mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a", size = 2647043 }, ] [[package]] @@ -549,11 +570,11 @@ wheels = [ [[package]] name = "packaging" -version = "24.0" +version = "24.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/b5/b43a27ac7472e1818c4bafd44430e69605baefe1f34440593e0332ec8b4d/packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9", size = 147882 } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } wheels = [ - { url = "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", size = 53488 }, + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, ] [[package]] @@ -653,32 +674,17 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.0.0" +version = "4.3.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/28/e40d24d2e2eb23135f8533ad33d582359c7825623b1e022f9d460def7c05/platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731", size = 19914 } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/16/70be3b725073035aa5fc3229321d06e22e73e3e09f6af78dcfdf16c7636c/platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", size = 17562 }, -] - -[[package]] -name = "pluggy" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/8a/42/8f2833655a29c4e9cb52ee8a2be04ceac61bcff4a680fb338cbd3d1e322d/pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3", size = 61613 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/32/4a79112b8b87b21450b066e102d6608907f4c885ed7b04c3fdb085d4d6ae/pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", size = 17695 }, + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, ] [[package]] name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, @@ -686,7 +692,7 @@ wheels = [ [[package]] name = "pre-commit" -version = "2.21.0" +version = "4.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, @@ -695,9 +701,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6b/00/1637ae945c6e10838ef5c41965f1c864e59301811bb203e979f335608e7c/pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658", size = 174966 } +sdist = { url = "https://files.pythonhosted.org/packages/2e/c8/e22c292035f1bac8b9f5237a2622305bc0304e776080b246f3df57c4ff9f/pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2", size = 191678 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/6b/6cfe3a8b351b54f4b6c6d2ad4286804e3367f628dce379c603d3b96635f4/pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad", size = 201938 }, + { url = "https://files.pythonhosted.org/packages/16/8f/496e10d51edd6671ebe0432e33ff800aa86775d2d147ce7d43389324a525/pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878", size = 218713 }, ] [[package]] @@ -711,35 +717,20 @@ wheels = [ [[package]] name = "pydot" -version = "2.0.0" +version = "3.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyparsing" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d7/2f/482fcbc389e180e7f8d7e7cb06bc5a7c37be6c57939dfb950951d97f2722/pydot-2.0.0.tar.gz", hash = "sha256:60246af215123fa062f21cd791be67dda23a6f280df09f68919e637a1e4f3235", size = 152022 } +sdist = { url = "https://files.pythonhosted.org/packages/bf/b8/500a772825c7ca87e4fd69c3bd6740e3375d6792a7065dd92759249f223d/pydot-3.0.3.tar.gz", hash = "sha256:5e009d97b2fff92b7a88f09ec1fd5b163f07f3b10469c927d362471d6faa0d50", size = 168086 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/90/c9b51f3cdff89cd8f93382060330f43d1af098a6624cff439e700791e922/pydot-2.0.0-py3-none-any.whl", hash = "sha256:408a47913ea7bd5d2d34b274144880c1310c4aee901f353cf21fe2e526a4ea28", size = 22675 }, -] - -[[package]] -name = "pygments" -version = "2.17.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/55/59/8bccf4157baf25e4aa5a0bb7fa3ba8600907de105ebc22b0c78cfbf6f565/pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367", size = 4827772 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", size = 1179756 }, + { url = "https://files.pythonhosted.org/packages/3e/1b/ef569ac44598b6b24bc0f80d5ac4f811af59d3f0d0d23b0216e014c0ec33/pydot-3.0.3-py3-none-any.whl", hash = "sha256:9b0b3081e0bd362d0c61148da10eb1281ec80089b02a28cf06f9093843986f3d", size = 35784 }, ] [[package]] name = "pygments" version = "2.18.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", size = 4891905 } wheels = [ { url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 }, @@ -747,20 +738,11 @@ wheels = [ [[package]] name = "pyparsing" -version = "3.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/08/13f3bce01b2061f2bbd582c9df82723de943784cf719a35ac886c652043a/pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032", size = 900231 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/0c/0e3c05b1c87bb6a1c76d281b0f35e78d2d80ac91b5f8f524cebf77f51049/pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c", size = 104100 }, -] - -[[package]] -name = "pyreadline3" -version = "3.5.4" +version = "3.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839 } +sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/e5aeee5387091148a19e1145f63606619cb5f20b83fccb63efae6474e7b2/pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c", size = 920984 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 }, + { url = "https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", size = 106921 }, ] [[package]] @@ -774,83 +756,40 @@ wheels = [ [[package]] name = "pytest" -version = "7.4.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, - { name = "iniconfig", marker = "python_full_version < '3.10'" }, - { name = "packaging", marker = "python_full_version < '3.10'" }, - { name = "pluggy", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "tomli", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/80/1f/9d8e98e4133ffb16c90f3b405c43e38d3abb715bb5d7a63a5a684f7e46a3/pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", size = 1357116 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8", size = 325287 }, -] - -[[package]] -name = "pytest" -version = "8.3.3" +version = "8.3.4" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, - { name = "iniconfig", marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.10'" }, - { name = "pluggy", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version == '3.10.*'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/6c/62bbd536103af674e227c41a8f3dcd022d591f6eed5facb5a0f31ee33bbc/pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", size = 1442487 } +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341 }, + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, ] [[package]] name = "pytest-asyncio" -version = "0.21.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ae/53/57663d99acaac2fcdafdc697e52a9b1b7d6fcf36616281ff9768a44e7ff3/pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45", size = 30656 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/ce/1e4b53c213dce25d6e8b163697fbce2d43799d76fa08eea6ad270451c370/pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b", size = 13368 }, -] - -[[package]] -name = "pytest-benchmark" -version = "4.0.0" +version = "0.24.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] dependencies = [ - { name = "py-cpuinfo", marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/28/08/e6b0067efa9a1f2a1eb3043ecd8a0c48bfeb60d3255006dcc829d72d5da2/pytest-benchmark-4.0.0.tar.gz", hash = "sha256:fb0785b83efe599a6a956361c0691ae1dbb5318018561af10f3e915caa0048d1", size = 334641 } +sdist = { url = "https://files.pythonhosted.org/packages/52/6d/c6cf50ce320cf8611df7a1254d86233b3df7cc07f9b5f5cbcb82e08aa534/pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276", size = 49855 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/a1/3b70862b5b3f830f0422844f25a823d0470739d994466be9dbbbb414d85a/pytest_benchmark-4.0.0-py3-none-any.whl", hash = "sha256:fdb7db64e31c8b277dff9850d2a2556d8b60bcb0ea6524e36e28ffd7c87f71d6", size = 43951 }, + { url = "https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b", size = 18024 }, ] [[package]] name = "pytest-benchmark" version = "5.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "py-cpuinfo", marker = "python_full_version >= '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "py-cpuinfo" }, + { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/39/d0/a8bd08d641b393db3be3819b03e2d9bb8760ca8479080a26a5f6e540e99c/pytest-benchmark-5.1.0.tar.gz", hash = "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105", size = 337810 } wheels = [ @@ -859,16 +798,15 @@ wheels = [ [[package]] name = "pytest-cov" -version = "4.1.0" +version = "6.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7a/15/da3df99fd551507694a9b01f512a2f6cf1254f33601605843c3775f39460/pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6", size = 63245 } +sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/4b/8b78d126e275efa2379b1c2e09dc52cf70df16fc3b90613ef82531499d73/pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a", size = 21949 }, + { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, ] [[package]] @@ -876,8 +814,7 @@ name = "pytest-django" version = "4.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/02/c0/43c8b2528c24d7f1a48a47e3f7381f5ab2ae8c64634b0c3f4bd843063955/pytest_django-4.9.0.tar.gz", hash = "sha256:8bf7bc358c9ae6f6fc51b6cebb190fe20212196e6807121f11bd6a3b03428314", size = 84067 } wheels = [ @@ -886,15 +823,14 @@ wheels = [ [[package]] name = "pytest-mock" -version = "3.11.1" +version = "3.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/2d/b3a811ec4fa24190a9ec5013e23c89421a7916167c6240c31fdc445f850c/pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f", size = 31251 } +sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814 } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/85/80ae98e019a429445bfb74e153d4cb47c3695e3e908515e95e95c18237e5/pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39", size = 9590 }, + { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863 }, ] [[package]] @@ -903,8 +839,7 @@ version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pytest" }, { name = "termcolor" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/ac/5754f5edd6d508bc6493bc37d74b928f102a5fff82d9a80347e180998f08/pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a", size = 14992 } @@ -932,12 +867,9 @@ dev = [ { name = "pillow" }, { name = "pre-commit" }, { name = "pydot" }, - { name = "pydot" }, - { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pytest" }, { name = "pytest-asyncio" }, - { name = "pytest-benchmark", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pytest-benchmark", version = "5.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pytest-benchmark" }, { name = "pytest-cov" }, { name = "pytest-django" }, { name = "pytest-mock" }, @@ -962,7 +894,6 @@ dev = [ { name = "pillow" }, { name = "pre-commit" }, { name = "pydot" }, - { name = "pydot" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-benchmark", specifier = ">=4.0.0" }, @@ -971,49 +902,63 @@ dev = [ { name = "pytest-mock", specifier = ">=3.10.0" }, { name = "pytest-sugar", specifier = ">=1.0.0" }, { name = "ruff", specifier = ">=0.8.1" }, - { name = "sphinx", marker = "python_full_version >= '3.9'" }, - { name = "sphinx-autobuild", marker = "python_full_version >= '3.9'" }, - { name = "sphinx-copybutton", marker = "python_full_version >= '3.9'", specifier = ">=0.5.2" }, - { name = "sphinx-gallery", marker = "python_full_version >= '3.9'" }, + { name = "sphinx" }, + { name = "sphinx-autobuild" }, + { name = "sphinx-copybutton", specifier = ">=0.5.2" }, + { name = "sphinx-gallery" }, ] [[package]] name = "pyyaml" -version = "6.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/e5/af35f7ea75cf72f2cd079c95ee16797de7cd71f29ea7c68ae5ce7be1eda0/PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", size = 125201 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/06/4beb652c0fe16834032e54f0956443d4cc797fe645527acee59e7deaa0a2/PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", size = 189447 }, - { url = "https://files.pythonhosted.org/packages/5b/07/10033a403b23405a8fc48975444463d3d10a5c2736b7eb2550b07b367429/PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f", size = 169264 }, - { url = "https://files.pythonhosted.org/packages/f1/26/55e4f21db1f72eaef092015d9017c11510e7e6301c62a6cfee91295d13c6/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", size = 677003 }, - { url = "https://files.pythonhosted.org/packages/ba/91/090818dfa62e85181f3ae23dd1e8b7ea7f09684864a900cab72d29c57346/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", size = 699070 }, - { url = "https://files.pythonhosted.org/packages/29/61/bf33c6c85c55bc45a29eee3195848ff2d518d84735eb0e2d8cb42e0d285e/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", size = 705525 }, - { url = "https://files.pythonhosted.org/packages/07/91/45dfd0ef821a7f41d9d0136ea3608bb5b1653e42fd56a7970532cb5c003f/PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", size = 707514 }, - { url = "https://files.pythonhosted.org/packages/b6/a0/b6700da5d49e9fed49dc3243d3771b598dad07abb37cc32e524607f96adc/PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", size = 130488 }, - { url = "https://files.pythonhosted.org/packages/24/97/9b59b43431f98d01806b288532da38099cc6f2fea0f3d712e21e269c0279/PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", size = 145338 }, - { url = "https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", size = 187867 }, - { url = "https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", size = 167530 }, - { url = "https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", size = 732244 }, - { url = "https://files.pythonhosted.org/packages/06/92/e0224aa6ebf9dc54a06a4609da37da40bb08d126f5535d81bff6b417b2ae/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", size = 752871 }, - { url = "https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", size = 757729 }, - { url = "https://files.pythonhosted.org/packages/03/5c/c4671451b2f1d76ebe352c0945d4cd13500adb5d05f5a51ee296d80152f7/PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", size = 748528 }, - { url = "https://files.pythonhosted.org/packages/73/9c/766e78d1efc0d1fca637a6b62cea1b4510a7fb93617eb805223294fef681/PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", size = 130286 }, - { url = "https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", size = 144699 }, - { url = "https://files.pythonhosted.org/packages/bc/06/1b305bf6aa704343be85444c9d011f626c763abb40c0edc1cad13bfd7f86/PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", size = 178692 }, - { url = "https://files.pythonhosted.org/packages/84/02/404de95ced348b73dd84f70e15a41843d817ff8c1744516bf78358f2ffd2/PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", size = 165622 }, - { url = "https://files.pythonhosted.org/packages/c7/4c/4a2908632fc980da6d918b9de9c1d9d7d7e70b2672b1ad5166ed27841ef7/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", size = 696937 }, - { url = "https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", size = 724969 }, - { url = "https://files.pythonhosted.org/packages/4f/78/77b40157b6cb5f2d3d31a3d9b2efd1ba3505371f76730d267e8b32cf4b7f/PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", size = 712604 }, - { url = "https://files.pythonhosted.org/packages/2e/97/3e0e089ee85e840f4b15bfa00e4e63d84a3691ababbfea92d6f820ea6f21/PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", size = 126098 }, - { url = "https://files.pythonhosted.org/packages/2b/9f/fbade56564ad486809c27b322d0f7e6a89c01f6b4fe208402e90d4443a99/PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", size = 138675 }, - { url = "https://files.pythonhosted.org/packages/57/c5/5d09b66b41d549914802f482a2118d925d876dc2a35b2d127694c1345c34/PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", size = 197846 }, - { url = "https://files.pythonhosted.org/packages/0e/88/21b2f16cb2123c1e9375f2c93486e35fdc86e63f02e274f0e99c589ef153/PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", size = 174396 }, - { url = "https://files.pythonhosted.org/packages/ac/6c/967d91a8edf98d2b2b01d149bd9e51b8f9fb527c98d80ebb60c6b21d60c4/PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", size = 731824 }, - { url = "https://files.pythonhosted.org/packages/4a/4b/c71ef18ef83c82f99e6da8332910692af78ea32bd1d1d76c9787dfa36aea/PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", size = 754777 }, - { url = "https://files.pythonhosted.org/packages/7d/39/472f2554a0f1e825bd7c5afc11c817cd7a2f3657460f7159f691fbb37c51/PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", size = 738883 }, - { url = "https://files.pythonhosted.org/packages/40/da/a175a35cf5583580e90ac3e2a3dbca90e43011593ae62ce63f79d7b28d92/PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", size = 750294 }, - { url = "https://files.pythonhosted.org/packages/24/62/7fcc372442ec8ea331da18c24b13710e010c5073ab851ef36bf9dacb283f/PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", size = 136936 }, - { url = "https://files.pythonhosted.org/packages/84/4d/82704d1ab9290b03da94e6425f5e87396b999fd7eb8e08f3a92c158402bf/PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", size = 152751 }, +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199 }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758 }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463 }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280 }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239 }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802 }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527 }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052 }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774 }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, + { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777 }, + { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318 }, + { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891 }, + { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614 }, + { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360 }, + { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006 }, + { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577 }, + { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593 }, + { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312 }, ] [[package]] @@ -1033,17 +978,16 @@ wheels = [ [[package]] name = "rich" -version = "10.16.2" +version = "13.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama" }, - { name = "commonmark" }, - { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown-it-py" }, + { name = "pygments" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/c3/e55ebdd66540503cee29cd3bb18a90bcfd5587a0cf3680173c368be56093/rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b", size = 197585 } +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/0d/58939059015dce00122b008c3edccbb68f0767126020c939116e6d764cd7/rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03", size = 214400 }, + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] [[package]] @@ -1111,8 +1055,7 @@ dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "jinja2" }, { name = "packaging" }, - { name = "pygments", version = "2.17.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pygments", version = "2.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pygments" }, { name = "requests" }, { name = "snowballstemmer" }, { name = "sphinxcontrib-applehelp" }, @@ -1238,51 +1181,81 @@ wheels = [ [[package]] name = "sqlparse" -version = "0.4.4" +version = "0.5.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/16/10f170ec641ed852611b6c9441b23d10b5702ab5288371feab3d36de2574/sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c", size = 72383 } +sdist = { url = "https://files.pythonhosted.org/packages/57/61/5bc3aff85dc5bf98291b37cf469dab74b3d0aef2dd88eade9070a200af05/sqlparse-0.5.2.tar.gz", hash = "sha256:9e37b35e16d1cc652a2545f0997c1deb23ea28fa1f3eefe609eee3063c3b105f", size = 84951 } wheels = [ - { url = "https://files.pythonhosted.org/packages/98/5a/66d7c9305baa9f11857f247d4ba761402cea75db6058ff850ed7128957b7/sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3", size = 41183 }, + { url = "https://files.pythonhosted.org/packages/7a/13/5f6654c9d915077fae255686ca6fa42095b62b7337e3e1aa9e82caa6f43a/sqlparse-0.5.2-py3-none-any.whl", hash = "sha256:e99bc85c78160918c3e1d9230834ab8d80fc06c59d03f8db2618f65f65dda55e", size = 44407 }, ] [[package]] name = "starlette" -version = "0.41.2" +version = "0.41.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/da/1fb4bdb72ae12b834becd7e1e7e47001d32f91ec0ce8d7bc1b618d9f0bd9/starlette-0.41.2.tar.gz", hash = "sha256:9834fd799d1a87fd346deb76158668cfa0b0d56f85caefe8268e2d97c3468b62", size = 2573867 } +sdist = { url = "https://files.pythonhosted.org/packages/1a/4c/9b5764bd22eec91c4039ef4c55334e9187085da2d8a2df7bd570869aae18/starlette-0.41.3.tar.gz", hash = "sha256:0e4ab3d16522a255be6b28260b938eae2482f98ce5cc934cb08dce8dc3ba5835", size = 2574159 } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/43/f185bfd0ca1d213beb4293bed51d92254df23d8ceaf6c0e17146d508a776/starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d", size = 73259 }, + { url = "https://files.pythonhosted.org/packages/96/00/2b325970b3060c7cecebab6d295afe763365822b1306a12eeab198f74323/starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7", size = 73225 }, ] [[package]] name = "termcolor" -version = "2.3.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b8/85/147a0529b4e80b6b9d021ca8db3a820fcac53ec7374b87073d004aaf444c/termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a", size = 12163 } +sdist = { url = "https://files.pythonhosted.org/packages/37/72/88311445fd44c455c7d553e61f95412cf89054308a1aa2434ab835075fc5/termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f", size = 13057 } wheels = [ - { url = "https://files.pythonhosted.org/packages/67/e1/434566ffce04448192369c1a282931cf4ae593e91907558eaecd2e9f2801/termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475", size = 6872 }, + { url = "https://files.pythonhosted.org/packages/7f/be/df630c387a0a054815d60be6a97eb4e8f17385d5d6fe660e1c02750062b4/termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8", size = 7755 }, ] [[package]] name = "tomli" -version = "2.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", size = 15164 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757 }, +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, ] [[package]] name = "typing-extensions" -version = "4.7.1" +version = "4.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3c/8b/0111dd7d6c1478bf83baa1cab85c686426c7a6274119aceb2bd9d35395ad/typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2", size = 72876 } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/6b/63cc3df74987c36fe26157ee12e09e8f9db4de771e0f3404263117e75b95/typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", size = 33232 }, + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, ] [[package]] @@ -1305,194 +1278,194 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.32.0" +version = "0.32.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/fc/1d785078eefd6945f3e5bab5c076e4230698046231eb0f3747bc5c8fa992/uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e", size = 77564 } +sdist = { url = "https://files.pythonhosted.org/packages/6a/3c/21dba3e7d76138725ef307e3d7ddd29b763119b3aa459d02cc05fefcff75/uvicorn-0.32.1.tar.gz", hash = "sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175", size = 77630 } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/14/78bd0e95dd2444b6caacbca2b730671d4295ccb628ef58b81bee903629df/uvicorn-0.32.0-py3-none-any.whl", hash = "sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82", size = 63723 }, + { url = "https://files.pythonhosted.org/packages/50/c1/2d27b0a15826c2b71dcf6e2f5402181ef85acf439617bb2f1453125ce1f3/uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e", size = 63828 }, ] [[package]] name = "virtualenv" -version = "20.26.6" +version = "20.28.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/40/abc5a766da6b0b2457f819feab8e9203cbeae29327bd241359f866a3da9d/virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48", size = 9372482 } +sdist = { url = "https://files.pythonhosted.org/packages/bf/75/53316a5a8050069228a2f6d11f32046cfa94fbb6cc3f08703f59b873de2e/virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa", size = 7650368 } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/90/57b8ac0c8a231545adc7698c64c5a36fa7cd8e376c691b9bde877269f2eb/virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2", size = 5999862 }, + { url = "https://files.pythonhosted.org/packages/10/f9/0919cf6f1432a8c4baa62511f8f8da8225432d22e83e3476f5be1a1edc6e/virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0", size = 4276702 }, ] [[package]] name = "watchfiles" -version = "0.24.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c8/27/2ba23c8cc85796e2d41976439b08d52f691655fdb9401362099502d1f0cf/watchfiles-0.24.0.tar.gz", hash = "sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1", size = 37870 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/a1/631c12626378b9f1538664aa221feb5c60dfafbd7f60b451f8d0bdbcdedd/watchfiles-0.24.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:083dc77dbdeef09fa44bb0f4d1df571d2e12d8a8f985dccde71ac3ac9ac067a0", size = 375096 }, - { url = "https://files.pythonhosted.org/packages/f7/5c/f27c979c8a10aaa2822286c1bffdce3db731cd1aa4224b9f86623e94bbfe/watchfiles-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e94e98c7cb94cfa6e071d401ea3342767f28eb5a06a58fafdc0d2a4974f4f35c", size = 367425 }, - { url = "https://files.pythonhosted.org/packages/74/0d/1889e5649885484d29f6c792ef274454d0a26b20d6ed5fdba5409335ccb6/watchfiles-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82ae557a8c037c42a6ef26c494d0631cacca040934b101d001100ed93d43f361", size = 437705 }, - { url = "https://files.pythonhosted.org/packages/85/8a/01d9a22e839f0d1d547af11b1fcac6ba6f889513f1b2e6f221d9d60d9585/watchfiles-0.24.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acbfa31e315a8f14fe33e3542cbcafc55703b8f5dcbb7c1eecd30f141df50db3", size = 433636 }, - { url = "https://files.pythonhosted.org/packages/62/32/a93db78d340c7ef86cde469deb20e36c6b2a873edee81f610e94bbba4e06/watchfiles-0.24.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b74fdffce9dfcf2dc296dec8743e5b0332d15df19ae464f0e249aa871fc1c571", size = 451069 }, - { url = "https://files.pythonhosted.org/packages/99/c2/e9e2754fae3c2721c9a7736f92dab73723f1968ed72535fff29e70776008/watchfiles-0.24.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:449f43f49c8ddca87c6b3980c9284cab6bd1f5c9d9a2b00012adaaccd5e7decd", size = 469306 }, - { url = "https://files.pythonhosted.org/packages/4c/45/f317d9e3affb06c3c27c478de99f7110143e87f0f001f0f72e18d0e1ddce/watchfiles-0.24.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4abf4ad269856618f82dee296ac66b0cd1d71450fc3c98532d93798e73399b7a", size = 476187 }, - { url = "https://files.pythonhosted.org/packages/ac/d3/f1f37248abe0114916921e638f71c7d21fe77e3f2f61750e8057d0b68ef2/watchfiles-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f895d785eb6164678ff4bb5cc60c5996b3ee6df3edb28dcdeba86a13ea0465e", size = 425743 }, - { url = "https://files.pythonhosted.org/packages/2b/e8/c7037ea38d838fd81a59cd25761f106ee3ef2cfd3261787bee0c68908171/watchfiles-0.24.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ae3e208b31be8ce7f4c2c0034f33406dd24fbce3467f77223d10cd86778471c", size = 612327 }, - { url = "https://files.pythonhosted.org/packages/a0/c5/0e6e228aafe01a7995fbfd2a4edb221bb11a2744803b65a5663fb85e5063/watchfiles-0.24.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2efec17819b0046dde35d13fb8ac7a3ad877af41ae4640f4109d9154ed30a188", size = 595096 }, - { url = "https://files.pythonhosted.org/packages/63/d5/4780e8bf3de3b4b46e7428a29654f7dc041cad6b19fd86d083e4b6f64bbe/watchfiles-0.24.0-cp310-none-win32.whl", hash = "sha256:6bdcfa3cd6fdbdd1a068a52820f46a815401cbc2cb187dd006cb076675e7b735", size = 264149 }, - { url = "https://files.pythonhosted.org/packages/fe/1b/5148898ba55fc9c111a2a4a5fb67ad3fa7eb2b3d7f0618241ed88749313d/watchfiles-0.24.0-cp310-none-win_amd64.whl", hash = "sha256:54ca90a9ae6597ae6dc00e7ed0a040ef723f84ec517d3e7ce13e63e4bc82fa04", size = 277542 }, - { url = "https://files.pythonhosted.org/packages/85/02/366ae902cd81ca5befcd1854b5c7477b378f68861597cef854bd6dc69fbe/watchfiles-0.24.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:bdcd5538e27f188dd3c804b4a8d5f52a7fc7f87e7fd6b374b8e36a4ca03db428", size = 375579 }, - { url = "https://files.pythonhosted.org/packages/bc/67/d8c9d256791fe312fea118a8a051411337c948101a24586e2df237507976/watchfiles-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2dadf8a8014fde6addfd3c379e6ed1a981c8f0a48292d662e27cabfe4239c83c", size = 367726 }, - { url = "https://files.pythonhosted.org/packages/b1/dc/a8427b21ef46386adf824a9fec4be9d16a475b850616cfd98cf09a97a2ef/watchfiles-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6509ed3f467b79d95fc62a98229f79b1a60d1b93f101e1c61d10c95a46a84f43", size = 437735 }, - { url = "https://files.pythonhosted.org/packages/3a/21/0b20bef581a9fbfef290a822c8be645432ceb05fb0741bf3c032e0d90d9a/watchfiles-0.24.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8360f7314a070c30e4c976b183d1d8d1585a4a50c5cb603f431cebcbb4f66327", size = 433644 }, - { url = "https://files.pythonhosted.org/packages/1c/e8/d5e5f71cc443c85a72e70b24269a30e529227986096abe091040d6358ea9/watchfiles-0.24.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:316449aefacf40147a9efaf3bd7c9bdd35aaba9ac5d708bd1eb5763c9a02bef5", size = 450928 }, - { url = "https://files.pythonhosted.org/packages/61/ee/bf17f5a370c2fcff49e1fec987a6a43fd798d8427ea754ce45b38f9e117a/watchfiles-0.24.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73bde715f940bea845a95247ea3e5eb17769ba1010efdc938ffcb967c634fa61", size = 469072 }, - { url = "https://files.pythonhosted.org/packages/a3/34/03b66d425986de3fc6077e74a74c78da298f8cb598887f664a4485e55543/watchfiles-0.24.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3770e260b18e7f4e576edca4c0a639f704088602e0bc921c5c2e721e3acb8d15", size = 475517 }, - { url = "https://files.pythonhosted.org/packages/70/eb/82f089c4f44b3171ad87a1b433abb4696f18eb67292909630d886e073abe/watchfiles-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0fd7248cf533c259e59dc593a60973a73e881162b1a2f73360547132742823", size = 425480 }, - { url = "https://files.pythonhosted.org/packages/53/20/20509c8f5291e14e8a13104b1808cd7cf5c44acd5feaecb427a49d387774/watchfiles-0.24.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d7a2e3b7f5703ffbd500dabdefcbc9eafeff4b9444bbdd5d83d79eedf8428fab", size = 612322 }, - { url = "https://files.pythonhosted.org/packages/df/2b/5f65014a8cecc0a120f5587722068a975a692cadbe9fe4ea56b3d8e43f14/watchfiles-0.24.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d831ee0a50946d24a53821819b2327d5751b0c938b12c0653ea5be7dea9c82ec", size = 595094 }, - { url = "https://files.pythonhosted.org/packages/18/98/006d8043a82c0a09d282d669c88e587b3a05cabdd7f4900e402250a249ac/watchfiles-0.24.0-cp311-none-win32.whl", hash = "sha256:49d617df841a63b4445790a254013aea2120357ccacbed00253f9c2b5dc24e2d", size = 264191 }, - { url = "https://files.pythonhosted.org/packages/8a/8b/badd9247d6ec25f5f634a9b3d0d92e39c045824ec7e8afcedca8ee52c1e2/watchfiles-0.24.0-cp311-none-win_amd64.whl", hash = "sha256:d3dcb774e3568477275cc76554b5a565024b8ba3a0322f77c246bc7111c5bb9c", size = 277527 }, - { url = "https://files.pythonhosted.org/packages/af/19/35c957c84ee69d904299a38bae3614f7cede45f07f174f6d5a2f4dbd6033/watchfiles-0.24.0-cp311-none-win_arm64.whl", hash = "sha256:9301c689051a4857d5b10777da23fafb8e8e921bcf3abe6448a058d27fb67633", size = 266253 }, - { url = "https://files.pythonhosted.org/packages/35/82/92a7bb6dc82d183e304a5f84ae5437b59ee72d48cee805a9adda2488b237/watchfiles-0.24.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7211b463695d1e995ca3feb38b69227e46dbd03947172585ecb0588f19b0d87a", size = 374137 }, - { url = "https://files.pythonhosted.org/packages/87/91/49e9a497ddaf4da5e3802d51ed67ff33024597c28f652b8ab1e7c0f5718b/watchfiles-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b8693502d1967b00f2fb82fc1e744df128ba22f530e15b763c8d82baee15370", size = 367733 }, - { url = "https://files.pythonhosted.org/packages/0d/d8/90eb950ab4998effea2df4cf3a705dc594f6bc501c5a353073aa990be965/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdab9555053399318b953a1fe1f586e945bc8d635ce9d05e617fd9fe3a4687d6", size = 437322 }, - { url = "https://files.pythonhosted.org/packages/6c/a2/300b22e7bc2a222dd91fce121cefa7b49aa0d26a627b2777e7bdfcf1110b/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34e19e56d68b0dad5cff62273107cf5d9fbaf9d75c46277aa5d803b3ef8a9e9b", size = 433409 }, - { url = "https://files.pythonhosted.org/packages/99/44/27d7708a43538ed6c26708bcccdde757da8b7efb93f4871d4cc39cffa1cc/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41face41f036fee09eba33a5b53a73e9a43d5cb2c53dad8e61fa6c9f91b5a51e", size = 452142 }, - { url = "https://files.pythonhosted.org/packages/b0/ec/c4e04f755be003129a2c5f3520d2c47026f00da5ecb9ef1e4f9449637571/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5148c2f1ea043db13ce9b0c28456e18ecc8f14f41325aa624314095b6aa2e9ea", size = 469414 }, - { url = "https://files.pythonhosted.org/packages/c5/4e/cdd7de3e7ac6432b0abf282ec4c1a1a2ec62dfe423cf269b86861667752d/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e4bd963a935aaf40b625c2499f3f4f6bbd0c3776f6d3bc7c853d04824ff1c9f", size = 472962 }, - { url = "https://files.pythonhosted.org/packages/27/69/e1da9d34da7fc59db358424f5d89a56aaafe09f6961b64e36457a80a7194/watchfiles-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c79d7719d027b7a42817c5d96461a99b6a49979c143839fc37aa5748c322f234", size = 425705 }, - { url = "https://files.pythonhosted.org/packages/e8/c1/24d0f7357be89be4a43e0a656259676ea3d7a074901f47022f32e2957798/watchfiles-0.24.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:32aa53a9a63b7f01ed32e316e354e81e9da0e6267435c7243bf8ae0f10b428ef", size = 612851 }, - { url = "https://files.pythonhosted.org/packages/c7/af/175ba9b268dec56f821639c9893b506c69fd999fe6a2e2c51de420eb2f01/watchfiles-0.24.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce72dba6a20e39a0c628258b5c308779b8697f7676c254a845715e2a1039b968", size = 594868 }, - { url = "https://files.pythonhosted.org/packages/44/81/1f701323a9f70805bc81c74c990137123344a80ea23ab9504a99492907f8/watchfiles-0.24.0-cp312-none-win32.whl", hash = "sha256:d9018153cf57fc302a2a34cb7564870b859ed9a732d16b41a9b5cb2ebed2d444", size = 264109 }, - { url = "https://files.pythonhosted.org/packages/b4/0b/32cde5bc2ebd9f351be326837c61bdeb05ad652b793f25c91cac0b48a60b/watchfiles-0.24.0-cp312-none-win_amd64.whl", hash = "sha256:551ec3ee2a3ac9cbcf48a4ec76e42c2ef938a7e905a35b42a1267fa4b1645896", size = 277055 }, - { url = "https://files.pythonhosted.org/packages/4b/81/daade76ce33d21dbec7a15afd7479de8db786e5f7b7d249263b4ea174e08/watchfiles-0.24.0-cp312-none-win_arm64.whl", hash = "sha256:b52a65e4ea43c6d149c5f8ddb0bef8d4a1e779b77591a458a893eb416624a418", size = 266169 }, - { url = "https://files.pythonhosted.org/packages/30/dc/6e9f5447ae14f645532468a84323a942996d74d5e817837a5c8ce9d16c69/watchfiles-0.24.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3d2e3ab79a1771c530233cadfd277fcc762656d50836c77abb2e5e72b88e3a48", size = 373764 }, - { url = "https://files.pythonhosted.org/packages/79/c0/c3a9929c372816c7fc87d8149bd722608ea58dc0986d3ef7564c79ad7112/watchfiles-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327763da824817b38ad125dcd97595f942d720d32d879f6c4ddf843e3da3fe90", size = 367873 }, - { url = "https://files.pythonhosted.org/packages/2e/11/ff9a4445a7cfc1c98caf99042df38964af12eed47d496dd5d0d90417349f/watchfiles-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd82010f8ab451dabe36054a1622870166a67cf3fce894f68895db6f74bbdc94", size = 438381 }, - { url = "https://files.pythonhosted.org/packages/48/a3/763ba18c98211d7bb6c0f417b2d7946d346cdc359d585cc28a17b48e964b/watchfiles-0.24.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d64ba08db72e5dfd5c33be1e1e687d5e4fcce09219e8aee893a4862034081d4e", size = 432809 }, - { url = "https://files.pythonhosted.org/packages/30/4c/616c111b9d40eea2547489abaf4ffc84511e86888a166d3a4522c2ba44b5/watchfiles-0.24.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1cf1f6dd7825053f3d98f6d33f6464ebdd9ee95acd74ba2c34e183086900a827", size = 451801 }, - { url = "https://files.pythonhosted.org/packages/b6/be/d7da83307863a422abbfeb12903a76e43200c90ebe5d6afd6a59d158edea/watchfiles-0.24.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43e3e37c15a8b6fe00c1bce2473cfa8eb3484bbeecf3aefbf259227e487a03df", size = 468886 }, - { url = "https://files.pythonhosted.org/packages/1d/d3/3dfe131ee59d5e90b932cf56aba5c996309d94dafe3d02d204364c23461c/watchfiles-0.24.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88bcd4d0fe1d8ff43675360a72def210ebad3f3f72cabfeac08d825d2639b4ab", size = 472973 }, - { url = "https://files.pythonhosted.org/packages/42/6c/279288cc5653a289290d183b60a6d80e05f439d5bfdfaf2d113738d0f932/watchfiles-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:999928c6434372fde16c8f27143d3e97201160b48a614071261701615a2a156f", size = 425282 }, - { url = "https://files.pythonhosted.org/packages/d6/d7/58afe5e85217e845edf26d8780c2d2d2ae77675eeb8d1b8b8121d799ce52/watchfiles-0.24.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:30bbd525c3262fd9f4b1865cb8d88e21161366561cd7c9e1194819e0a33ea86b", size = 612540 }, - { url = "https://files.pythonhosted.org/packages/6d/d5/b96eeb9fe3fda137200dd2f31553670cbc731b1e13164fd69b49870b76ec/watchfiles-0.24.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:edf71b01dec9f766fb285b73930f95f730bb0943500ba0566ae234b5c1618c18", size = 593625 }, - { url = "https://files.pythonhosted.org/packages/c1/e5/c326fe52ee0054107267608d8cea275e80be4455b6079491dfd9da29f46f/watchfiles-0.24.0-cp313-none-win32.whl", hash = "sha256:f4c96283fca3ee09fb044f02156d9570d156698bc3734252175a38f0e8975f07", size = 263899 }, - { url = "https://files.pythonhosted.org/packages/a6/8b/8a7755c5e7221bb35fe4af2dc44db9174f90ebf0344fd5e9b1e8b42d381e/watchfiles-0.24.0-cp313-none-win_amd64.whl", hash = "sha256:a974231b4fdd1bb7f62064a0565a6b107d27d21d9acb50c484d2cdba515b9366", size = 276622 }, - { url = "https://files.pythonhosted.org/packages/93/90/15b3b1cc19799c217e4369ca15dbf9ba1d0f821d61b27173a54800002478/watchfiles-0.24.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b665caeeda58625c3946ad7308fbd88a086ee51ccb706307e5b1fa91556ac886", size = 375920 }, - { url = "https://files.pythonhosted.org/packages/74/e2/ec7766a5b20ba5e37397ef8d32ff39a90daf7e4677410efe077c386338b6/watchfiles-0.24.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c51749f3e4e269231510da426ce4a44beb98db2dce9097225c338f815b05d4f", size = 369382 }, - { url = "https://files.pythonhosted.org/packages/a2/82/915b3a3295292f860181dc9c7d922834ac7265c8915052d396d40ccf4617/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b2509f08761f29a0fdad35f7e1638b8ab1adfa2666d41b794090361fb8b855", size = 438556 }, - { url = "https://files.pythonhosted.org/packages/9b/76/750eab8e7baecedca05e712b9571ac5eb240e494e8d4c78b359da2939619/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a60e2bf9dc6afe7f743e7c9b149d1fdd6dbf35153c78fe3a14ae1a9aee3d98b", size = 433677 }, - { url = "https://files.pythonhosted.org/packages/1a/69/7c55142bafcdad9fec58433b7c1f162b59c48f0a3732a9441252147b13c7/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7d9b87c4c55e3ea8881dfcbf6d61ea6775fffed1fedffaa60bd047d3c08c430", size = 451845 }, - { url = "https://files.pythonhosted.org/packages/d7/a6/124b0043a8936adf96fffa1d73217b205cc254b4a5a313b0a6ea33a44b7b/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78470906a6be5199524641f538bd2c56bb809cd4bf29a566a75051610bc982c3", size = 469931 }, - { url = "https://files.pythonhosted.org/packages/7a/14/29ffa6c7a695fb46a7ff835a5524976dbc07577215647fb35a61ea099c75/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07cdef0c84c03375f4e24642ef8d8178e533596b229d32d2bbd69e5128ede02a", size = 476577 }, - { url = "https://files.pythonhosted.org/packages/9d/8b/fea47dd852c644bd933108877293d0a1c56953c584e8b971530a9042c153/watchfiles-0.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d337193bbf3e45171c8025e291530fb7548a93c45253897cd764a6a71c937ed9", size = 426432 }, - { url = "https://files.pythonhosted.org/packages/0e/11/cfa073f1d9fa18867c2b4220ba445044fd48101ac481f8cbfea1c208ea88/watchfiles-0.24.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ec39698c45b11d9694a1b635a70946a5bad066b593af863460a8e600f0dff1ca", size = 613173 }, - { url = "https://files.pythonhosted.org/packages/77/44/05c8959304f96fbcd68b6c131c59df7bd3d7f0c2a7410324b7f63b1f9fe6/watchfiles-0.24.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e28d91ef48eab0afb939fa446d8ebe77e2f7593f5f463fd2bb2b14132f95b6e", size = 596184 }, - { url = "https://files.pythonhosted.org/packages/9b/85/033ecdb5eccb77770d6f24f9fa055067ffa962313a1383645afc711a3cd8/watchfiles-0.24.0-cp39-none-win32.whl", hash = "sha256:7138eff8baa883aeaa074359daabb8b6c1e73ffe69d5accdc907d62e50b1c0da", size = 264345 }, - { url = "https://files.pythonhosted.org/packages/16/6e/5ded97365346eceaf7fa32d4e2d16f4f97b11d648026b2903c2528c544f8/watchfiles-0.24.0-cp39-none-win_amd64.whl", hash = "sha256:b3ef2c69c655db63deb96b3c3e587084612f9b1fa983df5e0c3379d41307467f", size = 277760 }, - { url = "https://files.pythonhosted.org/packages/df/94/1ad200e937ec91b2a9d6b39ae1cf9c2b1a9cc88d5ceb43aa5c6962eb3c11/watchfiles-0.24.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:632676574429bee8c26be8af52af20e0c718cc7f5f67f3fb658c71928ccd4f7f", size = 376986 }, - { url = "https://files.pythonhosted.org/packages/ee/fd/d9e020d687ccf90fe95efc513fbb39a8049cf5a3ff51f53c59fcf4c47a5d/watchfiles-0.24.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a2a9891723a735d3e2540651184be6fd5b96880c08ffe1a98bae5017e65b544b", size = 369445 }, - { url = "https://files.pythonhosted.org/packages/43/cb/c0279b35053555d10ef03559c5aebfcb0c703d9c70a7b4e532df74b9b0e8/watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7fa2bc0efef3e209a8199fd111b8969fe9db9c711acc46636686331eda7dd4", size = 439383 }, - { url = "https://files.pythonhosted.org/packages/8b/c4/08b3c2cda45db5169148a981c2100c744a4a222fa7ae7644937c0c002069/watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01550ccf1d0aed6ea375ef259706af76ad009ef5b0203a3a4cce0f6024f9b68a", size = 426804 }, - { url = "https://files.pythonhosted.org/packages/02/81/9c9a1e6a83d3c320d2f89eca2b71854ae727eca8ab298ad5da00e36c69e2/watchfiles-0.24.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:96619302d4374de5e2345b2b622dc481257a99431277662c30f606f3e22f42be", size = 377076 }, - { url = "https://files.pythonhosted.org/packages/f1/05/9ef4158f15c417a420d907a6eb887c81953565d0268262195766a844a6d9/watchfiles-0.24.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:85d5f0c7771dcc7a26c7a27145059b6bb0ce06e4e751ed76cdf123d7039b60b5", size = 371717 }, - { url = "https://files.pythonhosted.org/packages/81/1b/8d036da7a9e4d490385b6979804229fb7ac9b591e4d84f159edf2b3f7cc2/watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951088d12d339690a92cef2ec5d3cfd957692834c72ffd570ea76a6790222777", size = 440973 }, - { url = "https://files.pythonhosted.org/packages/fb/fc/885015d4a17ada85508e406c10d638808e7bfbb5622a2e342c868ede18c0/watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fb58bcaa343fedc6a9e91f90195b20ccb3135447dc9e4e2570c3a39565853e", size = 428343 }, +sdist = { url = "https://files.pythonhosted.org/packages/9e/5e/5a9dfb8594b075d7c225d5fb628d498001c5dfae62298e9eb85b8754668f/watchfiles-1.0.0.tar.gz", hash = "sha256:37566c844c9ce3b5deb964fe1a23378e575e74b114618d211fbda8f59d7b5dab", size = 38187 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/3b/c453e0f87b34ad4ef72cb193b2fd6d40c682cb217b06d51c17400fbe8650/watchfiles-1.0.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:1d19df28f99d6a81730658fbeb3ade8565ff687f95acb59665f11502b441be5f", size = 394140 }, + { url = "https://files.pythonhosted.org/packages/6d/0c/f795dce52ca55472aa75fabd12f963ab5bbb860de5d24a5b2eeabeb44613/watchfiles-1.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:28babb38cf2da8e170b706c4b84aa7e4528a6fa4f3ee55d7a0866456a1662041", size = 382832 }, + { url = "https://files.pythonhosted.org/packages/71/ab/e1452f6e4cd0d829ae27ea8af6d3674d734332566fa5ceb870151b49b4f4/watchfiles-1.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12ab123135b2f42517f04e720526d41448667ae8249e651385afb5cda31fedc0", size = 441232 }, + { url = "https://files.pythonhosted.org/packages/37/76/548e9aee70bbe00b728bd33076e764f0c9d9beb8247c63073d9d10295571/watchfiles-1.0.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13a4f9ee0cd25682679eea5c14fc629e2eaa79aab74d963bc4e21f43b8ea1877", size = 447570 }, + { url = "https://files.pythonhosted.org/packages/0d/2c/e8d627f29353e8a10054243801e7bc305bd34789cf2101eadb42a0fdba51/watchfiles-1.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e1d9284cc84de7855fcf83472e51d32daf6f6cecd094160192628bc3fee1b78", size = 472440 }, + { url = "https://files.pythonhosted.org/packages/8b/86/ce94bba556dee4643d4b19f62bace982b08c4d86c7aa345fe9129519772b/watchfiles-1.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ee5edc939f53466b329bbf2e58333a5461e6c7b50c980fa6117439e2c18b42d", size = 492706 }, + { url = "https://files.pythonhosted.org/packages/67/5c/7db33af6d0d7d46618b67dda4f5448cbbc0366d0a5eb115020ab42faa129/watchfiles-1.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dccfc70480087567720e4e36ec381bba1ed68d7e5f368fe40c93b3b1eba0105", size = 489295 }, + { url = "https://files.pythonhosted.org/packages/14/a2/8237e16017c0bab92163381ac8e780b9fe85b4efa71893faf1a18c8a9e35/watchfiles-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83a6d33a9eda0af6a7470240d1af487807adc269704fe76a4972dd982d16236", size = 442559 }, + { url = "https://files.pythonhosted.org/packages/ce/71/8c6ff2f5f985c1e44395936e8f95495d5c42fdd649fbaa6f1ebaa5233d13/watchfiles-1.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:905f69aad276639eff3893759a07d44ea99560e67a1cf46ff389cd62f88872a2", size = 614528 }, + { url = "https://files.pythonhosted.org/packages/f8/be/6b2c73b8de25162e5b665607c847bb1ec98d60b5cccc638d915a870b4621/watchfiles-1.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09551237645d6bff3972592f2aa5424df9290e7a2e15d63c5f47c48cde585935", size = 612848 }, + { url = "https://files.pythonhosted.org/packages/e7/0e/79ad259865fa4be453f18cb006dd14234c293d91d3ff41e3cc7e406bff0a/watchfiles-1.0.0-cp310-none-win32.whl", hash = "sha256:d2b39aa8edd9e5f56f99a2a2740a251dc58515398e9ed5a4b3e5ff2827060755", size = 272040 }, + { url = "https://files.pythonhosted.org/packages/e9/3e/1b8e86a0970a7292f3fdef94acb4468212b81cd7c8ad4f724c5d56cdc02e/watchfiles-1.0.0-cp310-none-win_amd64.whl", hash = "sha256:2de52b499e1ab037f1a87cb8ebcb04a819bf087b1015a4cf6dcf8af3c2a2613e", size = 285356 }, + { url = "https://files.pythonhosted.org/packages/a7/10/10759faea3f011b86867a534a47c9aedca667a4b3806ffeac7d8a4c8adee/watchfiles-1.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:fbd0ab7a9943bbddb87cbc2bf2f09317e74c77dc55b1f5657f81d04666c25269", size = 394139 }, + { url = "https://files.pythonhosted.org/packages/b9/71/b76be784f3e48bb1929e2c1376f227608be9bda4f7ba0c06832f0d190bed/watchfiles-1.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:774ef36b16b7198669ce655d4f75b4c3d370e7f1cbdfb997fb10ee98717e2058", size = 382832 }, + { url = "https://files.pythonhosted.org/packages/d6/88/393b33c6da4963933e810eb0b8d6b44c7ba52ed2aaf6bb7709db377289f8/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b4fb98100267e6a5ebaff6aaa5d20aea20240584647470be39fe4823012ac96", size = 441232 }, + { url = "https://files.pythonhosted.org/packages/35/2c/2d2c131866f7c49ec68c504565d2336f40a595bcd857cd464a68ea0fdb42/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0fc3bf0effa2d8075b70badfdd7fb839d7aa9cea650d17886982840d71fdeabf", size = 447569 }, + { url = "https://files.pythonhosted.org/packages/ab/08/373713cc4859958cdf0a38ad85740010dbbf5617441edc3480d37387024c/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:648e2b6db53eca6ef31245805cd528a16f56fa4cc15aeec97795eaf713c11435", size = 472439 }, + { url = "https://files.pythonhosted.org/packages/2b/df/8e209910e260f58f005974a60423bb6fc243d26e8793103462870502c744/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa13d604fcb9417ae5f2e3de676e66aa97427d888e83662ad205bed35a313176", size = 492707 }, + { url = "https://files.pythonhosted.org/packages/83/4d/d0673571c223a784849f45c4da6de2af960602ba5061a2f033f96606a118/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:936f362e7ff28311b16f0b97ec51e8f2cc451763a3264640c6ed40fb252d1ee4", size = 489294 }, + { url = "https://files.pythonhosted.org/packages/32/ed/0c96c714408c8edab862e816b45be51dbe4e77dc7518c29b0dccc02961a8/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:245fab124b9faf58430da547512d91734858df13f2ddd48ecfa5e493455ffccb", size = 442559 }, + { url = "https://files.pythonhosted.org/packages/3d/2b/665bf9aefd0f22a265f7b93e69aa4dc068d8ac5ad9ecbd974305eaeff2c0/watchfiles-1.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4ff9c7e84e8b644a8f985c42bcc81457240316f900fc72769aaedec9d088055a", size = 614531 }, + { url = "https://files.pythonhosted.org/packages/9f/41/fd125e824a195219adb204b54f3affce5615f5f1b3889acd441f28d2fbd2/watchfiles-1.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c9a8d8fd97defe935ef8dd53d562e68942ad65067cd1c54d6ed8a088b1d931d", size = 612852 }, + { url = "https://files.pythonhosted.org/packages/dc/ac/750bf3625f4d3172ee7acfd952552070a88fd697935cfead79a68eb8d69d/watchfiles-1.0.0-cp311-none-win32.whl", hash = "sha256:a0abf173975eb9dd17bb14c191ee79999e650997cc644562f91df06060610e62", size = 272294 }, + { url = "https://files.pythonhosted.org/packages/bd/04/8c18986b79d106a88f54629f8f901cd725d76227c9a9191ada8ce8c962e8/watchfiles-1.0.0-cp311-none-win_amd64.whl", hash = "sha256:2a825ba4b32c214e3855b536eb1a1f7b006511d8e64b8215aac06eb680642d84", size = 285435 }, + { url = "https://files.pythonhosted.org/packages/b4/38/7e64929e8ca2b2a94cb9d8ddf6be9c06be8be870b6014d0f06e76b72f9cf/watchfiles-1.0.0-cp311-none-win_arm64.whl", hash = "sha256:a5a7a06cfc65e34fd0a765a7623c5ba14707a0870703888e51d3d67107589817", size = 276512 }, + { url = "https://files.pythonhosted.org/packages/37/0a/75491ba001f1495d2a12d7f6b90738f20badac78291ca5d56bf7990c859a/watchfiles-1.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:28fb64b5843d94e2c2483f7b024a1280662a44409bedee8f2f51439767e2d107", size = 394139 }, + { url = "https://files.pythonhosted.org/packages/5a/ee/935095538ff08ab68555de2bbc18acaf91f4cce8518bf32196f1ff9b8326/watchfiles-1.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e3750434c83b61abb3163b49c64b04180b85b4dabb29a294513faec57f2ffdb7", size = 382832 }, + { url = "https://files.pythonhosted.org/packages/74/40/86787dca3ea251aabb3abfbe4beeffe9c7ae6e69de56a25d572aecde580e/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bedf84835069f51c7b026b3ca04e2e747ea8ed0a77c72006172c72d28c9f69fc", size = 441232 }, + { url = "https://files.pythonhosted.org/packages/59/e2/08db1ba48a30462ec7e382c2b1de5400b09a2a7c95fe3f16d3e7da844f0c/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90004553be36427c3d06ec75b804233f8f816374165d5225b93abd94ba6e7234", size = 447569 }, + { url = "https://files.pythonhosted.org/packages/73/54/10adf42f203d876076cf0684726c102b3dba82b1c7eea2d82e5991875f62/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b46e15c34d4e401e976d6949ad3a74d244600d5c4b88c827a3fdf18691a46359", size = 472439 }, + { url = "https://files.pythonhosted.org/packages/29/77/d0d3b5ec6224800cd77f5d058473d0a844d753a3dad9f53f369bc98946bc/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:487d15927f1b0bd24e7df921913399bb1ab94424c386bea8b267754d698f8f0e", size = 492707 }, + { url = "https://files.pythonhosted.org/packages/c8/74/616bd8edfa7b0aaee96e4b3ad7edd0ccf0f4213a06050e965d68e0cdbaef/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ff236d7a3f4b0a42f699a22fc374ba526bc55048a70cbb299661158e1bb5e1f", size = 489293 }, + { url = "https://files.pythonhosted.org/packages/9c/1e/5335eaf5fb9a9516722c7f63f477ca1e361d8159fe46e03d96539cb80f5b/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c01446626574561756067f00b37e6b09c8622b0fc1e9fdbc7cbcea328d4e514", size = 442559 }, + { url = "https://files.pythonhosted.org/packages/c7/1c/df716e9acf7931b52f48bd9b2eec9a26ff55c73b43bfdbc03ea985543d01/watchfiles-1.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b551c465a59596f3d08170bd7e1c532c7260dd90ed8135778038e13c5d48aa81", size = 614531 }, + { url = "https://files.pythonhosted.org/packages/8d/38/c97d572e147234dd5f107179854efbf9ac6470db11db96f690cdb80e9b1b/watchfiles-1.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1ed613ee107269f66c2df631ec0fc8efddacface85314d392a4131abe299f00", size = 612853 }, + { url = "https://files.pythonhosted.org/packages/2d/1d/161eb1caa7e63b60428b2439efb0a87f0db4d5f4b91dd8712b6eca689954/watchfiles-1.0.0-cp312-none-win32.whl", hash = "sha256:5f75cd42e7e2254117cf37ff0e68c5b3f36c14543756b2da621408349bd9ca7c", size = 272337 }, + { url = "https://files.pythonhosted.org/packages/fc/1d/62acefeb546d24971e8f77cf5c475307054da4c21e9c49ec1917b293368b/watchfiles-1.0.0-cp312-none-win_amd64.whl", hash = "sha256:cf517701a4a872417f4e02a136e929537743461f9ec6cdb8184d9a04f4843545", size = 285572 }, + { url = "https://files.pythonhosted.org/packages/41/08/e20f3dbd2db59067596acc9b81345ac68a9c762352d38e789b2516719876/watchfiles-1.0.0-cp312-none-win_arm64.whl", hash = "sha256:8a2127cd68950787ee36753e6d401c8ea368f73beaeb8e54df5516a06d1ecd82", size = 276513 }, + { url = "https://files.pythonhosted.org/packages/c6/14/e14eb2ad369b306be70423fbf6da47bc39333d2beeafb14f23d2f37fdd79/watchfiles-1.0.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:95de85c254f7fe8cbdf104731f7f87f7f73ae229493bebca3722583160e6b152", size = 394141 }, + { url = "https://files.pythonhosted.org/packages/81/c3/738aeb2a01cbdf5fa823f702694ac72879a97fa5873d15d4607a877c7082/watchfiles-1.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:533a7cbfe700e09780bb31c06189e39c65f06c7f447326fee707fd02f9a6e945", size = 382833 }, + { url = "https://files.pythonhosted.org/packages/ed/aa/1cc14d11be667eb7189a2daa0adf307b93d6624fee5b80b8e84c23fb2486/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2218e78e2c6c07b1634a550095ac2a429026b2d5cbcd49a594f893f2bb8c936", size = 441231 }, + { url = "https://files.pythonhosted.org/packages/c5/38/96f4c3485094a164ced67ae444f3e890bdaad17d1b62c894aa8439443d81/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9122b8fdadc5b341315d255ab51d04893f417df4e6c1743b0aac8bf34e96e025", size = 447570 }, + { url = "https://files.pythonhosted.org/packages/9e/ce/0e35e0191517fa1d876ce0b4e23c818cf3a50d825305dcb7471da8774da7/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9272fdbc0e9870dac3b505bce1466d386b4d8d6d2bacf405e603108d50446940", size = 472440 }, + { url = "https://files.pythonhosted.org/packages/2c/b5/eb9c799c6e14f25f26573ac08734225035a8821f7dd9161c69df882fc119/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a3b33c3aefe9067ebd87846806cd5fc0b017ab70d628aaff077ab9abf4d06b3", size = 492706 }, + { url = "https://files.pythonhosted.org/packages/84/fa/985d4cbfe99a56d7277c0e522fd138fe5fc4d8ea6351ee3302e93ed67e63/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc338ce9f8846543d428260fa0f9a716626963148edc937d71055d01d81e1525", size = 489295 }, + { url = "https://files.pythonhosted.org/packages/94/1a/8bc18a170eb621a30fb01f4902d60ce362c88b1f65f3b15d45f53b467200/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ac778a460ea22d63c7e6fb0bc0f5b16780ff0b128f7f06e57aaec63bd339285", size = 442560 }, + { url = "https://files.pythonhosted.org/packages/e9/e0/07ce46f1770ca1d229635efb5393ff593c41762f389532ae9c7b2ced79b0/watchfiles-1.0.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:53ae447f06f8f29f5ab40140f19abdab822387a7c426a369eb42184b021e97eb", size = 614532 }, + { url = "https://files.pythonhosted.org/packages/7b/56/cdd2847d24249e879a001e6aed9ddeeaa24a80aabfdcb9c19389d0837dfe/watchfiles-1.0.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1f73c2147a453315d672c1ad907abe6d40324e34a185b51e15624bc793f93cc6", size = 612852 }, + { url = "https://files.pythonhosted.org/packages/72/c9/89a3df27c97eeef5890591a95f7afd266a32dfe55bce1f3bea3390fa56f5/watchfiles-1.0.0-cp313-none-win32.whl", hash = "sha256:eba98901a2eab909dbd79681190b9049acc650f6111fde1845484a4450761e98", size = 271721 }, + { url = "https://files.pythonhosted.org/packages/ef/e9/6e1bd83a08d254b0394500a2bb691b7940f09fcd849f400d01491932f641/watchfiles-1.0.0-cp313-none-win_amd64.whl", hash = "sha256:d562a6114ddafb09c33246c6ace7effa71ca4b6a2324a47f4b09b6445ea78941", size = 284809 }, + { url = "https://files.pythonhosted.org/packages/59/04/1d54f34e42ffb05dc51a8e6004b75d7433f2b764d7752ed2de8bec65b447/watchfiles-1.0.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3d94fd83ed54266d789f287472269c0def9120a2022674990bd24ad989ebd7a0", size = 394143 }, + { url = "https://files.pythonhosted.org/packages/0d/fd/60c03572a41eb71abd572cd78d1a7d8a697e42215b7662cf477563a05d66/watchfiles-1.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48051d1c504448b2fcda71c5e6e3610ae45de6a0b8f5a43b961f250be4bdf5a8", size = 382828 }, + { url = "https://files.pythonhosted.org/packages/80/eb/f17b1c7e3740d0f10f86c18a22827e8851d1c8afa5ad7f2daf91957fb415/watchfiles-1.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29cf884ad4285d23453c702ed03d689f9c0e865e3c85d20846d800d4787de00f", size = 441233 }, + { url = "https://files.pythonhosted.org/packages/71/de/29dba07c7fe525e9fc6e8c49b8e1f38c3de64e1ca1da5f52453559658499/watchfiles-1.0.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d3572d4c34c4e9c33d25b3da47d9570d5122f8433b9ac6519dca49c2740d23cd", size = 447568 }, + { url = "https://files.pythonhosted.org/packages/55/57/3f6cd10053b64a90d32c5b28330beff65d9cff899166c0fc9c3a392feba5/watchfiles-1.0.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c2696611182c85eb0e755b62b456f48debff484b7306b56f05478b843ca8ece", size = 472435 }, + { url = "https://files.pythonhosted.org/packages/bf/99/1c5e6c6be3667562bbc7ffecc6f2f8b43da14044d576ee90130bc0feff63/watchfiles-1.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:550109001920a993a4383b57229c717fa73627d2a4e8fcb7ed33c7f1cddb0c85", size = 492706 }, + { url = "https://files.pythonhosted.org/packages/ef/65/4cc00fcec20ecc5eae1ca342920fd155e731b89fcddde68a33057f17ff4f/watchfiles-1.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b555a93c15bd2c71081922be746291d776d47521a00703163e5fbe6d2a402399", size = 489293 }, + { url = "https://files.pythonhosted.org/packages/0b/d3/30ecf8f227a66ea206cdcb70e7dccb688bb52d0f0a45c95e9084b472258a/watchfiles-1.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:947ccba18a38b85c366dafeac8df2f6176342d5992ca240a9d62588b214d731f", size = 442557 }, + { url = "https://files.pythonhosted.org/packages/39/af/ee9786eaa3468bf642813d764740613c3872b8399b0cee254c3e0170c1bf/watchfiles-1.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ffd98a299b0a74d1b704ef0ed959efb753e656a4e0425c14e46ae4c3cbdd2919", size = 614525 }, + { url = "https://files.pythonhosted.org/packages/18/d5/0b5abbb497f8ca0b50709ff65b029db0696d297971310f7d085e66b8c4c2/watchfiles-1.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f8c4f3a1210ed099a99e6a710df4ff2f8069411059ffe30fa5f9467ebed1256b", size = 612845 }, + { url = "https://files.pythonhosted.org/packages/18/1c/eb2942cf079b4b1d6a76ecccf6762c98f0b40f90311d99a9e0e01332a2af/watchfiles-1.0.0-cp39-none-win32.whl", hash = "sha256:1e176b6b4119b3f369b2b4e003d53a226295ee862c0962e3afd5a1c15680b4e3", size = 272430 }, + { url = "https://files.pythonhosted.org/packages/b2/a2/0dc79ebd569c18db7341eb49471211b59a0669a25f0458b531b4134a57ae/watchfiles-1.0.0-cp39-none-win_amd64.whl", hash = "sha256:2d9c0518fabf4a3f373b0a94bb9e4ea7a1df18dec45e26a4d182aa8918dee855", size = 285705 }, + { url = "https://files.pythonhosted.org/packages/c7/6a/2abb1c062def34f9521bac3ca68a5a3f82fe10ec99b2c3cfff1d80fe9c4b/watchfiles-1.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f159ac795785cde4899e0afa539f4c723fb5dd336ce5605bc909d34edd00b79b", size = 395369 }, + { url = "https://files.pythonhosted.org/packages/5d/19/ee2fcaa691f59d30537aedb5ae206add0faf869c91843e2b86dc4d4bb783/watchfiles-1.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c3d258d78341d5d54c0c804a5b7faa66cd30ba50b2756a7161db07ce15363b8d", size = 384725 }, + { url = "https://files.pythonhosted.org/packages/68/93/583e52c1143b8e72564ae92d2b51c384245287b4782e039affa75e49487b/watchfiles-1.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bbd0311588c2de7f9ea5cf3922ccacfd0ec0c1922870a2be503cc7df1ca8be7", size = 442645 }, + { url = "https://files.pythonhosted.org/packages/96/3e/1ff270fc153f051a8a2e5840917a48d72028bff83905f6b6a7d431fa0e3d/watchfiles-1.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a13ac46b545a7d0d50f7641eefe47d1597e7d1783a5d89e09d080e6dff44b0", size = 442565 }, + { url = "https://files.pythonhosted.org/packages/05/de/d3acd29e19c661b06bfc0644fabe2697e3cfa12f1568c1a51e196ec54420/watchfiles-1.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2bca898c1dc073912d3db7fa6926cc08be9575add9e84872de2c99c688bac4e", size = 395362 }, + { url = "https://files.pythonhosted.org/packages/d2/f2/35e3b4544f88dbcacbbc0dd7b23a3a08f0673c31644d8ba643a636bf16a4/watchfiles-1.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:06d828fe2adc4ac8a64b875ca908b892a3603d596d43e18f7948f3fef5fc671c", size = 384720 }, + { url = "https://files.pythonhosted.org/packages/37/1f/4b0b566e28dc737fcdc0b72ad80f15257984220cd93a7b46f1724aa6e293/watchfiles-1.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:074c7618cd6c807dc4eaa0982b4a9d3f8051cd0b72793511848fd64630174b17", size = 442640 }, + { url = "https://files.pythonhosted.org/packages/32/93/95fb97482db0affecdf9c6c3d58f7e485cba858217b0fd2d1fb71e9b078c/watchfiles-1.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95dc785bc284552d044e561b8f4fe26d01ab5ca40d35852a6572d542adfeb4bc", size = 444154 }, ] [[package]] name = "websockets" -version = "13.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e2/73/9223dbc7be3dcaf2a7bbf756c351ec8da04b1fa573edaf545b95f6b0c7fd/websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878", size = 158549 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/94/d15dbfc6a5eb636dbc754303fba18208f2e88cf97e733e1d64fb9cb5c89e/websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee", size = 157815 }, - { url = "https://files.pythonhosted.org/packages/30/02/c04af33f4663945a26f5e8cf561eb140c35452b50af47a83c3fbcfe62ae1/websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7", size = 155466 }, - { url = "https://files.pythonhosted.org/packages/35/e8/719f08d12303ea643655e52d9e9851b2dadbb1991d4926d9ce8862efa2f5/websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6", size = 155716 }, - { url = "https://files.pythonhosted.org/packages/91/e1/14963ae0252a8925f7434065d25dcd4701d5e281a0b4b460a3b5963d2594/websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b", size = 164806 }, - { url = "https://files.pythonhosted.org/packages/ec/fa/ab28441bae5e682a0f7ddf3d03440c0c352f930da419301f4a717f675ef3/websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa", size = 163810 }, - { url = "https://files.pythonhosted.org/packages/44/77/dea187bd9d16d4b91566a2832be31f99a40d0f5bfa55eeb638eb2c3bc33d/websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700", size = 164125 }, - { url = "https://files.pythonhosted.org/packages/cf/d9/3af14544e83f1437eb684b399e6ba0fa769438e869bf5d83d74bc197fae8/websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c", size = 164532 }, - { url = "https://files.pythonhosted.org/packages/1c/8a/6d332eabe7d59dfefe4b8ba6f46c8c5fabb15b71c8a8bc3d2b65de19a7b6/websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0", size = 163948 }, - { url = "https://files.pythonhosted.org/packages/1a/91/a0aeadbaf3017467a1ee03f8fb67accdae233fe2d5ad4b038c0a84e357b0/websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f", size = 163898 }, - { url = "https://files.pythonhosted.org/packages/71/31/a90fb47c63e0ae605be914b0b969d7c6e6ffe2038cd744798e4b3fbce53b/websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe", size = 158706 }, - { url = "https://files.pythonhosted.org/packages/93/ca/9540a9ba80da04dc7f36d790c30cae4252589dbd52ccdc92e75b0be22437/websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a", size = 159141 }, - { url = "https://files.pythonhosted.org/packages/b2/f0/cf0b8a30d86b49e267ac84addbebbc7a48a6e7bb7c19db80f62411452311/websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19", size = 157813 }, - { url = "https://files.pythonhosted.org/packages/bf/e7/22285852502e33071a8cf0ac814f8988480ec6db4754e067b8b9d0e92498/websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5", size = 155469 }, - { url = "https://files.pythonhosted.org/packages/68/d4/c8c7c1e5b40ee03c5cc235955b0fb1ec90e7e37685a5f69229ad4708dcde/websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd", size = 155717 }, - { url = "https://files.pythonhosted.org/packages/c9/e4/c50999b9b848b1332b07c7fd8886179ac395cb766fda62725d1539e7bc6c/websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02", size = 165379 }, - { url = "https://files.pythonhosted.org/packages/bc/49/4a4ad8c072f18fd79ab127650e47b160571aacfc30b110ee305ba25fffc9/websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7", size = 164376 }, - { url = "https://files.pythonhosted.org/packages/af/9b/8c06d425a1d5a74fd764dd793edd02be18cf6fc3b1ccd1f29244ba132dc0/websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096", size = 164753 }, - { url = "https://files.pythonhosted.org/packages/d5/5b/0acb5815095ff800b579ffc38b13ab1b915b317915023748812d24e0c1ac/websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084", size = 165051 }, - { url = "https://files.pythonhosted.org/packages/30/93/c3891c20114eacb1af09dedfcc620c65c397f4fd80a7009cd12d9457f7f5/websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3", size = 164489 }, - { url = "https://files.pythonhosted.org/packages/28/09/af9e19885539759efa2e2cd29b8b3f9eecef7ecefea40d46612f12138b36/websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9", size = 164438 }, - { url = "https://files.pythonhosted.org/packages/b6/08/6f38b8e625b3d93de731f1d248cc1493327f16cb45b9645b3e791782cff0/websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f", size = 158710 }, - { url = "https://files.pythonhosted.org/packages/fb/39/ec8832ecb9bb04a8d318149005ed8cee0ba4e0205835da99e0aa497a091f/websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557", size = 159137 }, - { url = "https://files.pythonhosted.org/packages/df/46/c426282f543b3c0296cf964aa5a7bb17e984f58dde23460c3d39b3148fcf/websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc", size = 157821 }, - { url = "https://files.pythonhosted.org/packages/aa/85/22529867010baac258da7c45848f9415e6cf37fef00a43856627806ffd04/websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49", size = 155480 }, - { url = "https://files.pythonhosted.org/packages/29/2c/bdb339bfbde0119a6e84af43ebf6275278698a2241c2719afc0d8b0bdbf2/websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd", size = 155715 }, - { url = "https://files.pythonhosted.org/packages/9f/d0/8612029ea04c5c22bf7af2fd3d63876c4eaeef9b97e86c11972a43aa0e6c/websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0", size = 165647 }, - { url = "https://files.pythonhosted.org/packages/56/04/1681ed516fa19ca9083f26d3f3a302257e0911ba75009533ed60fbb7b8d1/websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6", size = 164592 }, - { url = "https://files.pythonhosted.org/packages/38/6f/a96417a49c0ed132bb6087e8e39a37db851c70974f5c724a4b2a70066996/websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9", size = 165012 }, - { url = "https://files.pythonhosted.org/packages/40/8b/fccf294919a1b37d190e86042e1a907b8f66cff2b61e9befdbce03783e25/websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68", size = 165311 }, - { url = "https://files.pythonhosted.org/packages/c1/61/f8615cf7ce5fe538476ab6b4defff52beb7262ff8a73d5ef386322d9761d/websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14", size = 164692 }, - { url = "https://files.pythonhosted.org/packages/5c/f1/a29dd6046d3a722d26f182b783a7997d25298873a14028c4760347974ea3/websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf", size = 164686 }, - { url = "https://files.pythonhosted.org/packages/0f/99/ab1cdb282f7e595391226f03f9b498f52109d25a2ba03832e21614967dfa/websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c", size = 158712 }, - { url = "https://files.pythonhosted.org/packages/46/93/e19160db48b5581feac8468330aa11b7292880a94a37d7030478596cc14e/websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3", size = 159145 }, - { url = "https://files.pythonhosted.org/packages/51/20/2b99ca918e1cbd33c53db2cace5f0c0cd8296fc77558e1908799c712e1cd/websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6", size = 157828 }, - { url = "https://files.pythonhosted.org/packages/b8/47/0932a71d3d9c0e9483174f60713c84cee58d62839a143f21a2bcdbd2d205/websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708", size = 155487 }, - { url = "https://files.pythonhosted.org/packages/a9/60/f1711eb59ac7a6c5e98e5637fef5302f45b6f76a2c9d64fd83bbb341377a/websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418", size = 155721 }, - { url = "https://files.pythonhosted.org/packages/6a/e6/ba9a8db7f9d9b0e5f829cf626ff32677f39824968317223605a6b419d445/websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a", size = 165609 }, - { url = "https://files.pythonhosted.org/packages/c1/22/4ec80f1b9c27a0aebd84ccd857252eda8418ab9681eb571b37ca4c5e1305/websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f", size = 164556 }, - { url = "https://files.pythonhosted.org/packages/27/ac/35f423cb6bb15600438db80755609d27eda36d4c0b3c9d745ea12766c45e/websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5", size = 164993 }, - { url = "https://files.pythonhosted.org/packages/31/4e/98db4fd267f8be9e52e86b6ee4e9aa7c42b83452ea0ea0672f176224b977/websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135", size = 165360 }, - { url = "https://files.pythonhosted.org/packages/3f/15/3f0de7cda70ffc94b7e7024544072bc5b26e2c1eb36545291abb755d8cdb/websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2", size = 164745 }, - { url = "https://files.pythonhosted.org/packages/a1/6e/66b6b756aebbd680b934c8bdbb6dcb9ce45aad72cde5f8a7208dbb00dd36/websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6", size = 164732 }, - { url = "https://files.pythonhosted.org/packages/35/c6/12e3aab52c11aeb289e3dbbc05929e7a9d90d7a9173958477d3ef4f8ce2d/websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d", size = 158709 }, - { url = "https://files.pythonhosted.org/packages/41/d8/63d6194aae711d7263df4498200c690a9c39fb437ede10f3e157a6343e0d/websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2", size = 159144 }, - { url = "https://files.pythonhosted.org/packages/61/26/5f7a7fb03efedb4f90ed61968338bfe7c389863b0ceda239b94ae61c5ae4/websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d", size = 157810 }, - { url = "https://files.pythonhosted.org/packages/0e/d4/9b4814a07dffaa7a79d71b4944d10836f9adbd527a113f6675734ef3abed/websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7", size = 155467 }, - { url = "https://files.pythonhosted.org/packages/1a/1a/2abdc7ce3b56429ae39d6bfb48d8c791f5a26bbcb6f44aabcf71ffc3fda2/websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a", size = 155714 }, - { url = "https://files.pythonhosted.org/packages/2a/98/189d7cf232753a719b2726ec55e7922522632248d5d830adf078e3f612be/websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa", size = 164587 }, - { url = "https://files.pythonhosted.org/packages/a5/2b/fb77cedf3f9f55ef8605238c801eef6b9a5269b01a396875a86896aea3a6/websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa", size = 163588 }, - { url = "https://files.pythonhosted.org/packages/a3/b7/070481b83d2d5ac0f19233d9f364294e224e6478b0762f07fa7f060e0619/websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79", size = 163894 }, - { url = "https://files.pythonhosted.org/packages/eb/be/d6e1cff7d441cfe5eafaacc5935463e5f14c8b1c0d39cb8afde82709b55a/websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17", size = 164315 }, - { url = "https://files.pythonhosted.org/packages/8b/5e/ffa234473e46ab2d3f9fd9858163d5db3ecea1439e4cb52966d78906424b/websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6", size = 163714 }, - { url = "https://files.pythonhosted.org/packages/cc/92/cea9eb9d381ca57065a5eb4ec2ce7a291bd96c85ce742915c3c9ffc1069f/websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5", size = 163673 }, - { url = "https://files.pythonhosted.org/packages/a4/f1/279104fff239bfd04c12b1e58afea227d72fd1acf431e3eed3f6ac2c96d2/websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c", size = 158702 }, - { url = "https://files.pythonhosted.org/packages/25/0b/b87370ff141375c41f7dd67941728e4b3682ebb45882591516c792a2ebee/websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d", size = 159146 }, - { url = "https://files.pythonhosted.org/packages/2d/75/6da22cb3ad5b8c606963f9a5f9f88656256fecc29d420b4b2bf9e0c7d56f/websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238", size = 155499 }, - { url = "https://files.pythonhosted.org/packages/c0/ba/22833d58629088fcb2ccccedfae725ac0bbcd713319629e97125b52ac681/websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5", size = 155737 }, - { url = "https://files.pythonhosted.org/packages/95/54/61684fe22bdb831e9e1843d972adadf359cf04ab8613285282baea6a24bb/websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9", size = 157095 }, - { url = "https://files.pythonhosted.org/packages/fc/f5/6652fb82440813822022a9301a30afde85e5ff3fb2aebb77f34aabe2b4e8/websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6", size = 156701 }, - { url = "https://files.pythonhosted.org/packages/67/33/ae82a7b860fa8a08aba68818bdf7ff61f04598aa5ab96df4cd5a3e418ca4/websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a", size = 156654 }, - { url = "https://files.pythonhosted.org/packages/63/0b/a1b528d36934f833e20f6da1032b995bf093d55cb416b9f2266f229fb237/websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23", size = 159192 }, - { url = "https://files.pythonhosted.org/packages/59/fd/e4bf9a7159dba6a16c59ae9e670e3e8ad9dcb6791bc0599eb86de32d50a9/websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e", size = 155499 }, - { url = "https://files.pythonhosted.org/packages/74/42/d48ede93cfe0c343f3b552af08efc60778d234989227b16882eed1b8b189/websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09", size = 155731 }, - { url = "https://files.pythonhosted.org/packages/f6/f2/2ef6bff1c90a43b80622a17c0852b48c09d3954ab169266ad7b15e17cdcb/websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842", size = 157093 }, - { url = "https://files.pythonhosted.org/packages/d1/14/6f20bbaeeb350f155edf599aad949c554216f90e5d4ae7373d1f2e5931fb/websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb", size = 156701 }, - { url = "https://files.pythonhosted.org/packages/c7/86/38279dfefecd035e22b79c38722d4f87c4b6196f1556b7a631d0a3095ca7/websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20", size = 156649 }, - { url = "https://files.pythonhosted.org/packages/f6/c5/12c6859a2eaa8c53f59a647617a27f1835a226cd7106c601067c53251d98/websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678", size = 159187 }, - { url = "https://files.pythonhosted.org/packages/56/27/96a5cd2626d11c8280656c6c71d8ab50fe006490ef9971ccd154e0c42cd2/websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f", size = 152134 }, +version = "14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/1b/380b883ce05bb5f45a905b61790319a28958a9ab1e4b6b95ff5464b60ca1/websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8", size = 162840 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/91/b1b375dbd856fd5fff3f117de0e520542343ecaf4e8fc60f1ac1e9f5822c/websockets-14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a0adf84bc2e7c86e8a202537b4fd50e6f7f0e4a6b6bf64d7ccb96c4cd3330b29", size = 161950 }, + { url = "https://files.pythonhosted.org/packages/61/8f/4d52f272d3ebcd35e1325c646e98936099a348374d4a6b83b524bded8116/websockets-14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90b5d9dfbb6d07a84ed3e696012610b6da074d97453bd01e0e30744b472c8179", size = 159601 }, + { url = "https://files.pythonhosted.org/packages/c4/b1/29e87b53eb1937992cdee094a0988aadc94f25cf0b37e90c75eed7123d75/websockets-14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2177ee3901075167f01c5e335a6685e71b162a54a89a56001f1c3e9e3d2ad250", size = 159854 }, + { url = "https://files.pythonhosted.org/packages/3f/e6/752a2f5e8321ae2a613062676c08ff2fccfb37dc837a2ee919178a372e8a/websockets-14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f14a96a0034a27f9d47fd9788913924c89612225878f8078bb9d55f859272b0", size = 168835 }, + { url = "https://files.pythonhosted.org/packages/60/27/ca62de7877596926321b99071639275e94bb2401397130b7cf33dbf2106a/websockets-14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f874ba705deea77bcf64a9da42c1f5fc2466d8f14daf410bc7d4ceae0a9fcb0", size = 167844 }, + { url = "https://files.pythonhosted.org/packages/7e/db/f556a1d06635c680ef376be626c632e3f2bbdb1a0189d1d1bffb061c3b70/websockets-14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9607b9a442392e690a57909c362811184ea429585a71061cd5d3c2b98065c199", size = 168157 }, + { url = "https://files.pythonhosted.org/packages/b3/bc/99e5f511838c365ac6ecae19674eb5e94201aa4235bd1af3e6fa92c12905/websockets-14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bea45f19b7ca000380fbd4e02552be86343080120d074b87f25593ce1700ad58", size = 168561 }, + { url = "https://files.pythonhosted.org/packages/c6/e7/251491585bad61c79e525ac60927d96e4e17b18447cc9c3cfab47b2eb1b8/websockets-14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:219c8187b3ceeadbf2afcf0f25a4918d02da7b944d703b97d12fb01510869078", size = 167979 }, + { url = "https://files.pythonhosted.org/packages/ac/98/7ac2e4eeada19bdbc7a3a66a58e3ebdf33648b9e1c5b3f08c3224df168cf/websockets-14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad2ab2547761d79926effe63de21479dfaf29834c50f98c4bf5b5480b5838434", size = 167925 }, + { url = "https://files.pythonhosted.org/packages/ab/3d/09e65c47ee2396b7482968068f6e9b516221e1032b12dcf843b9412a5dfb/websockets-14.1-cp310-cp310-win32.whl", hash = "sha256:1288369a6a84e81b90da5dbed48610cd7e5d60af62df9851ed1d1d23a9069f10", size = 162831 }, + { url = "https://files.pythonhosted.org/packages/8a/67/59828a3d09740e6a485acccfbb66600632f2178b6ed1b61388ee96f17d5a/websockets-14.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0744623852f1497d825a49a99bfbec9bea4f3f946df6eb9d8a2f0c37a2fec2e", size = 163266 }, + { url = "https://files.pythonhosted.org/packages/97/ed/c0d03cb607b7fe1f7ff45e2cd4bb5cd0f9e3299ced79c2c303a6fff44524/websockets-14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512", size = 161949 }, + { url = "https://files.pythonhosted.org/packages/06/91/bf0a44e238660d37a2dda1b4896235d20c29a2d0450f3a46cd688f43b239/websockets-14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac", size = 159606 }, + { url = "https://files.pythonhosted.org/packages/ff/b8/7185212adad274c2b42b6a24e1ee6b916b7809ed611cbebc33b227e5c215/websockets-14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280", size = 159854 }, + { url = "https://files.pythonhosted.org/packages/5a/8a/0849968d83474be89c183d8ae8dcb7f7ada1a3c24f4d2a0d7333c231a2c3/websockets-14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1", size = 169402 }, + { url = "https://files.pythonhosted.org/packages/bd/4f/ef886e37245ff6b4a736a09b8468dae05d5d5c99de1357f840d54c6f297d/websockets-14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3", size = 168406 }, + { url = "https://files.pythonhosted.org/packages/11/43/e2dbd4401a63e409cebddedc1b63b9834de42f51b3c84db885469e9bdcef/websockets-14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cf0ad281c979306a6a34242b371e90e891bce504509fb6bb5246bbbf31e7b6", size = 168776 }, + { url = "https://files.pythonhosted.org/packages/6d/d6/7063e3f5c1b612e9f70faae20ebaeb2e684ffa36cb959eb0862ee2809b32/websockets-14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0", size = 169083 }, + { url = "https://files.pythonhosted.org/packages/49/69/e6f3d953f2fa0f8a723cf18cd011d52733bd7f6e045122b24e0e7f49f9b0/websockets-14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89", size = 168529 }, + { url = "https://files.pythonhosted.org/packages/70/ff/f31fa14561fc1d7b8663b0ed719996cf1f581abee32c8fb2f295a472f268/websockets-14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23", size = 168475 }, + { url = "https://files.pythonhosted.org/packages/f1/15/b72be0e4bf32ff373aa5baef46a4c7521b8ea93ad8b49ca8c6e8e764c083/websockets-14.1-cp311-cp311-win32.whl", hash = "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e", size = 162833 }, + { url = "https://files.pythonhosted.org/packages/bc/ef/2d81679acbe7057ffe2308d422f744497b52009ea8bab34b6d74a2657d1d/websockets-14.1-cp311-cp311-win_amd64.whl", hash = "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09", size = 163263 }, + { url = "https://files.pythonhosted.org/packages/55/64/55698544ce29e877c9188f1aee9093712411a8fc9732cca14985e49a8e9c/websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed", size = 161957 }, + { url = "https://files.pythonhosted.org/packages/a2/b1/b088f67c2b365f2c86c7b48edb8848ac27e508caf910a9d9d831b2f343cb/websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d", size = 159620 }, + { url = "https://files.pythonhosted.org/packages/c1/89/2a09db1bbb40ba967a1b8225b07b7df89fea44f06de9365f17f684d0f7e6/websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707", size = 159852 }, + { url = "https://files.pythonhosted.org/packages/ca/c1/f983138cd56e7d3079f1966e81f77ce6643f230cd309f73aa156bb181749/websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a", size = 169675 }, + { url = "https://files.pythonhosted.org/packages/c1/c8/84191455d8660e2a0bdb33878d4ee5dfa4a2cedbcdc88bbd097303b65bfa/websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45", size = 168619 }, + { url = "https://files.pythonhosted.org/packages/8d/a7/62e551fdcd7d44ea74a006dc193aba370505278ad76efd938664531ce9d6/websockets-14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58", size = 169042 }, + { url = "https://files.pythonhosted.org/packages/ad/ed/1532786f55922c1e9c4d329608e36a15fdab186def3ca9eb10d7465bc1cc/websockets-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058", size = 169345 }, + { url = "https://files.pythonhosted.org/packages/ea/fb/160f66960d495df3de63d9bcff78e1b42545b2a123cc611950ffe6468016/websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4", size = 168725 }, + { url = "https://files.pythonhosted.org/packages/cf/53/1bf0c06618b5ac35f1d7906444b9958f8485682ab0ea40dee7b17a32da1e/websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05", size = 168712 }, + { url = "https://files.pythonhosted.org/packages/e5/22/5ec2f39fff75f44aa626f86fa7f20594524a447d9c3be94d8482cd5572ef/websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0", size = 162838 }, + { url = "https://files.pythonhosted.org/packages/74/27/28f07df09f2983178db7bf6c9cccc847205d2b92ced986cd79565d68af4f/websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f", size = 163277 }, + { url = "https://files.pythonhosted.org/packages/34/77/812b3ba5110ed8726eddf9257ab55ce9e85d97d4aa016805fdbecc5e5d48/websockets-14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9", size = 161966 }, + { url = "https://files.pythonhosted.org/packages/8d/24/4fcb7aa6986ae7d9f6d083d9d53d580af1483c5ec24bdec0978307a0f6ac/websockets-14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b", size = 159625 }, + { url = "https://files.pythonhosted.org/packages/f8/47/2a0a3a2fc4965ff5b9ce9324d63220156bd8bedf7f90824ab92a822e65fd/websockets-14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3", size = 159857 }, + { url = "https://files.pythonhosted.org/packages/dd/c8/d7b425011a15e35e17757e4df75b25e1d0df64c0c315a44550454eaf88fc/websockets-14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59", size = 169635 }, + { url = "https://files.pythonhosted.org/packages/93/39/6e3b5cffa11036c40bd2f13aba2e8e691ab2e01595532c46437b56575678/websockets-14.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2", size = 168578 }, + { url = "https://files.pythonhosted.org/packages/cf/03/8faa5c9576299b2adf34dcccf278fc6bbbcda8a3efcc4d817369026be421/websockets-14.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da", size = 169018 }, + { url = "https://files.pythonhosted.org/packages/8c/05/ea1fec05cc3a60defcdf0bb9f760c3c6bd2dd2710eff7ac7f891864a22ba/websockets-14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9", size = 169383 }, + { url = "https://files.pythonhosted.org/packages/21/1d/eac1d9ed787f80754e51228e78855f879ede1172c8b6185aca8cef494911/websockets-14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7", size = 168773 }, + { url = "https://files.pythonhosted.org/packages/0e/1b/e808685530185915299740d82b3a4af3f2b44e56ccf4389397c7a5d95d39/websockets-14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a", size = 168757 }, + { url = "https://files.pythonhosted.org/packages/b6/19/6ab716d02a3b068fbbeb6face8a7423156e12c446975312f1c7c0f4badab/websockets-14.1-cp313-cp313-win32.whl", hash = "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6", size = 162834 }, + { url = "https://files.pythonhosted.org/packages/6c/fd/ab6b7676ba712f2fc89d1347a4b5bdc6aa130de10404071f2b2606450209/websockets-14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0", size = 163277 }, + { url = "https://files.pythonhosted.org/packages/4d/23/ac9d8c5ec7b90efc3687d60474ef7e698f8b75cb7c9dfedad72701e797c9/websockets-14.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:01bb2d4f0a6d04538d3c5dfd27c0643269656c28045a53439cbf1c004f90897a", size = 161945 }, + { url = "https://files.pythonhosted.org/packages/c5/6b/ffa450e3b736a86ae6b40ce20a758ac9af80c96a18548f6c323ed60329c5/websockets-14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:414ffe86f4d6f434a8c3b7913655a1a5383b617f9bf38720e7c0799fac3ab1c6", size = 159600 }, + { url = "https://files.pythonhosted.org/packages/74/62/f90d1fd57ea7337ecaa99f17c31a544b9dcdb7c7c32a3d3997ccc42d57d3/websockets-14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fda642151d5affdee8a430bd85496f2e2517be3a2b9d2484d633d5712b15c56", size = 159850 }, + { url = "https://files.pythonhosted.org/packages/35/dd/1e71865de1f3c265e11d02b0b4c76178f84351c6611e515fbe3d2bd1b98c/websockets-14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd7c11968bc3860d5c78577f0dbc535257ccec41750675d58d8dc66aa47fe52c", size = 168616 }, + { url = "https://files.pythonhosted.org/packages/ba/ae/0d069b52e26d48402dbe90c7581eb6a5bed5d7dbe3d9ca3cf1033859d58e/websockets-14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a032855dc7db987dff813583d04f4950d14326665d7e714d584560b140ae6b8b", size = 167619 }, + { url = "https://files.pythonhosted.org/packages/1c/3f/d3f2df62704c53e0296f0ce714921b6a15df10e2e463734c737b1d9e2522/websockets-14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7e7ea2f782408c32d86b87a0d2c1fd8871b0399dd762364c731d86c86069a78", size = 167921 }, + { url = "https://files.pythonhosted.org/packages/e0/e2/2dcb295bdae9393070cea58c790d87d1d36149bb4319b1da6014c8a36d42/websockets-14.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:39450e6215f7d9f6f7bc2a6da21d79374729f5d052333da4d5825af8a97e6735", size = 168343 }, + { url = "https://files.pythonhosted.org/packages/6b/fd/fa48e8b4e10e2c165cbfc16dada7405b4008818be490fc6b99a4928e232a/websockets-14.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ceada5be22fa5a5a4cdeec74e761c2ee7db287208f54c718f2df4b7e200b8d4a", size = 167745 }, + { url = "https://files.pythonhosted.org/packages/42/45/79db33f2b744d2014b40946428e6c37ce944fde8791d82e1c2f4d4a67d96/websockets-14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3fc753451d471cff90b8f467a1fc0ae64031cf2d81b7b34e1811b7e2691bc4bc", size = 167705 }, + { url = "https://files.pythonhosted.org/packages/da/27/f66507db34ca9c79562f28fa5983433f7b9080fd471cc188906006d36ba4/websockets-14.1-cp39-cp39-win32.whl", hash = "sha256:14839f54786987ccd9d03ed7f334baec0f02272e7ec4f6e9d427ff584aeea8b4", size = 162828 }, + { url = "https://files.pythonhosted.org/packages/11/25/bb8f81a4ec94f595adb845608c5ec9549cb6b446945b292fe61807c7c95b/websockets-14.1-cp39-cp39-win_amd64.whl", hash = "sha256:d9fd19ecc3a4d5ae82ddbfb30962cf6d874ff943e56e0c81f5169be2fda62979", size = 163271 }, + { url = "https://files.pythonhosted.org/packages/fb/cd/382a05a1ba2a93bd9fb807716a660751295df72e77204fb130a102fcdd36/websockets-14.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e5dc25a9dbd1a7f61eca4b7cb04e74ae4b963d658f9e4f9aad9cd00b688692c8", size = 159633 }, + { url = "https://files.pythonhosted.org/packages/b7/a0/fa7c62e2952ef028b422fbf420f9353d9dd4dfaa425de3deae36e98c0784/websockets-14.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:04a97aca96ca2acedf0d1f332c861c5a4486fdcba7bcef35873820f940c4231e", size = 159867 }, + { url = "https://files.pythonhosted.org/packages/c1/94/954b4924f868db31d5f0935893c7a8446515ee4b36bb8ad75a929469e453/websockets-14.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df174ece723b228d3e8734a6f2a6febbd413ddec39b3dc592f5a4aa0aff28098", size = 161121 }, + { url = "https://files.pythonhosted.org/packages/7a/2e/f12bbb41a8f2abb76428ba4fdcd9e67b5b364a3e7fa97c88f4d6950aa2d4/websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:034feb9f4286476f273b9a245fb15f02c34d9586a5bc936aff108c3ba1b21beb", size = 160731 }, + { url = "https://files.pythonhosted.org/packages/13/97/b76979401f2373af1fe3e08f960b265cecab112e7dac803446fb98351a52/websockets-14.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c308dabd2b380807ab64b62985eaccf923a78ebc572bd485375b9ca2b7dc7", size = 160681 }, + { url = "https://files.pythonhosted.org/packages/39/9c/16916d9a436c109a1d7ba78817e8fee357b78968be3f6e6f517f43afa43d/websockets-14.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a42d3ecbb2db5080fc578314439b1d79eef71d323dc661aa616fb492436af5d", size = 163316 }, + { url = "https://files.pythonhosted.org/packages/0f/57/50fd09848a80a1b63a572c610f230f8a17590ca47daf256eb28a0851df73/websockets-14.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ddaa4a390af911da6f680be8be4ff5aaf31c4c834c1a9147bc21cbcbca2d4370", size = 159633 }, + { url = "https://files.pythonhosted.org/packages/d7/2f/db728b0c7962ad6a13ced8286325bf430b59722d943e7f6bdbd8a78e2bfe/websockets-14.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a4c805c6034206143fbabd2d259ec5e757f8b29d0a2f0bf3d2fe5d1f60147a4a", size = 159863 }, + { url = "https://files.pythonhosted.org/packages/fa/e4/21e7481936fbfffee138edb488a6184eb3468b402a8181b95b9e44f6a676/websockets-14.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:205f672a6c2c671a86d33f6d47c9b35781a998728d2c7c2a3e1cf3333fcb62b7", size = 161119 }, + { url = "https://files.pythonhosted.org/packages/64/2d/efb6cf716d4f9da60190756e06f8db2066faf1ae4a4a8657ab136dfcc7a8/websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef440054124728cc49b01c33469de06755e5a7a4e83ef61934ad95fc327fbb0", size = 160724 }, + { url = "https://files.pythonhosted.org/packages/40/b0/a70b972d853c3f26040834fcff3dd45c8a0292af9f5f0b36f9fbb82d5d44/websockets-14.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7591d6f440af7f73c4bd9404f3772bfee064e639d2b6cc8c94076e71b2471c1", size = 160676 }, + { url = "https://files.pythonhosted.org/packages/4a/76/f9da7f97476cc7b8c74829bb4851f1faf660455839689ffcc354b52860a7/websockets-14.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:25225cc79cfebc95ba1d24cd3ab86aaa35bcd315d12fa4358939bd55e9bd74a5", size = 163311 }, + { url = "https://files.pythonhosted.org/packages/b0/0b/c7e5d11020242984d9d37990310520ed663b942333b83a033c2f20191113/websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e", size = 156277 }, ] [[package]] name = "zipp" -version = "3.15.0" +version = "3.21.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/00/27/f0ac6b846684cecce1ee93d32450c45ab607f65c2e0255f0092032d91f07/zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", size = 18454 } +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5b/fa/c9e82bbe1af6266adf08afb563905eb87cab83fde00a0a08963510621047/zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556", size = 6758 }, + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, ] From 37f9d2d6d2fc5a599870f305a4e9c92d2a82d406 Mon Sep 17 00:00:00 2001 From: Fernando Macedo Date: Thu, 5 Dec 2024 13:53:54 -0300 Subject: [PATCH 16/45] refac: Split the SCXML parser into schema definition, parser and actions for executable content --- .github/workflows/python-package.yml | 2 +- .github/workflows/release.yml | 2 +- .pre-commit-config.yaml | 2 +- pyproject.toml | 5 + statemachine/io/__init__.py | 22 +- statemachine/io/scxml.py | 709 ------------------ statemachine/io/scxml/__init__.py | 0 statemachine/io/scxml/actions.py | 432 +++++++++++ statemachine/io/scxml/parser.py | 293 ++++++++ statemachine/io/scxml/processor.py | 122 +++ statemachine/io/scxml/schema.py | 127 ++++ statemachine/spec_parser.py | 25 +- tests/examples/user_machine.py | 2 +- tests/scxml/conftest.py | 2 +- ...{test187-fail-fail.scxml => test187.scxml} | 0 .../{test237-fail.scxml => test237.scxml} | 0 .../{test242-fail.scxml => test242.scxml} | 0 .../{test252-fail.scxml => test252.scxml} | 0 .../{test377-fail.scxml => test377.scxml} | 0 .../{test378-fail.scxml => test378.scxml} | 0 .../{test407-fail.scxml => test407.scxml} | 0 .../{test409-fail.scxml => test409.scxml} | 0 .../{test554-fail.scxml => test554.scxml} | 0 tests/test_spec_parser.py | 9 +- uv.lock | 24 + 25 files changed, 1027 insertions(+), 751 deletions(-) delete mode 100644 statemachine/io/scxml.py create mode 100644 statemachine/io/scxml/__init__.py create mode 100644 statemachine/io/scxml/actions.py create mode 100644 statemachine/io/scxml/parser.py create mode 100644 statemachine/io/scxml/processor.py create mode 100644 statemachine/io/scxml/schema.py rename tests/scxml/w3c/mandatory/{test187-fail-fail.scxml => test187.scxml} (100%) rename tests/scxml/w3c/mandatory/{test237-fail.scxml => test237.scxml} (100%) rename tests/scxml/w3c/mandatory/{test242-fail.scxml => test242.scxml} (100%) rename tests/scxml/w3c/mandatory/{test252-fail.scxml => test252.scxml} (100%) rename tests/scxml/w3c/mandatory/{test377-fail.scxml => test377.scxml} (100%) rename tests/scxml/w3c/mandatory/{test378-fail.scxml => test378.scxml} (100%) rename tests/scxml/w3c/mandatory/{test407-fail.scxml => test407.scxml} (100%) rename tests/scxml/w3c/mandatory/{test409-fail.scxml => test409.scxml} (100%) rename tests/scxml/w3c/mandatory/{test554-fail.scxml => test554.scxml} (100%) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 4fd41910..20e6d474 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -46,7 +46,7 @@ jobs: #---------------------------------------------- - name: Test with pytest run: | - uv run pytest --cov-report=xml:coverage.xml + uv run pytest -n auto --cov-report=xml:coverage.xml uv run coverage xml #---------------------------------------------- # upload coverage diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff4ee563..7703ea3e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,7 @@ jobs: - name: Test run: | - uv run pytest + uv run pytest -n auto - name: Build run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 378b6ebd..3796d911 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: pass_filenames: false - id: pytest name: Pytest - entry: uv run pytest + entry: uv run pytest -n auto types: [python] language: system pass_filenames: false diff --git a/pyproject.toml b/pyproject.toml index 745fdcd2..fa7d3b78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ dev = [ "furo >=2024.5.6", "sphinx-copybutton >=0.5.2", "pdbr>=0.8.9", + "pytest-xdist>=3.6.1", ] [build-system] @@ -63,6 +64,7 @@ packages = ["statemachine/"] [tool.pytest.ini_options] addopts = [ + "-s", "--ignore=docs/conf.py", "--ignore=docs/auto_examples/", "--ignore=docs/_build/", @@ -85,6 +87,9 @@ markers = [ ] python_files = ["tests.py", "test_*.py", "*_tests.py"] xfail_strict = true +log_cli = true +log_cli_level = "DEBUG" +asyncio_default_fixture_loop_scope = "module" [tool.coverage.run] branch = true diff --git a/statemachine/io/__init__.py b/statemachine/io/__init__.py index 14c06d38..7ffd570d 100644 --- a/statemachine/io/__init__.py +++ b/statemachine/io/__init__.py @@ -16,7 +16,7 @@ class TransitionDict(TypedDict, total=False): target: str - event: str + event: str | None internal: bool validators: bool cond: CallbacksType @@ -26,6 +26,9 @@ class TransitionDict(TypedDict, total=False): after: CallbacksType +TransitionsDict = Dict[str | None, List[TransitionDict]] + + class StateDict(TypedDict, total=False): name: str value: Any @@ -36,7 +39,7 @@ class StateDict(TypedDict, total=False): class StateWithTransitionsDict(StateDict, total=False): - on: Dict[str, List[TransitionDict]] + on: TransitionsDict StateOptions = StateDict | StateWithTransitionsDict @@ -75,19 +78,20 @@ def create_machine_class_from_definition( events: Dict[str, TransitionList] = {} for state_id, state_events in events_definitions.items(): for event_name, transitions_data in state_events.items(): - for trantion_data in transitions_data: + for transition_data in transitions_data: source = states_instances[state_id] - target = states_instances[trantion_data["target"]] + target = states_instances[transition_data["target"]] + # TODO: Join `trantion_data.event` with `event_name` transition = source.to( target, event=event_name, - cond=trantion_data.get("cond"), - unless=trantion_data.get("unless"), - on=trantion_data.get("on"), - before=trantion_data.get("before"), - after=trantion_data.get("after"), + cond=transition_data.get("cond"), + unless=transition_data.get("unless"), + on=transition_data.get("on"), + before=transition_data.get("before"), + after=transition_data.get("after"), ) if event_name in events: diff --git a/statemachine/io/scxml.py b/statemachine/io/scxml.py deleted file mode 100644 index 5bcddf11..00000000 --- a/statemachine/io/scxml.py +++ /dev/null @@ -1,709 +0,0 @@ -""" -Simple SCXML parser that converts SCXML documents to state machine definitions. -""" - -import html -import re -import xml.etree.ElementTree as ET -from dataclasses import dataclass -from pathlib import Path -from typing import Any -from typing import Dict -from typing import List -from uuid import uuid4 - -from statemachine.event import Event -from statemachine.io import create_machine_class_from_definition - -from ..model import Model -from ..statemachine import StateMachine - - -@dataclass -class _Data: - kwargs: dict - - def __getattr__(self, name): - return self.kwargs.get(name, None) - - def get(self, name, default=None): - return self.kwargs.get(name, default) - - -class EventDataWrapper: - origin: str = "" - origintype: str = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor" - """The origintype of the :ref:`Event` as specified by the SCXML namespace.""" - - def __init__(self, event_data): - self.event_data = event_data - - def __getattr__(self, name): - return getattr(self.event_data, name) - - @property - def name(self): - return self.event_data.event - - @property - def data(self): - "Property used by the SCXML namespace" - if self.trigger_data.kwargs: - return _Data(self.trigger_data.kwargs) - elif self.trigger_data.args and len(self.trigger_data.args) == 1: - return self.trigger_data.args[0] - else: - return self.trigger_data.args - - -def _eval(expr: str, **kwargs) -> Any: - if "machine" in kwargs: - kwargs.update(kwargs["machine"].model.__dict__) - if "event_data" in kwargs: - kwargs["_event"] = EventDataWrapper(kwargs["event_data"]) - - return eval(expr, {}, kwargs) - - -def parse_executable_content(element): - """Parses the children as content XML into a callable.""" - actions = [parse_element(child) for child in element] - - def execute_block(*args, **kwargs): - machine = kwargs["machine"] - try: - for action in actions: - action(*args, **kwargs) - - machine._processing_loop() - except Exception as e: - machine.send("error.execution", error=e) - - if not actions: - return None - return execute_block - - -def parse_element(element): - """Parses an individual XML element into a callable.""" - tag = element.tag - if tag == "raise": - return parse_raise(element) - elif tag == "assign": - return parse_assign(element) - elif tag == "foreach": - return parse_foreach(element) - elif tag == "log": - return parse_log(element) - elif tag == "if": - return parse_if(element) - elif tag == "send": - return parse_send(element) - elif tag == "cancel": - return parse_cancel(element) - elif tag == "script": - return parse_script(element) - else: - raise ValueError(f"Unknown tag: {tag}") - - -def parse_raise(element): - """Parses the element into a callable.""" - event = element.attrib["event"] - - def raise_action(*args, **kwargs): - machine = kwargs["machine"] - machine.send(event) - - return raise_action - - -def parse_cancel(element): - """Parses the element into a callable.""" - sendid = element.attrib.get("sendid") - sendidexpr = element.attrib.get("sendidexpr") - - def cancel(*args, **kwargs): - if sendid and sendidexpr: - raise ValueError(" cannot have both a 'sendid' and 'sendidexpr' attribute") - elif sendid: - send_id = sendid - elif sendidexpr: - send_id = _eval(sendidexpr, **kwargs) - else: - raise ValueError(" must have either a 'sendid' or 'sendidexpr' attribute") - machine = kwargs["machine"] - machine.cancel_event(send_id) - - return cancel - - -def parse_log(element): - """Parses the element into a callable.""" - label = element.attrib.get("label") - expr = element.attrib["expr"] - - def raise_log(*args, **kwargs): - machine = kwargs["machine"] - kwargs.update(machine.model.__dict__) - value = _eval(expr, **kwargs) - if label: - print(f"{label}: {value!r}") - else: - print(f"{value!r}") - - return raise_log - - -def parse_assign(element): - """Parses the element into a callable.""" - location = element.attrib.get("location") - expr = element.attrib["expr"] - - def assign_action(*args, **kwargs): - machine = kwargs["machine"] - value = _eval(expr, **kwargs) - - *path, attr = location.split(".") - obj = machine.model - for p in path: - obj = getattr(obj, p) - - if not attr.isidentifier(): - raise ValueError( - f" 'location' must be a valid Python attribute name, got: {location}" - ) - setattr(obj, attr, value) - - return assign_action - - -def parse_script(element): - """ - Parses the