diff --git a/nada_dsl/ast_util.py b/nada_dsl/ast_util.py index b535e3a..c521019 100644 --- a/nada_dsl/ast_util.py +++ b/nada_dsl/ast_util.py @@ -419,3 +419,24 @@ def to_mir(self): "source_ref_index": self.source_ref.to_index(), } } + +@dataclass +class DocumentAccessorASTOperation(ASTOperation): + """AST representation of an document accessor operation.""" + + key: str + source: int + + def child_operations(self): + return [self.source] + + def to_mir(self): + return { + "DocumentAccessor": { + "id": self.id, + "key": self.key, + "source": self.source, + "type": self.ty, + "source_ref_index": self.source_ref.to_index(), + } + } diff --git a/nada_dsl/compiler_frontend.py b/nada_dsl/compiler_frontend.py index de41075..5a52203 100644 --- a/nada_dsl/compiler_frontend.py +++ b/nada_dsl/compiler_frontend.py @@ -11,6 +11,7 @@ from typing import List, Dict, Any, Optional, Tuple from sortedcontainers import SortedDict +from nada_dsl import DocumentAccessorASTOperation from nada_dsl.ast_util import ( AST_OPERATIONS, ASTOperation, @@ -300,6 +301,7 @@ def process_operation( NadaFunctionArgASTOperation, NTupleAccessorASTOperation, ObjectAccessorASTOperation, + DocumentAccessorASTOperation, ), ): processed_operation = ProcessOperationOutput(operation.to_mir(), None) diff --git a/nada_dsl/nada_types/__init__.py b/nada_dsl/nada_types/__init__.py index 1c30396..926ed90 100644 --- a/nada_dsl/nada_types/__init__.py +++ b/nada_dsl/nada_types/__init__.py @@ -114,7 +114,6 @@ def is_numeric(self) -> bool: # TODO: abstract? -@dataclass class DslType: """Nada type class. @@ -136,8 +135,6 @@ class DslType: """ - child: OperationType - def __init__(self, child: OperationType): """NadaType default constructor diff --git a/nada_dsl/nada_types/collections.py b/nada_dsl/nada_types/collections.py index 573c430..e1a9d5c 100644 --- a/nada_dsl/nada_types/collections.py +++ b/nada_dsl/nada_types/collections.py @@ -1,6 +1,8 @@ """Nada Collection type definitions.""" - +import os from dataclasses import dataclass +import inspect +import json from typing import Any, Dict, Generic, List import typing @@ -12,7 +14,7 @@ NewASTOperation, ObjectAccessorASTOperation, ReduceASTOperation, - UnaryASTOperation, + UnaryASTOperation, DocumentAccessorASTOperation, ) from nada_dsl.nada_types import DslType @@ -27,6 +29,8 @@ from nada_dsl.nada_types.function import NadaFunction, create_nada_fn from nada_dsl.nada_types.generics import U, T, R from . import AllTypes, AllTypesType, DslTypeRepr, OperationType +from jsonschema import Draft7Validator +from jsonschema.exceptions import SchemaError def is_primitive_integer(nada_type_str: str): @@ -108,7 +112,7 @@ def store_in_ast(self, ty): ) -class TupleType(DslType): +class TupleType(NadaType): """Marker type for Tuples.""" is_compound = True @@ -165,18 +169,18 @@ def type(self): return TupleType(self.left_type, self.right_type) -def _generate_accessor(ty: Any, accessor: Any) -> DslType: +def _wrap_accessor_with_type(ty: Any, accessor: Any) -> DslType: if hasattr(ty, "ty") and ty.ty.is_literal(): # TODO: fix raise TypeError("Literals are not supported in accessors") return ty.instantiate(accessor) -class NTupleType(DslType): +class NTupleType(NadaType): """Marker type for NTuples.""" is_compound = True - def __init__(self, types: List[DslType]): + def __init__(self, types: List[NadaType]): self.types = types def instantiate(self, child_or_value): @@ -224,7 +228,7 @@ def __getitem__(self, index: int) -> DslType: source_ref=SourceRef.back_frame(), ) - return _generate_accessor(self.types[index], accessor) + return _wrap_accessor_with_type(self.types[index], accessor) def type(self): """Metatype for NTuple""" @@ -261,12 +265,12 @@ def store_in_ast(self, ty: object): ) -class ObjectType(DslType): +class ObjectType(NadaType): """Marker type for Objects.""" is_compound = True - def __init__(self, types: Dict[str, DslType]): + def __init__(self, types: Dict[str, NadaType]): self.types = types def to_mir(self): @@ -314,7 +318,7 @@ def __getattr__(self, attr: str) -> DslType: source_ref=SourceRef.back_frame(), ) - return _generate_accessor(self.types[attr], accessor) + return _wrap_accessor_with_type(self.types[attr], accessor) def type(self): """Metatype for Object""" @@ -350,6 +354,117 @@ def store_in_ast(self, ty: object): ty=ty, ) +class DocumentType(NadaType): + """Marker type for Objects.""" + + is_compound = True + + def __init__(self, types: Dict[str, NadaType]): + self.types = types + + def to_mir(self): + """Convert an object into a Nada type.""" + return { + "Document": {"types": {name: ty.to_mir() for name, ty in self.types.items()}} + } + + def instantiate(self, child_or_value): + return Document(child_or_value, self.types) + +class Document(DslType): + """The Document type""" + + def __init__(self, child, filepath: str = None, public: bool = False, schema: dict = None): + if not schema: + with open(filepath, "r") as schema_file: + schema = json.load(schema_file) + + try: + Draft7Validator.check_schema(schema) + except SchemaError as e: + raise TypeError("Schema validation error:", e.message) + + + self.__schema = schema + self.__public = public + super().__init__(child) + + def __getattr__(self, item): + if item not in self.__schema["properties"]: + raise AttributeError( + f"'Document has no attribute '{item}'" + ) + + accessor = DocumentAccessor( + key=item, + child=self, + source_ref=SourceRef.back_frame(), + ) + + attribute_type = self.__schema_to_nada_type(self.__schema["properties"][item]) + + return _wrap_accessor_with_type(attribute_type, accessor) + + def __schema_to_nada_type(self, schema: dict) -> NadaType: + IntegerType = PublicIntegerType if self.__public else SecretIntegerType + UnsignedIntegerType = PublicUnsignedIntegerType if self.__public else SecretUnsignedIntegerType + BooleanType = PublicBooleanType if self.__public else SecretBooleanType + if schema["type"] == "integer" and "nada_type" in schema and schema["nada_type"] == "unsigned": + return UnsignedIntegerType() + if schema["type"] == "integer": + return IntegerType() + elif schema["type"] == "boolean": + return BooleanType() + elif schema["type"] == "object": + return ObjectType(types={key: self.__schema_to_nada_type(value) for key, value in schema["properties"].items()}) + elif schema["type"] == "array" and "prefixItems" in schema: + return NTupleType([self.__schema_to_nada_type(value) for value in schema["prefixItems"]]) + elif schema["type"] == "array": + if "size" not in schema: + raise TypeError("size not defined in array schema") + return ArrayType(contained_type=self.__schema_to_nada_type(schema["items"]), size=schema["size"]) + else: + raise TypeError(f"type '{schema['type']}' not supported in json schema") + + def type(self): + return DocumentType({key: self.__schema_to_nada_type(value) for key, value in self.__schema["properties"].items()}) + +class PublicDocument(Document): + def __init__(self, child, filepath: str): + super().__init__(child, filepath, True) + +class SecretDocument(Document): + def __init__(self, child, filepath: str): + super().__init__(child, filepath, False) + +@dataclass +class DocumentAccessor: + """Accessor for Object""" + + child: Object + key: str + source_ref: SourceRef + + def __init__( + self, + child: Object, + key: str, + source_ref: SourceRef, + ): + self.id = next_operation_id() + self.child = child + self.key = key + self.source_ref = source_ref + + def store_in_ast(self, ty: object): + """Store this accessor in the AST.""" + AST_OPERATIONS[self.id] = DocumentAccessorASTOperation( + id=self.id, + source=self.child.child.id, + key=self.key, + source_ref=self.source_ref, + ty=ty, + ) class Zip: """The Zip operation.""" @@ -412,7 +527,7 @@ def store_in_ast(self, ty: DslTypeRepr): ) -class ArrayType(DslType): +class ArrayType(NadaType): """Marker type for arrays.""" is_compound = True diff --git a/nada_mir/pyproject.toml b/nada_mir/pyproject.toml index 6a6102f..119e123 100644 --- a/nada_mir/pyproject.toml +++ b/nada_mir/pyproject.toml @@ -15,7 +15,11 @@ classifiers = [ "Operating System :: OS Independent", ] -dependencies = ["grpcio-tools==1.62.3", "betterproto==2.0.0b7"] +dependencies = [ + "grpcio-tools==1.62.3", + "betterproto==2.0.0b7", + "jsonschema==4.22.0", +] [project.optional-dependencies] dev = ["betterproto[compiler]==2.0.0b7"] diff --git a/pyproject.toml b/pyproject.toml index 5a2cb22..58a189d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,17 +14,28 @@ dependencies = [ "parsial~=0.1", "sortedcontainers~=2.4", "typing_extensions~=4.12.2", + "jsonschema==4.22.0", ] classifiers = ["License :: OSI Approved :: Apache Software License"] license = { file = "LICENSE" } [project.optional-dependencies] -docs = ["toml~=0.10.2", "sphinx>=5,<9", "sphinx-rtd-theme>=1.0,<3.1", "sphinx-autoapi~=3.3.2"] +docs = [ + "toml~=0.10.2", + "sphinx>=5,<9", + "sphinx-rtd-theme>=1.0,<3.1", + "sphinx-autoapi~=3.3.2", +] test = ["pytest>=7.4,<9.0", "pytest-cov>=4,<7"] lint = ["pylint>=2.17,<3.4"] [tool.setuptools] -packages = ["nada_dsl", "nada_dsl.audit", "nada_dsl.future", "nada_dsl.nada_types"] +packages = [ + "nada_dsl", + "nada_dsl.audit", + "nada_dsl.future", + "nada_dsl.nada_types", +] [tool.pytest.ini_options] addopts = "--doctest-modules --ignore=docs --cov=nada_dsl --cov-report term-missing" @@ -42,7 +53,8 @@ dev-dependencies = [ "tomli", "requests", "typing_extensions~=4.12.2", - "ruff>=0.8.0" + "ruff>=0.8.0", + "jsonschema==4.22.0", ] [tool.uv.sources] diff --git a/test-programs/doc.json b/test-programs/doc.json new file mode 100644 index 0000000..ed9c67e --- /dev/null +++ b/test-programs/doc.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "a": { + "type": "integer" + }, + "b": { + "type": "boolean" + }, + "c": { + "type": "object", + "properties": { + "c": { + "type": "integer" + } + } + }, + "d": { + "type": "array", + "items": { + "type": "integer" + }, + "size": 2 + }, + "e": { + "type": "array", + "prefixItems": [{"type": "integer"}, {"type": "boolean"}] + }, + "f": { + "type": "integer", + "nada_type": "unsigned_integer" + } + }, + "required": [ + "a", + "b" + ], + "additionalProperties": false +} \ No newline at end of file diff --git a/test-programs/document.py b/test-programs/document.py new file mode 100644 index 0000000..ee594c1 --- /dev/null +++ b/test-programs/document.py @@ -0,0 +1,55 @@ +import os.path + +from nada_dsl import * + +schema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "a": { + "type": "integer" + }, + "b": { + "type": "boolean" + }, + "c": { + "type": "object", + "properties": { + "c": { + "type": "integer" + } + } + }, + "d": { + "type": "array", + "items": { + "type": "integer" + }, + "size": 2 + }, + "e": { + "type": "array", + "prefixItems": [{"type": "integer"}, {"type": "boolean"}] + }, + "f": { + "type": "integer", + "nada_type": "unsigned_integer" + } + }, + "required": [ + "a", + "b" + ], + "additionalProperties": False +} + +def nada_main(): + party1 = Party(name="Party1") + doc = Document(Input(name="my_doc", party=party1), schema=schema) + my_int = PublicInteger(Input(name="my_int", party=party1)) + doc.a + doc.b + doc.c + doc.d + doc.e + return [Output(doc.a + my_int, "my_output", party1)] diff --git a/test-programs/mir.json b/test-programs/mir.json new file mode 100644 index 0000000..bb6e09c --- /dev/null +++ b/test-programs/mir.json @@ -0,0 +1,164 @@ +{ + "functions": [], + "parties": [ + { + "name": "Party1", + "source_ref_index": 4 + } + ], + "inputs": [ + { + "name": "my_int", + "type": "Integer", + "party": "Party1", + "doc": "", + "source_ref_index": 1 + }, + { + "name": "my_doc", + "type": { + "Document": { + "types": { + "a": "SecretInteger", + "b": "SecretBoolean", + "c": { + "Object": { + "types": { + "c": "SecretInteger" + } + } + }, + "d": { + "Array": { + "inner_type": "SecretInteger", + "size": 2 + } + }, + "e": { + "NTuple": { + "types": [ + "SecretInteger", + "SecretBoolean" + ] + } + }, + "f": "SecretInteger" + } + } + }, + "party": "Party1", + "doc": "", + "source_ref_index": 3 + } + ], + "literals": [], + "outputs": [ + { + "operation_id": 9, + "name": "my_output", + "party": "Party1", + "type": "SecretInteger", + "source_ref_index": 2 + } + ], + "operations": { + "9": { + "Addition": { + "id": 9, + "left": 8, + "right": 2, + "type": "SecretInteger", + "source_ref_index": 0 + } + }, + "2": { + "InputReference": { + "id": 2, + "refers_to": "my_int", + "type": "Integer", + "source_ref_index": 1 + } + }, + "8": { + "DocumentAccessor": { + "id": 8, + "key": "a", + "source": 1, + "type": "SecretInteger", + "source_ref_index": 2 + } + }, + "1": { + "InputReference": { + "id": 1, + "refers_to": "my_doc", + "type": { + "Document": { + "types": { + "a": "SecretInteger", + "b": "SecretBoolean", + "c": { + "Object": { + "types": { + "c": "SecretInteger" + } + } + }, + "d": { + "Array": { + "inner_type": "SecretInteger", + "size": 2 + } + }, + "e": { + "NTuple": { + "types": [ + "SecretInteger", + "SecretBoolean" + ] + } + }, + "f": "SecretInteger" + } + } + }, + "source_ref_index": 3 + } + } + }, + "source_files": { + "document.py": "import os.path\n\nfrom nada_dsl import *\n\nschema = {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"a\": {\n \"type\": \"integer\"\n },\n \"b\": {\n \"type\": \"boolean\"\n },\n \"c\": {\n \"type\": \"object\",\n \"properties\": {\n \"c\": {\n \"type\": \"integer\"\n }\n }\n },\n \"d\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"integer\"\n },\n \"size\": 2\n },\n \"e\": {\n \"type\": \"array\",\n \"prefixItems\": [{\"type\": \"integer\"}, {\"type\": \"boolean\"}]\n },\n \"f\": {\n \"type\": \"integer\",\n \"nada_type\": \"unsigned_integer\"\n }\n },\n \"required\": [\n \"a\",\n \"b\"\n ],\n \"additionalProperties\": False\n}\n\ndef nada_main():\n party1 = Party(name=\"Party1\")\n doc = Document(Input(name=\"my_doc\", party=party1), schema=schema)\n my_int = PublicInteger(Input(name=\"my_int\", party=party1))\n doc.a\n doc.b\n doc.c\n doc.d\n doc.e\n return [Output(doc.a + my_int, \"my_output\", party1)]\n" + }, + "source_refs": [ + { + "lineno": 137, + "offset": 0, + "file": "scalar_types.py", + "length": 0 + }, + { + "lineno": 49, + "offset": 1031, + "file": "document.py", + "length": 62 + }, + { + "lineno": 55, + "offset": 0, + "file": "document.py", + "length": 0 + }, + { + "lineno": 48, + "offset": 961, + "file": "document.py", + "length": 69 + }, + { + "lineno": 47, + "offset": 927, + "file": "document.py", + "length": 33 + } + ] +} diff --git a/tests/compile_test.py b/tests/compile_test.py index 3045d29..ce381dc 100644 --- a/tests/compile_test.py +++ b/tests/compile_test.py @@ -151,3 +151,10 @@ def test_compile_ntuple(): def test_compile_object(): mir_str = compile_script(f"{get_test_programs_folder()}/object_accessor.py").mir assert mir_str != "" + + +def test_compile_document(): + mir_str = compile_script(f"{get_test_programs_folder()}/document.py").mir + print(f"{mir_str}") + assert mir_str != "" + raise Exception("TODO: implement the rest of the test") diff --git a/uv.lock b/uv.lock index bc07a9b..ea766d3 100644 --- a/uv.lock +++ b/uv.lock @@ -45,6 +45,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/45/86/4736ac618d82a20d87d2f92ae19441ebc7ac9e7a581d7e58bbe79233b24a/asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", size = 27764 }, ] +[[package]] +name = "attrs" +version = "24.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 }, +] + [[package]] name = "babel" version = "2.16.0" @@ -469,6 +478,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, ] +[[package]] +name = "jsonschema" +version = "4.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/f1/1c1dc0f6b3bf9e76f7526562d29c320fa7d6a2f35b37a1392cc0acd58263/jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7", size = 325490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/2f/324fab4be6fe37fb7b521546e8a557e6cf08c1c1b3d0b4839a00f589d9ef/jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802", size = 88316 }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, +] + [[package]] name = "markupsafe" version = "3.0.2" @@ -623,6 +659,7 @@ version = "0.7.1" source = { editable = "." } dependencies = [ { name = "asttokens" }, + { name = "jsonschema" }, { name = "parsial" }, { name = "richreports" }, { name = "sortedcontainers" }, @@ -646,6 +683,7 @@ test = [ [package.dev-dependencies] dev = [ + { name = "jsonschema" }, { name = "nada-mir-proto", extra = ["dev"] }, { name = "pylint" }, { name = "pytest" }, @@ -663,6 +701,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "asttokens", specifier = "~=2.4" }, + { name = "jsonschema", specifier = "==4.22.0" }, { name = "parsial", specifier = "~=0.1" }, { name = "pylint", marker = "extra == 'lint'", specifier = ">=2.17,<3.4" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=7.4,<9.0" }, @@ -678,6 +717,7 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ + { name = "jsonschema", specifier = "==4.22.0" }, { name = "nada-mir-proto", extras = ["dev"], editable = "nada_mir" }, { name = "pylint", specifier = ">=2.17,<3.4" }, { name = "pytest", specifier = ">=7.4,<9.0" }, @@ -699,6 +739,7 @@ source = { editable = "nada_mir" } dependencies = [ { name = "betterproto" }, { name = "grpcio-tools" }, + { name = "jsonschema" }, ] [package.optional-dependencies] @@ -711,6 +752,7 @@ requires-dist = [ { name = "betterproto", specifier = "==2.0.0b7" }, { name = "betterproto", extras = ["compiler"], marker = "extra == 'dev'", specifier = "==2.0.0b7" }, { name = "grpcio-tools", specifier = "==1.62.3" }, + { name = "jsonschema", specifier = "==4.22.0" }, ] [[package]] @@ -886,6 +928,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, ] +[[package]] +name = "referencing" +version = "0.35.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/5b/73ca1f8e72fff6fa52119dbd185f73a907b1989428917b24cff660129b6d/referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", size = 62991 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de", size = 26684 }, +] + [[package]] name = "requests" version = "2.32.3" @@ -910,6 +965,78 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bb/e5/6d9baab97743fab7c168d3ee330ebc1b3d6c90df37469a5ce4e3fa90f811/richreports-0.2.0-py3-none-any.whl", hash = "sha256:b99a4a0fb65d53f0d68e577518a89d5e098a9361a72fb1df7f8f0b9d4b6df2ac", size = 7534 }, ] +[[package]] +name = "rpds-py" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/23/80/afdf96daf9b27d61483ef05b38f282121db0e38f5fd4e89f40f5c86c2a4f/rpds_py-0.21.0.tar.gz", hash = "sha256:ed6378c9d66d0de903763e7706383d60c33829581f0adff47b6535f1802fa6db", size = 26335 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/a4/91747f902f166c589f1753cbd8bda713aceb75817c8bb597058a38aa85e6/rpds_py-0.21.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a017f813f24b9df929674d0332a374d40d7f0162b326562daae8066b502d0590", size = 327473 }, + { url = "https://files.pythonhosted.org/packages/8a/72/75a30a07f96ae210e732c50c7339e742945fdc83661e65a1c80fcf39ceea/rpds_py-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20cc1ed0bcc86d8e1a7e968cce15be45178fd16e2ff656a243145e0b439bd250", size = 318359 }, + { url = "https://files.pythonhosted.org/packages/dc/63/87d469d7628cd71366fd1baa32573acd37385843b8d39b6e2b69f16eec48/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad116dda078d0bc4886cb7840e19811562acdc7a8e296ea6ec37e70326c1b41c", size = 361377 }, + { url = "https://files.pythonhosted.org/packages/dd/b1/78da258a4cafa1d8606a21b7d9ed4cc9d72d1c663583060ab02444b9bd9c/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:808f1ac7cf3b44f81c9475475ceb221f982ef548e44e024ad5f9e7060649540e", size = 369494 }, + { url = "https://files.pythonhosted.org/packages/44/47/6fdb7273cc80066d434e83cd49a3cfedb6d96ff70908480870877fb64b1e/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de552f4a1916e520f2703ec474d2b4d3f86d41f353e7680b597512ffe7eac5d0", size = 403639 }, + { url = "https://files.pythonhosted.org/packages/5f/4a/8c6c46afc050b5243be579be7f7b194d00b9731e83cc0845e9c70db127bb/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efec946f331349dfc4ae9d0e034c263ddde19414fe5128580f512619abed05f1", size = 430551 }, + { url = "https://files.pythonhosted.org/packages/d4/31/2dd40abc26fc0fc037b86006583276dc375d38ac821d4ca2394274e8045b/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b80b4690bbff51a034bfde9c9f6bf9357f0a8c61f548942b80f7b66356508bf5", size = 360795 }, + { url = "https://files.pythonhosted.org/packages/9d/2a/665b9ebef76f54764f1437ac03373a95a69480b7ce56c480360f88730cae/rpds_py-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085ed25baac88953d4283e5b5bd094b155075bb40d07c29c4f073e10623f9f2e", size = 382663 }, + { url = "https://files.pythonhosted.org/packages/e8/8c/e056f0c887d29baa256f8c8d7f7079a72d80395c35c14219de45ab19dce2/rpds_py-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:daa8efac2a1273eed2354397a51216ae1e198ecbce9036fba4e7610b308b6153", size = 546477 }, + { url = "https://files.pythonhosted.org/packages/33/11/588568f6c2ed5c9d6d121c188c71ca0f76e0e369a6d66f835737189e5a75/rpds_py-0.21.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:95a5bad1ac8a5c77b4e658671642e4af3707f095d2b78a1fdd08af0dfb647624", size = 549477 }, + { url = "https://files.pythonhosted.org/packages/15/86/c1401e2f70fbdf963c2ac9157994ebeb00c101ddf87975a90507f27cb2f4/rpds_py-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3e53861b29a13d5b70116ea4230b5f0f3547b2c222c5daa090eb7c9c82d7f664", size = 527966 }, + { url = "https://files.pythonhosted.org/packages/66/f2/452420f1493112825e975c87b3b4fd8b334e0e228cdb641597a92e0c3267/rpds_py-0.21.0-cp310-none-win32.whl", hash = "sha256:ea3a6ac4d74820c98fcc9da4a57847ad2cc36475a8bd9683f32ab6d47a2bd682", size = 200978 }, + { url = "https://files.pythonhosted.org/packages/35/4c/674b2e2d75607acdbc7a162ace36dcaad225c9e760cef5defa5c0f5ddd2d/rpds_py-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:b8f107395f2f1d151181880b69a2869c69e87ec079c49c0016ab96860b6acbe5", size = 218549 }, + { url = "https://files.pythonhosted.org/packages/80/61/615929ea79f5fd0b3aca000411a33bcc1753607ccc1af0ce7b05b56e6e56/rpds_py-0.21.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5555db3e618a77034954b9dc547eae94166391a98eb867905ec8fcbce1308d95", size = 327267 }, + { url = "https://files.pythonhosted.org/packages/a5/f5/28e89dda55b731d78cbfea284dc9789d265a8a06523f0adf60e9b05cade7/rpds_py-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:97ef67d9bbc3e15584c2f3c74bcf064af36336c10d2e21a2131e123ce0f924c9", size = 318227 }, + { url = "https://files.pythonhosted.org/packages/e4/ef/eb90feb3e384543c48e2f867551075c43a429aa4c9a44e9c4bd71f4f786b/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab2c2a26d2f69cdf833174f4d9d86118edc781ad9a8fa13970b527bf8236027", size = 361235 }, + { url = "https://files.pythonhosted.org/packages/ed/e7/8ea2d3d3398266c5c8ddd957d86003493b6d14f8f158b726dd09c8f43dee/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e8921a259f54bfbc755c5bbd60c82bb2339ae0324163f32868f63f0ebb873d9", size = 369467 }, + { url = "https://files.pythonhosted.org/packages/51/25/a286abda9da7820c971a0b1abcf1d31fb81c44a1088a128ad26c77206622/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a7ff941004d74d55a47f916afc38494bd1cfd4b53c482b77c03147c91ac0ac3", size = 403482 }, + { url = "https://files.pythonhosted.org/packages/7a/1e/9c3c0463fe142456dcd9e9be0ffd15b66a77adfcdf3ecf94fa2b12d95fcb/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5145282a7cd2ac16ea0dc46b82167754d5e103a05614b724457cffe614f25bd8", size = 429943 }, + { url = "https://files.pythonhosted.org/packages/e1/fd/f1fd7e77fef8e5a442ce7fd80ba957730877515fe18d7195f646408a60ce/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de609a6f1b682f70bb7163da745ee815d8f230d97276db049ab447767466a09d", size = 360437 }, + { url = "https://files.pythonhosted.org/packages/55/83/347932db075847f4f8172c3b53ad70fe725edd9058f0d4098080ad45e3bc/rpds_py-0.21.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40c91c6e34cf016fa8e6b59d75e3dbe354830777fcfd74c58b279dceb7975b75", size = 382400 }, + { url = "https://files.pythonhosted.org/packages/22/9b/2a6eeab4e6752adba751cfee19bdf35d11e1073509f74883cbf14d42d682/rpds_py-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d2132377f9deef0c4db89e65e8bb28644ff75a18df5293e132a8d67748397b9f", size = 546560 }, + { url = "https://files.pythonhosted.org/packages/3c/19/6e51a141fe6f017d07b7d899b10a4af9e0f268deffacc1107d70fcd9257b/rpds_py-0.21.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0a9e0759e7be10109645a9fddaaad0619d58c9bf30a3f248a2ea57a7c417173a", size = 549334 }, + { url = "https://files.pythonhosted.org/packages/cf/40/4ae09a07e4531278e6bee41ef3e4f166c23468135afc2c6c98917bfc28e6/rpds_py-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e20da3957bdf7824afdd4b6eeb29510e83e026473e04952dca565170cd1ecc8", size = 527855 }, + { url = "https://files.pythonhosted.org/packages/eb/45/2135be31543677687a426117c56d8b33e8b581bc4a8b7abfa53721012162/rpds_py-0.21.0-cp311-none-win32.whl", hash = "sha256:f71009b0d5e94c0e86533c0b27ed7cacc1239cb51c178fd239c3cfefefb0400a", size = 200968 }, + { url = "https://files.pythonhosted.org/packages/68/fa/e66c3aaf13ef91c203ba47c102cd7c5dca92dde8837e5093577968d6d36d/rpds_py-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:e168afe6bf6ab7ab46c8c375606298784ecbe3ba31c0980b7dcbb9631dcba97e", size = 218502 }, + { url = "https://files.pythonhosted.org/packages/d9/5a/3aa6f5d8bacbe4f55ebf9a3c9628dad40cdb57f845124cf13c78895ea156/rpds_py-0.21.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:30b912c965b2aa76ba5168fd610087bad7fcde47f0a8367ee8f1876086ee6d1d", size = 329516 }, + { url = "https://files.pythonhosted.org/packages/df/c0/67c8c8ac850c6e3681e356a59d46315bf73bc77cb50c9a32db8ae44325b7/rpds_py-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca9989d5d9b1b300bc18e1801c67b9f6d2c66b8fd9621b36072ed1df2c977f72", size = 321245 }, + { url = "https://files.pythonhosted.org/packages/64/83/bf31341f21fa594035891ff04a497dc86b210cc1a903a9cc01b097cc614f/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f54e7106f0001244a5f4cf810ba8d3f9c542e2730821b16e969d6887b664266", size = 363951 }, + { url = "https://files.pythonhosted.org/packages/a2/e1/8218bba36737621262df316fbb729639af25ff611cc07bfeaadc1bfa6292/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fed5dfefdf384d6fe975cc026886aece4f292feaf69d0eeb716cfd3c5a4dd8be", size = 373113 }, + { url = "https://files.pythonhosted.org/packages/39/8d/4afcd688e3ad33ec273900f42e6a41e9bd9f43cfc509b6d498683d2d0338/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590ef88db231c9c1eece44dcfefd7515d8bf0d986d64d0caf06a81998a9e8cab", size = 405944 }, + { url = "https://files.pythonhosted.org/packages/fa/65/3326efa721b6ecd70262aab69a26c9bc19398cdb0a2a416ef30b58326460/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f983e4c2f603c95dde63df633eec42955508eefd8d0f0e6d236d31a044c882d7", size = 422874 }, + { url = "https://files.pythonhosted.org/packages/31/fb/48a647d0afab74289dd21a4128002d58684c22600a22c4bfb76cb9e3bfb0/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b229ce052ddf1a01c67d68166c19cb004fb3612424921b81c46e7ea7ccf7c3bf", size = 364227 }, + { url = "https://files.pythonhosted.org/packages/f1/b0/1cdd179d7382dd52d65b1fd19c54d090b6bd0688dfbe259bb5ab7548c359/rpds_py-0.21.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ebf64e281a06c904a7636781d2e973d1f0926a5b8b480ac658dc0f556e7779f4", size = 386447 }, + { url = "https://files.pythonhosted.org/packages/dc/41/84ace07f31aac3a96b73a374d89106cf252f7d3274e7cae85d17a27c602d/rpds_py-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:998a8080c4495e4f72132f3d66ff91f5997d799e86cec6ee05342f8f3cda7dca", size = 549386 }, + { url = "https://files.pythonhosted.org/packages/33/ce/bf51bc5a3aa539171ea8c7737ab5ac06cef54c79b6b2a0511afc41533c89/rpds_py-0.21.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:98486337f7b4f3c324ab402e83453e25bb844f44418c066623db88e4c56b7c7b", size = 554777 }, + { url = "https://files.pythonhosted.org/packages/76/b1/950568e55a94c2979c2b61ec24e76e648a525fbc7551ccfc1f2841e39d44/rpds_py-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a78d8b634c9df7f8d175451cfeac3810a702ccb85f98ec95797fa98b942cea11", size = 530918 }, + { url = "https://files.pythonhosted.org/packages/78/84/93f00e3613426c8a7a9ca16782d2828f2ac55296dd5c6b599379d9f59ee2/rpds_py-0.21.0-cp312-none-win32.whl", hash = "sha256:a58ce66847711c4aa2ecfcfaff04cb0327f907fead8945ffc47d9407f41ff952", size = 203112 }, + { url = "https://files.pythonhosted.org/packages/e6/08/7a186847dd78881a781d2be9b42c8e49c3261c0f4a6d0289ba9a1e4cde71/rpds_py-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:e860f065cc4ea6f256d6f411aba4b1251255366e48e972f8a347cf88077b24fd", size = 220735 }, + { url = "https://files.pythonhosted.org/packages/32/3a/e69ec108eefb9b1f19ee00dde7a800b485942e62b123f01d9156a6d8569c/rpds_py-0.21.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ee4eafd77cc98d355a0d02f263efc0d3ae3ce4a7c24740010a8b4012bbb24937", size = 329206 }, + { url = "https://files.pythonhosted.org/packages/f6/c0/fa689498fa3415565306398c8d2a596207c2a13d3cc03724f32514bddfbc/rpds_py-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:688c93b77e468d72579351a84b95f976bd7b3e84aa6686be6497045ba84be560", size = 320245 }, + { url = "https://files.pythonhosted.org/packages/68/d0/466b61007005f1b2fd8501f23e4bdee4d71c7381b61358750920d1882ac9/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38dbf31c57032667dd5a2f0568ccde66e868e8f78d5a0d27dcc56d70f3fcd3b", size = 363585 }, + { url = "https://files.pythonhosted.org/packages/1e/e2/787ea3a0f4b197893c62c254e6f14929c40bbcff86922928ac4eafaa8edf/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d6129137f43f7fa02d41542ffff4871d4aefa724a5fe38e2c31a4e0fd343fb0", size = 372302 }, + { url = "https://files.pythonhosted.org/packages/b5/ef/99f2cfe6aa128c21f1b30c66ecd348cbd59792953ca35eeb6efa38b88aa1/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520ed8b99b0bf86a176271f6fe23024323862ac674b1ce5b02a72bfeff3fff44", size = 405344 }, + { url = "https://files.pythonhosted.org/packages/30/3c/9d12d0b76ecfe80a7ba4770459828dda495d72b18cafd6dfd54c67b2e282/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaeb25ccfb9b9014a10eaf70904ebf3f79faaa8e60e99e19eef9f478651b9b74", size = 422322 }, + { url = "https://files.pythonhosted.org/packages/f9/22/387aec1cd6e124adbc3b1f40c4e4152c3963ae47d78d3ca650102ea72c4f/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af04ac89c738e0f0f1b913918024c3eab6e3ace989518ea838807177d38a2e94", size = 363739 }, + { url = "https://files.pythonhosted.org/packages/d1/3e/0ad65b776db13d13f002ab363fe3821cd1adec500d8e05e0a81047a75f9d/rpds_py-0.21.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9b76e2afd585803c53c5b29e992ecd183f68285b62fe2668383a18e74abe7a3", size = 386579 }, + { url = "https://files.pythonhosted.org/packages/4f/3b/c68c1067b24a7df47edcc0325a825908601aba399e2d372a156edc631ad1/rpds_py-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5afb5efde74c54724e1a01118c6e5c15e54e642c42a1ba588ab1f03544ac8c7a", size = 548924 }, + { url = "https://files.pythonhosted.org/packages/ab/1c/35f1a5cce4bca71c49664f00140010a96b126e5f443ebaf6db741c25b9b7/rpds_py-0.21.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:52c041802a6efa625ea18027a0723676a778869481d16803481ef6cc02ea8cb3", size = 554217 }, + { url = "https://files.pythonhosted.org/packages/c8/d0/48154c152f9adb8304b21d867d28e79be3b352633fb195c03c7107a4da9a/rpds_py-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee1e4fc267b437bb89990b2f2abf6c25765b89b72dd4a11e21934df449e0c976", size = 530540 }, + { url = "https://files.pythonhosted.org/packages/50/e8/78847f4e112e99fd5b7bc30fea3e4a44c20b811473d6755f944c5bf0aec7/rpds_py-0.21.0-cp313-none-win32.whl", hash = "sha256:0c025820b78817db6a76413fff6866790786c38f95ea3f3d3c93dbb73b632202", size = 202604 }, + { url = "https://files.pythonhosted.org/packages/60/31/083e6337775e133fb0217ed0ab0752380efa6e5112f2250d592d4135a228/rpds_py-0.21.0-cp313-none-win_amd64.whl", hash = "sha256:320c808df533695326610a1b6a0a6e98f033e49de55d7dc36a13c8a30cfa756e", size = 220448 }, + { url = "https://files.pythonhosted.org/packages/ff/d3/ffb04445d29c03d380047c62bed01b979adb9204424e2c833817012f679e/rpds_py-0.21.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6b4ef7725386dc0762857097f6b7266a6cdd62bfd209664da6712cb26acef035", size = 328265 }, + { url = "https://files.pythonhosted.org/packages/dc/9d/894ff29a2be8f85fd1acff6e0c1b52b629aee019da8651125af9ee4894e1/rpds_py-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6bc0e697d4d79ab1aacbf20ee5f0df80359ecf55db33ff41481cf3e24f206919", size = 319238 }, + { url = "https://files.pythonhosted.org/packages/43/3d/0e5b835c22933a5bdc4413e4a91de55a8c1ef33f55eb2514a5cf24729173/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da52d62a96e61c1c444f3998c434e8b263c384f6d68aca8274d2e08d1906325c", size = 362136 }, + { url = "https://files.pythonhosted.org/packages/67/81/c9f29da910ac19758f170633c0937fc2f0898b84389bd05bfc255c985f19/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98e4fe5db40db87ce1c65031463a760ec7906ab230ad2249b4572c2fc3ef1f9f", size = 370411 }, + { url = "https://files.pythonhosted.org/packages/a8/df/b989044f90b81093e454eb54799e7ee5b085ebf957a75d07d5e21eac2fb5/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30bdc973f10d28e0337f71d202ff29345320f8bc49a31c90e6c257e1ccef4333", size = 404598 }, + { url = "https://files.pythonhosted.org/packages/8f/09/f79cd575f503932f41138c4bec4c902eb3b71ea8570436688145cc77b8ef/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:faa5e8496c530f9c71f2b4e1c49758b06e5f4055e17144906245c99fa6d45356", size = 430224 }, + { url = "https://files.pythonhosted.org/packages/34/46/7fae3500bc188df2feee09dd72df262b97d31e8e4bd2ff4a8be4e28bf1d3/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32eb88c30b6a4f0605508023b7141d043a79b14acb3b969aa0b4f99b25bc7d4a", size = 361660 }, + { url = "https://files.pythonhosted.org/packages/5b/1d/d850242d30e68f99ad80815576f38b378b5aba393613e3357ed5e593499e/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a89a8ce9e4e75aeb7fa5d8ad0f3fecdee813802592f4f46a15754dcb2fd6b061", size = 384008 }, + { url = "https://files.pythonhosted.org/packages/c9/16/df4cfd1de216c25de24f8631f17380f8edee92201ec7810d1e2ba1dd9f85/rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:241e6c125568493f553c3d0fdbb38c74babf54b45cef86439d4cd97ff8feb34d", size = 546855 }, + { url = "https://files.pythonhosted.org/packages/c0/b8/03d4561095d4fbf2ab62ed651a2b5cb674fe5245b1ab2f7909e8056bd014/rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:3b766a9f57663396e4f34f5140b3595b233a7b146e94777b97a8413a1da1be18", size = 550599 }, + { url = "https://files.pythonhosted.org/packages/f4/54/d93867e2bf4acf57314798181faf3bd7d1a4f51a3aa81cb6211d56f74d3f/rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:af4a644bf890f56e41e74be7d34e9511e4954894d544ec6b8efe1e21a1a8da6c", size = 528963 }, + { url = "https://files.pythonhosted.org/packages/66/86/6f72984a284d720d84fba5ee7b0d1b0d320978b516497cbfd6e335e95a3e/rpds_py-0.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3e30a69a706e8ea20444b98a49f386c17b26f860aa9245329bab0851ed100677", size = 219621 }, +] + [[package]] name = "ruff" version = "0.8.0"