From 09b67c694bbbcfd93bd399ca4dac63ace71785db Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 16 Mar 2025 14:26:21 +0100 Subject: [PATCH 001/189] feat: templates/protocols/dialogues.jinja --- .../data/templates/protocols/dialogues.jinja | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 auto_dev/data/templates/protocols/dialogues.jinja diff --git a/auto_dev/data/templates/protocols/dialogues.jinja b/auto_dev/data/templates/protocols/dialogues.jinja new file mode 100644 index 00000000..4909603d --- /dev/null +++ b/auto_dev/data/templates/protocols/dialogues.jinja @@ -0,0 +1,127 @@ +{{ header }} + +""" +This module contains the classes required for {{ snake_name }} dialogue management. + +- {{ camel_name }}Dialogue: The dialogue class maintains state of a dialogue and manages it. +- {{ camel_name }}Dialogues: The dialogues class keeps track of all dialogues. +""" + +from abc import ABC +from typing import Dict, Type, Callable, FrozenSet, cast + +from aea.common import Address +from aea.skills.base import Model +from aea.protocols.base import Message +from aea.protocols.dialogue.base import Dialogue, Dialogues, DialogueLabel +from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message + + +def _role_from_first_message(message: Message, sender: Address) -> Dialogue.Role: + """Infer the role of the agent from an incoming/outgoing first message""" + return {{ camel_name }}Dialogue.Role.{{ role }} + + +class {{ camel_name }}Dialogue(Dialogue): + """The {{ snake_name }} dialogue class maintains state of a dialogue and manages it.""" + + INITIAL_PERFORMATIVES: FrozenSet[Message.Performative] = frozenset({ + {%- for performative in initial_performatives %} + {{ camel_name }}Message.Performative.{{ performative }}, + {%- endfor %} + }) + TERMINAL_PERFORMATIVES: FrozenSet[Message.Performative] = frozenset({ + {%- for performative in terminal_performatives %} + {{ camel_name }}Message.Performative.{{ performative }}, + {%- endfor %} + }) + VALID_REPLIES: Dict[Message.Performative, FrozenSet[Message.Performative]] = { + {%- for performative, replies in valid_replies.items() %} + {{ camel_name }}Message.Performative.{{ performative }}: {% if replies|length > 0 %}frozenset({ + {%- for reply in replies %} + {{ camel_name }}Message.Performative.{{ reply }}, + {%- endfor %} + }){% else %}frozenset({}){% endif %}, + {%- endfor %} + } + + class Role(Dialogue.Role): + """This class defines the agent's role in a {{ snake_name }} dialogue.""" + {%- for role in roles %} + {{ role.name }} = "{{ role.value }}" + {%- endfor %} + + class EndState(Dialogue.EndState): + """This class defines the end states of a {{ snake_name }} dialogue.""" + {%- for state in end_states %} + {{ state.name }} = {{ state.value }} + {%- endfor %} + + def __init__( + self, + dialogue_label: DialogueLabel, + self_address: Address, + role: Dialogue.Role, + message_class: Type[{{ camel_name }}Message] = {{ camel_name }}Message, + ) -> None: + """Initialize a dialogue. + + Args: + dialogue_label: the identifier of the dialogue + self_address: the address of the entity for whom this dialogue is maintained + role: the role of the agent this dialogue is maintained for + message_class: the message class used + """ + Dialogue.__init__( + self, + dialogue_label=dialogue_label, + message_class=message_class, + self_address=self_address, + role=role, + ) + + +class Base{{ camel_name }}Dialogues(Dialogues, ABC): + """This class keeps track of all {{ snake_name }} dialogues.""" + + END_STATES = frozenset({ + {%- for state in end_states %} + {{ camel_name }}Message.EndState.{{ state.name }}{{ "," if not loop.last }} + {%- endfor %} + }) + _keep_terminal_state_dialogues = {{ keep_terminal_state_dialogues }} + + def __init__( + self, + self_address: Address, + role_from_first_message: Callable[[Message, Address], Dialogue.Role] = _role_from_first_message, + dialogue_class: Type[{{ camel_name }}Dialogue] = {{ camel_name }}Dialogue, + ) -> None: + """Initialize dialogues. + + Args: + self_address: the address of the entity for whom dialogues are maintained + dialogue_class: the dialogue class used + role_from_first_message: the callable determining role from first message + """ + Dialogues.__init__( + self, + self_address=self_address, + end_states=cast(FrozenSet[Dialogue.EndState], self.END_STATES), + message_class={{ camel_name }}Message, + dialogue_class=dialogue_class, + role_from_first_message=role_from_first_message, + ) + + +class {{ camel_name }}Dialogues(Base{{ camel_name }}Dialogues, Model): + """This class defines the dialogues used in {{ snake_name }}.""" + + def __init__(self, **kwargs): + """Initialize dialogues.""" + Model.__init__(self, keep_terminal_state_dialogues={{ keep_terminal_state_dialogues }}, **kwargs) + Base{{ camel_name }}Dialogues.__init__( + self, + self_address=str(self.context.skill_id), + role_from_first_message=_role_from_first_message, + ) From 46d869b01a4bf80eec70b93e10329d1b2ba2ca81 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:01:08 +0100 Subject: [PATCH 002/189] tests: add test cases for primitive types and basic enums --- .../data/protocols/protobuf/basic_enum.proto | 13 ++++++++++++ .../protocols/protobuf/optional_enum.proto | 13 ++++++++++++ .../protobuf/optional_primitives.proto | 21 +++++++++++++++++++ .../data/protocols/protobuf/primitives.proto | 21 +++++++++++++++++++ .../protocols/protobuf/repeated_enum.proto | 13 ++++++++++++ .../protobuf/repeated_primitives.proto | 21 +++++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 tests/data/protocols/protobuf/basic_enum.proto create mode 100644 tests/data/protocols/protobuf/optional_enum.proto create mode 100644 tests/data/protocols/protobuf/optional_primitives.proto create mode 100644 tests/data/protocols/protobuf/primitives.proto create mode 100644 tests/data/protocols/protobuf/repeated_enum.proto create mode 100644 tests/data/protocols/protobuf/repeated_primitives.proto diff --git a/tests/data/protocols/protobuf/basic_enum.proto b/tests/data/protocols/protobuf/basic_enum.proto new file mode 100644 index 00000000..50db17f8 --- /dev/null +++ b/tests/data/protocols/protobuf/basic_enum.proto @@ -0,0 +1,13 @@ +// basic_enum.proto + +syntax = "proto3"; + +enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; +} + +message BasicEnum { + Status status = 1; +} diff --git a/tests/data/protocols/protobuf/optional_enum.proto b/tests/data/protocols/protobuf/optional_enum.proto new file mode 100644 index 00000000..4f932d1d --- /dev/null +++ b/tests/data/protocols/protobuf/optional_enum.proto @@ -0,0 +1,13 @@ +// optional_enum.proto + +syntax = "proto3"; + +enum Response { + OK = 0; + FAIL = 1; + TIMEOUT = 2; +} + +message OptionalEnum { + optional Response response = 1; +} diff --git a/tests/data/protocols/protobuf/optional_primitives.proto b/tests/data/protocols/protobuf/optional_primitives.proto new file mode 100644 index 00000000..6089bf92 --- /dev/null +++ b/tests/data/protocols/protobuf/optional_primitives.proto @@ -0,0 +1,21 @@ +// optional_primitives.proto + +syntax = "proto3"; + +message OptionalPrimitives { + optional double optional_double_field = 1; + optional float optional_float_field = 2; + optional int32 optional_int32_field = 3; + optional int64 optional_int64_field = 4; + optional uint32 optional_uint32_field = 5; + optional uint64 optional_uint64_field = 6; + optional sint32 optional_sint32_field = 7; + optional sint64 optional_sint64_field = 8; + optional fixed32 optional_fixed32_field = 9; + optional fixed64 optional_fixed64_field = 10; + optional sfixed32 optional_sfixed32_field = 11; + optional sfixed64 optional_sfixed64_field = 12; + optional bool optional_bool_field = 13; + optional string optional_string_field = 14; + optional bytes optional_bytes_field = 15; +} diff --git a/tests/data/protocols/protobuf/primitives.proto b/tests/data/protocols/protobuf/primitives.proto new file mode 100644 index 00000000..3b104cf3 --- /dev/null +++ b/tests/data/protocols/protobuf/primitives.proto @@ -0,0 +1,21 @@ +// primitives.proto + +syntax = "proto3"; + +message Primitives { + double double_field = 1; + float float_field = 2; + int32 int32_field = 3; + int64 int64_field = 4; + uint32 uint32_field = 5; + uint64 uint64_field = 6; + sint32 sint32_field = 7; + sint64 sint64_field = 8; + fixed32 fixed32_field = 9; + fixed64 fixed64_field = 10; + sfixed32 sfixed32_field = 11; + sfixed64 sfixed64_field = 12; + bool bool_field = 13; + string string_field = 14; + bytes bytes_field = 15; +} diff --git a/tests/data/protocols/protobuf/repeated_enum.proto b/tests/data/protocols/protobuf/repeated_enum.proto new file mode 100644 index 00000000..306c57dd --- /dev/null +++ b/tests/data/protocols/protobuf/repeated_enum.proto @@ -0,0 +1,13 @@ +// repeated_enum.proto + +syntax = "proto3"; + +enum Role { + USER = 0; + ADMIN = 1; + GUEST = 2; +} + +message RepeatedEnum { + repeated Role roles = 1; +} diff --git a/tests/data/protocols/protobuf/repeated_primitives.proto b/tests/data/protocols/protobuf/repeated_primitives.proto new file mode 100644 index 00000000..4454e3ef --- /dev/null +++ b/tests/data/protocols/protobuf/repeated_primitives.proto @@ -0,0 +1,21 @@ +// repeated_primitives.proto + +syntax = "proto3"; + +message RepeatedPrimitives { + repeated double double_field = 1; + repeated float float_field = 2; + repeated int32 int32_field = 3; + repeated int64 int64_field = 4; + repeated uint32 uint32_field = 5; + repeated uint64 uint64_field = 6; + repeated sint32 sint32_field = 7; + repeated sint64 sint64_field = 8; + repeated fixed32 fixed32_field = 9; + repeated fixed64 fixed64_field = 10; + repeated sfixed32 sfixed32_field = 11; + repeated sfixed64 sfixed64_field = 12; + repeated bool bool_field = 13; + repeated string string_field = 14; + repeated bytes bytes_field = 15; +} From cb848e98358b69f8f87f54551e381a34ed295386 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:01:49 +0100 Subject: [PATCH 003/189] tests: add map-related test cases including nested and variant maps --- tests/data/protocols/protobuf/map_enum.proto | 13 +++++++++++ .../data/protocols/protobuf/map_message.proto | 12 ++++++++++ .../data/protocols/protobuf/map_of_map.proto | 11 ++++++++++ .../protobuf/map_repeated_value.proto | 11 ++++++++++ .../protocols/protobuf/map_scalar_keys.proto | 21 ++++++++++++++++++ .../protobuf/map_variant_value.proto | 22 +++++++++++++++++++ .../protobuf/nested_variant_map.proto | 20 +++++++++++++++++ 7 files changed, 110 insertions(+) create mode 100644 tests/data/protocols/protobuf/map_enum.proto create mode 100644 tests/data/protocols/protobuf/map_message.proto create mode 100644 tests/data/protocols/protobuf/map_of_map.proto create mode 100644 tests/data/protocols/protobuf/map_repeated_value.proto create mode 100644 tests/data/protocols/protobuf/map_scalar_keys.proto create mode 100644 tests/data/protocols/protobuf/map_variant_value.proto create mode 100644 tests/data/protocols/protobuf/nested_variant_map.proto diff --git a/tests/data/protocols/protobuf/map_enum.proto b/tests/data/protocols/protobuf/map_enum.proto new file mode 100644 index 00000000..0fcaa6c5 --- /dev/null +++ b/tests/data/protocols/protobuf/map_enum.proto @@ -0,0 +1,13 @@ +// map_enum.proto + +syntax = "proto3"; + +enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; +} + +message MapEnum { + map status_map = 1; +} diff --git a/tests/data/protocols/protobuf/map_message.proto b/tests/data/protocols/protobuf/map_message.proto new file mode 100644 index 00000000..08f629ef --- /dev/null +++ b/tests/data/protocols/protobuf/map_message.proto @@ -0,0 +1,12 @@ +// map_message.proto + +syntax = "proto3"; + +message ValueMessage { + string name = 1; + int32 count = 2; +} + +message MapMessage { + map map_value = 1; +} diff --git a/tests/data/protocols/protobuf/map_of_map.proto b/tests/data/protocols/protobuf/map_of_map.proto new file mode 100644 index 00000000..fe28eb7c --- /dev/null +++ b/tests/data/protocols/protobuf/map_of_map.proto @@ -0,0 +1,11 @@ +// map_of_map.proto + +syntax = "proto3"; + +message MapOfMap { + map outer = 1; + + message InnerMap { + map inner = 1; + } +} diff --git a/tests/data/protocols/protobuf/map_repeated_value.proto b/tests/data/protocols/protobuf/map_repeated_value.proto new file mode 100644 index 00000000..859d7304 --- /dev/null +++ b/tests/data/protocols/protobuf/map_repeated_value.proto @@ -0,0 +1,11 @@ +// map_repeated_value.proto + +syntax = "proto3"; + +message MapRepeatedValue { + map data = 1; + + message RepeatedInts { + repeated int32 values = 1; + } +} diff --git a/tests/data/protocols/protobuf/map_scalar_keys.proto b/tests/data/protocols/protobuf/map_scalar_keys.proto new file mode 100644 index 00000000..18d37172 --- /dev/null +++ b/tests/data/protocols/protobuf/map_scalar_keys.proto @@ -0,0 +1,21 @@ +// map_scalar_keys.proto + +syntax = "proto3"; + +message MapScalarKeys { + // map double_key = 1; + // map float_key = 2; + map int32_key = 3; + map int64_key = 4; + map uint32_key = 5; + map uint64_key = 6; + map sint32_key = 7; + map sint64_key = 8; + map fixed32_key = 9; + map fixed64_key = 10; + map sfixed32_key = 11; + map sfixed64_key = 12; + map bool_key = 13; + map string_key = 14; + // map string_key = 15; +} diff --git a/tests/data/protocols/protobuf/map_variant_value.proto b/tests/data/protocols/protobuf/map_variant_value.proto new file mode 100644 index 00000000..a5bf7616 --- /dev/null +++ b/tests/data/protocols/protobuf/map_variant_value.proto @@ -0,0 +1,22 @@ +// map_variant_value.proto + +syntax = "proto3"; + +enum MyEnum { + ZERO = 0; + ONE = 1; +} + +message MapVariantValue { + map data = 1; + + message Variant { + oneof value { + int32 i = 1; + string s = 2; + MyEnum e = 3; + repeated string r = 4; + map m = 5; + } + } +} diff --git a/tests/data/protocols/protobuf/nested_variant_map.proto b/tests/data/protocols/protobuf/nested_variant_map.proto new file mode 100644 index 00000000..3b78c852 --- /dev/null +++ b/tests/data/protocols/protobuf/nested_variant_map.proto @@ -0,0 +1,20 @@ +// nested_variant_map.proto + +syntax = "proto3"; + +message NestedVariantMap { + map items = 1; + + message Nested { + map sub_items = 1; + + message Variant { + oneof value { + int32 i = 1; + string s = 2; + repeated string r = 3; + map m = 4; + } + } + } +} From 1cc66873dadfa8624d2f9a17686f3499d8ebfaf9 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:02:23 +0100 Subject: [PATCH 004/189] tests: add nested message and oneof-related test cases --- .../protobuf/deeply_nested_message.proto | 19 +++++++++++++++++++ .../protocols/protobuf/empty_message.proto | 5 +++++ .../protocols/protobuf/nested_message.proto | 10 ++++++++++ tests/data/protocols/protobuf/oneof_map.proto | 16 ++++++++++++++++ .../data/protocols/protobuf/oneof_value.proto | 11 +++++++++++ .../protocols/protobuf/simple_message.proto | 9 +++++++++ 6 files changed, 70 insertions(+) create mode 100644 tests/data/protocols/protobuf/deeply_nested_message.proto create mode 100644 tests/data/protocols/protobuf/empty_message.proto create mode 100644 tests/data/protocols/protobuf/nested_message.proto create mode 100644 tests/data/protocols/protobuf/oneof_map.proto create mode 100644 tests/data/protocols/protobuf/oneof_value.proto create mode 100644 tests/data/protocols/protobuf/simple_message.proto diff --git a/tests/data/protocols/protobuf/deeply_nested_message.proto b/tests/data/protocols/protobuf/deeply_nested_message.proto new file mode 100644 index 00000000..99d2c486 --- /dev/null +++ b/tests/data/protocols/protobuf/deeply_nested_message.proto @@ -0,0 +1,19 @@ +// deeply_nested_message.proto + +syntax = "proto3"; + +message DeeplyNestedMessage { + NestedLevel1 nested = 1; + + message NestedLevel1 { + NestedLevel2 nested = 1; + + message NestedLevel2 { + NestedLevel3 nested = 1; + + message NestedLevel3 { + int32 value = 1; + } + } + } +} diff --git a/tests/data/protocols/protobuf/empty_message.proto b/tests/data/protocols/protobuf/empty_message.proto new file mode 100644 index 00000000..563ece07 --- /dev/null +++ b/tests/data/protocols/protobuf/empty_message.proto @@ -0,0 +1,5 @@ +// empty_messages.proto + +syntax = "proto3"; + +message EmptyMessage {} diff --git a/tests/data/protocols/protobuf/nested_message.proto b/tests/data/protocols/protobuf/nested_message.proto new file mode 100644 index 00000000..8fddb981 --- /dev/null +++ b/tests/data/protocols/protobuf/nested_message.proto @@ -0,0 +1,10 @@ +// nested_messages.proto + +syntax = "proto3"; + +message NestedMessage { + message InnerMessage { + string label = 1; + } + InnerMessage nested = 1; +} diff --git a/tests/data/protocols/protobuf/oneof_map.proto b/tests/data/protocols/protobuf/oneof_map.proto new file mode 100644 index 00000000..09993f65 --- /dev/null +++ b/tests/data/protocols/protobuf/oneof_map.proto @@ -0,0 +1,16 @@ +// oneof_map.proto + +message Map1 { + map entries = 1; +} + +message Map2 { + map entries = 1; +} + +message OneofWithMap { + oneof selection { + Map1 map1 = 1; + Map2 map2 = 2; + } +} diff --git a/tests/data/protocols/protobuf/oneof_value.proto b/tests/data/protocols/protobuf/oneof_value.proto new file mode 100644 index 00000000..160d6510 --- /dev/null +++ b/tests/data/protocols/protobuf/oneof_value.proto @@ -0,0 +1,11 @@ +// oneof_value.proto + +syntax = "proto3"; + +message OneofValue { + oneof value { + int32 int_value = 1; + string string_value = 2; + bool bool_value = 3; + } +} diff --git a/tests/data/protocols/protobuf/simple_message.proto b/tests/data/protocols/protobuf/simple_message.proto new file mode 100644 index 00000000..7b16dd2c --- /dev/null +++ b/tests/data/protocols/protobuf/simple_message.proto @@ -0,0 +1,9 @@ +// simple_messages.proto + +syntax = "proto3"; + +message SimpleMessage { + int32 id = 1; + string name = 2; + bool active = 3; +} From a89ab5cb5989163d40009fe290d0d74b9fc892ec Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:02:40 +0100 Subject: [PATCH 005/189] tests: add recursive structure test cases --- tests/data/protocols/protobuf/recursive_map.proto | 6 ++++++ tests/data/protocols/protobuf/recursive_mutual.proto | 11 +++++++++++ tests/data/protocols/protobuf/recursive_node.proto | 8 ++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/data/protocols/protobuf/recursive_map.proto create mode 100644 tests/data/protocols/protobuf/recursive_mutual.proto create mode 100644 tests/data/protocols/protobuf/recursive_node.proto diff --git a/tests/data/protocols/protobuf/recursive_map.proto b/tests/data/protocols/protobuf/recursive_map.proto new file mode 100644 index 00000000..8966e33a --- /dev/null +++ b/tests/data/protocols/protobuf/recursive_map.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message RecursiveMap { + map children = 1; + string value = 2; +} diff --git a/tests/data/protocols/protobuf/recursive_mutual.proto b/tests/data/protocols/protobuf/recursive_mutual.proto new file mode 100644 index 00000000..c5c70eb5 --- /dev/null +++ b/tests/data/protocols/protobuf/recursive_mutual.proto @@ -0,0 +1,11 @@ +// recursive_mutual.proto + +syntax = "proto3"; + +message A { + optional B b = 1; +} + +message B { + optional A a = 1; +} diff --git a/tests/data/protocols/protobuf/recursive_node.proto b/tests/data/protocols/protobuf/recursive_node.proto new file mode 100644 index 00000000..500593e5 --- /dev/null +++ b/tests/data/protocols/protobuf/recursive_node.proto @@ -0,0 +1,8 @@ +// recursive_node.proto + +syntax = "proto3"; + +message RecursiveNode { + string name = 1; + optional RecursiveNode child = 2; +} From 78ae9dc7b4c1b6757263e3d0064c61823726af8d Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:05:03 +0100 Subject: [PATCH 006/189] feat: first protodantic.jinja draft --- .../templates/protocols/protodantic.jinja | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 auto_dev/data/templates/protocols/protodantic.jinja diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja new file mode 100644 index 00000000..1a1c869e --- /dev/null +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -0,0 +1,60 @@ +import struct + +from pydantic import BaseModel, confloat, conint + + +MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes + +min_int32 = -1 << 31 +max_int32 = (1 << 31) - 1 +min_uint32 = 0 +max_uint32 = (1 << 32) - 1 + +min_int64 = -1 << 63 +max_int64 = (1 << 63) - 1 +min_uint64 = 0 +max_uint64 = (1 << 64) - 1 + +min_float32 = struct.unpack('f', struct.pack('I', 0xFF7FFFFF))[0] +max_float32 = struct.unpack('f', struct.pack('I', 0x7F7FFFFF))[0] +min_float64 = struct.unpack('d', struct.pack('Q', 0xFFEFFFFFFFFFFFFF))[0] +max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] +{#-#} +{%- set scalar_map = { + "double": "confloat(ge=min_float64, le=max_float64)", + "float": "confloat(ge=min_float32, le=max_float32)", + "int32": "conint(ge=min_int32, le=max_int32)", + "int64": "conint(ge=min_int64, le=max_int64)", + "uint32": "conint(ge=min_uint32, le=max_uint32)", + "uint64": "conint(ge=min_uint64, le=max_uint64)", + "sint32": "conint(ge=min_int32, le=max_int32)", + "sint64": "conint(ge=min_int64, le=max_int64)", + "fixed32": "conint(ge=min_uint32, le=max_uint32)", + "fixed64": "conint(ge=min_uint64, le=max_uint64)", + "sfixed32": "conint(ge=min_int32, le=max_int32)", + "sfixed64": "conint(ge=min_int64, le=max_int64)", + "bool": "bool", + "string": "str", + "bytes": "bytes", +} %} +{#-#} +{%- for message in result.file_elements %} +{%- if message.__class__.__name__ == "Message" %} +class {{ message.name }}(BaseModel): +{#- First handle nested messages only #} +{%- for element in message.elements if element.__class__.__name__ == "Message" %} + class {{ element.name }}(BaseModel): + {%- for field in element.elements %} + {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} + {%- endfor %} +{%- endfor %} +{#- Now handle top-level fields only #} +{%- for field in message.elements if field.__class__.__name__ == "Field" %} + {%- if field.cardinality == 'REPEATED' %} + {{ field.name }}: list[{{ scalar_map.get(field.type, field.type) }}] + {%- else %} + {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} + {%- endif %} +{%- endfor %} +{% endif %} +{% endfor %} From a44ac4279df0bbf46c3708454c8767bbcb25d805 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:06:46 +0100 Subject: [PATCH 007/189] feat: add proto-schema-parser to pyproject.toml --- poetry.lock | 121 ++++++++++++++++++++++++++++++------------------- pyproject.toml | 1 + 2 files changed, 75 insertions(+), 47 deletions(-) diff --git a/poetry.lock b/poetry.lock index dd984990..bc32ed0a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -114,7 +114,7 @@ propcache = ">=0.2.0" yarl = ">=1.17.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] +speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] [[package]] name = "aiosignal" @@ -204,6 +204,18 @@ files = [ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] +[[package]] +name = "antlr4-python3-runtime" +version = "4.13.2" +description = "ANTLR 4.13.2 runtime for Python 3" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "antlr4_python3_runtime-4.13.2-py3-none-any.whl", hash = "sha256:fe3835eb8d33daece0e799090eda89719dbccee7aa39ef94eed3818cafa5a7e8"}, + {file = "antlr4_python3_runtime-4.13.2.tar.gz", hash = "sha256:909b647e1d2fc2b70180ac586df3933e38919c85f98ccc656a96cd3f25ef3916"}, +] + [[package]] name = "anyio" version = "4.8.0" @@ -225,7 +237,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] trio = ["trio (>=0.26.1)"] [[package]] @@ -280,12 +292,12 @@ files = [ ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "babel" @@ -300,7 +312,7 @@ files = [ ] [package.extras] -dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "backoff" @@ -1168,7 +1180,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" @@ -1216,10 +1228,10 @@ markers = {main = "extra == \"all\"", dev = "sys_platform == \"linux\""} cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] +pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.1)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] @@ -1563,7 +1575,7 @@ pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"p dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] pycryptodome = ["pycryptodome (>=3.6.6,<4)"] -pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] +pysha3 = ["pysha3 (>=1.0.0,<2.0.0) ; python_version < \"3.9\"", "safe-pysha3 (>=1.0.0) ; python_version >= \"3.9\""] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] @@ -1607,10 +1619,10 @@ eth-utils = ">=2.0.0,<3.0.0" [package.extras] coincurve = ["coincurve (>=7.0.0,<16.0.0)"] -dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] +dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] eth-keys = ["eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)"] lint = ["flake8 (==3.0.4)", "mypy (==0.782)"] -test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] +test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] [[package]] name = "eth-rlp" @@ -1711,7 +1723,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "flask" @@ -1895,13 +1907,13 @@ graphql-core = ">=3.2,<3.3" yarl = ">=1.6,<2.0" [package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)"] -all = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] +aiohttp = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\""] +all = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] botocore = ["botocore (>=1.21,<2)"] -dev = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] +dev = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] httpx = ["httpx (>=0.23.1,<1)"] requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)"] -test = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] +test = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.4.0)"] websockets = ["websockets (>=10,<12)"] @@ -2075,7 +2087,7 @@ rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" [package.extras] -brotli = ["brotli", "brotlicffi"] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -2098,7 +2110,7 @@ exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} sortedcontainers = ">=2.1.0,<3.0.0" [package.extras] -all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2)"] +all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] codemods = ["libcst (>=0.3.16)"] crosshair = ["crosshair-tool (>=0.0.78)", "hypothesis-crosshair (>=0.0.18)"] @@ -2112,7 +2124,7 @@ pandas = ["pandas (>=1.1)"] pytest = ["pytest (>=4.6)"] pytz = ["pytz (>=2014.1)"] redis = ["redis (>=3.0.0)"] -zoneinfo = ["tzdata (>=2024.2)"] +zoneinfo = ["tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] [[package]] name = "idna" @@ -2145,12 +2157,12 @@ files = [ zipp = ">=3.20" [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] @@ -2246,7 +2258,7 @@ files = [ [package.extras] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -test = ["portend", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +test = ["portend", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] [[package]] name = "jaraco-functools" @@ -2264,7 +2276,7 @@ files = [ more-itertools = "*" [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] @@ -2286,7 +2298,7 @@ files = [ [package.extras] test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] -trio = ["async_generator", "trio"] +trio = ["async_generator ; python_version == \"3.6\"", "trio"] [[package]] name = "jinja2" @@ -2393,7 +2405,7 @@ pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] completion = ["shtab (>=1.1.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] @@ -2662,7 +2674,7 @@ watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform_system == \"Windows\"", "ghp-import (==1.0)", "importlib-metadata (==4.4) ; python_version < \"3.10\"", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] [[package]] name = "mkdocs-autorefs" @@ -3276,8 +3288,8 @@ cryptography = ">=3.3" pynacl = ">=1.5" [package.extras] -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] +gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] invoke = ["invoke (>=2.0)"] [[package]] @@ -3447,6 +3459,21 @@ files = [ {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, ] +[[package]] +name = "proto-schema-parser" +version = "1.5.0" +description = "A Pure Python Protobuf .proto Parser" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "proto_schema_parser-1.5.0-py3-none-any.whl", hash = "sha256:c1083fd9a15e441651a50fbc56784c91163205077ebb895e4fe69e3054b97fd1"}, + {file = "proto_schema_parser-1.5.0.tar.gz", hash = "sha256:749e2ca7c1ef906b2f1e155af32f2e10b19bdda7069e1a389c3cd61b61fb644d"}, +] + +[package.dependencies] +antlr4-python3-runtime = ">=4.13.0" + [[package]] name = "protobuf" version = "4.24.4" @@ -3656,7 +3683,7 @@ typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" @@ -4403,7 +4430,7 @@ types-PyYAML = "*" urllib3 = ">=1.25.10,<3.0" [package.extras] -tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-requests"] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli ; python_version < \"3.11\"", "tomli-w", "types-requests"] [[package]] name = "rfc3986" @@ -4572,13 +4599,13 @@ files = [ markers = {main = "extra == \"all\""} [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] -core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "six" @@ -4883,7 +4910,7 @@ virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2, [package.extras] docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] -testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] +testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3) ; python_version < \"3.4\"", "psutil (>=5.6.1) ; platform_python_implementation == \"cpython\"", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] [[package]] name = "twine" @@ -4971,7 +4998,7 @@ files = [ ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -5036,7 +5063,7 @@ platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "watchdog" @@ -5128,10 +5155,10 @@ typing-extensions = ">=4.0.1" websockets = ">=10.0.0,<14.0.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0)", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] +dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0) ; python_version < \"3.8\"", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] docs = ["sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)"] ipfs = ["ipfshttpclient (==0.8.0a2)"] -tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1)", "py-geth (>=3.14.0,<4)"] +tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "py-geth (>=3.14.0,<4)"] [[package]] name = "websocket-client" @@ -5353,11 +5380,11 @@ files = [ ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [[package]] @@ -5427,4 +5454,4 @@ all = ["isort", "open-aea", "open-aea-ledger-cosmos", "open-aea-ledger-ethereum" [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.14" -content-hash = "49aa473e1d5865ac4e2f30fe6986061da0576c00094efd71ffea1126ddcd62d5" +content-hash = "6b14c0f46917556a602ef61dd5009068c86766b08313657284473fe77b0a65fe" diff --git a/pyproject.toml b/pyproject.toml index 563abab5..34dae288 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,7 @@ isort = "^5.13.2" openapi-spec-validator = "0.2.8" disutils = "^1.4.32.post2" setuptools = "^75.8.0" +proto-schema-parser = "^1.5.0" [tool.poetry.group.dev.dependencies] From ac02f85cebff1fce77a5bb77fe977f890b320002 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 22 Mar 2025 17:07:13 +0100 Subject: [PATCH 008/189] feat: first protodantic.py draft --- auto_dev/protocols/protodantic.py | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 auto_dev/protocols/protodantic.py diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py new file mode 100644 index 00000000..8aef7490 --- /dev/null +++ b/auto_dev/protocols/protodantic.py @@ -0,0 +1,39 @@ +import re +import subprocess # nosec: B404 +from pathlib import Path +from pprint import pprint +from collections import defaultdict + +from typing import Union +from typing import Generic, TypeVar +from jinja2 import Template, Environment, FileSystemLoader +from pydantic import BaseModel +from pydantic.generics import GenericModel + +from hypothesis import strategies as st + +from proto_schema_parser.parser import Parser +from proto_schema_parser.ast import Message, Enum, OneOf, Field + +from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER + + +def get_repo_root() -> Path: + command = ["git", "rev-parse", "--show-toplevel"] + repo_root = subprocess.check_output(command, stderr=subprocess.STDOUT).strip() # nosec: B603 + return Path(repo_root.decode("utf-8")) + + +path = get_repo_root() / "tests" / "data" / "protocols" / "protobuf" +assert path.exists() +proto_files = {file.name: file for file in path.glob("*.proto")} + +env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa +jinja_template = env.get_template('protocols/protodantic.jinja') + +file = proto_files["primitives.proto"] +content = file.read_text() + +result = Parser().parse(content) +generated_code = jinja_template.render(result=result) +print(generated_code) From 5dd5c53f35798f9bd593894d4be283c22a57bf89 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 12:44:19 +0100 Subject: [PATCH 009/189] feat: protocols/hypothesis.jinja --- .../data/templates/protocols/hypothesis.jinja | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 auto_dev/data/templates/protocols/hypothesis.jinja diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja new file mode 100644 index 00000000..b189e21a --- /dev/null +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -0,0 +1,67 @@ +from hypothesis import given +from hypothesis import strategies as st +import pytest + +from {{ import_path }} import ( + min_int32, + max_int32, + min_uint32, + max_uint32, + min_int64, + max_int64, + min_uint64, + max_uint64, + min_float32, + max_float32, + min_float64, + max_float64, + {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} + {{ message.name }}, + {%- endfor %} +) + +{#- Primitive type mappings to hypothesis strategies #} +{%- set scalar_map = { + "double": "st.floats(min_value=min_float64, max_value=max_float64, allow_nan=False, allow_infinity=False, width=64)", + "float": "st.floats(min_value=min_float32, max_value=max_float32, allow_nan=False, allow_infinity=False, width=32)", + "int32": "st.integers(min_value=min_int32, max_value=max_int32)", + "int64": "st.integers(min_value=min_int64, max_value=max_int64)", + "uint32": "st.integers(min_value=min_uint32, max_value=max_uint32)", + "uint64": "st.integers(min_value=min_uint64, max_value=max_uint64)", + "sint32": "st.integers(min_value=min_int32, max_value=max_int32)", + "sint64": "st.integers(min_value=min_int64, max_value=max_int64)", + "fixed32": "st.integers(min_value=min_uint32, max_value=max_uint32)", + "fixed64": "st.integers(min_value=min_uint64, max_value=max_uint64)", + "sfixed32": "st.integers(min_value=min_int32, max_value=max_int32)", + "sfixed64": "st.integers(min_value=min_int64, max_value=max_int64)", + "bool": "st.booleans()", + "string": "st.text()", + "bytes": "st.binary()", +} %} +{#-#} + +{# Define strategies for each message #} +{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{{ message.name|lower }}_strategy = st.builds( + {{ message.name }}, + {%- for element in message.elements %} + {%- if element.__class__.__name__ == "Message" %} + {{ element.name|lower }}=st.builds( + {{ message.name }}.{{ element.name }}, + {%- for field in element.elements %} + {{ field.name }}={{ scalar_map.get(field.type, field.type) }}, + {%- endfor %} + ), + {%- elif element.__class__.__name__ == "Field" %} + {{ element.name }}={% if element.cardinality == 'REPEATED' %}st.lists({{ scalar_map.get(element.type, element.type) }}){% else %}{{ scalar_map.get(element.type, element.type) }}{% endif %}, + {%- endif %} + {%- endfor %} +) +{%- endfor %} + +{# Define tests for each message #} +{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +@given({{ message.name|lower }}_strategy) +def test_{{ message.name|lower }}({{ message.name|lower }}: {{ message.name }}): + assert isinstance({{ message.name|lower }}, {{ message.name }}) +{%- endfor %} From 7153cb8ecd2df6ea3bfbf4cd39d41cc13b01c244 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 12:46:50 +0100 Subject: [PATCH 010/189] feat: create and write code and tests in protodantic.py --- auto_dev/protocols/protodantic.py | 35 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 8aef7490..122a28b0 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -1,4 +1,5 @@ import re +import os import subprocess # nosec: B404 from pathlib import Path from pprint import pprint @@ -8,7 +9,6 @@ from typing import Generic, TypeVar from jinja2 import Template, Environment, FileSystemLoader from pydantic import BaseModel -from pydantic.generics import GenericModel from hypothesis import strategies as st @@ -24,16 +24,35 @@ def get_repo_root() -> Path: return Path(repo_root.decode("utf-8")) -path = get_repo_root() / "tests" / "data" / "protocols" / "protobuf" +repo_root = get_repo_root() +path = repo_root / "tests" / "data" / "protocols" / "protobuf" assert path.exists() proto_files = {file.name: file for file in path.glob("*.proto")} env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa -jinja_template = env.get_template('protocols/protodantic.jinja') -file = proto_files["primitives.proto"] -content = file.read_text() -result = Parser().parse(content) -generated_code = jinja_template.render(result=result) -print(generated_code) +def compute_import_path(file_path: Path, repo_root: Path) -> str: + if file_path.is_relative_to(repo_root): + relative_path = file_path.relative_to(repo_root) + return ".".join(relative_path.with_suffix('').parts) + return f".{file_path.stem}" + + +def create_pydantic( + proto_inpath: Path, + code_outpath: Path, + test_outpath: Path, +) -> None: + content = proto_inpath.read_text() + + protodantic_template = env.get_template('protocols/protodantic.jinja') + hypothesis_template = env.get_template('protocols/hypothesis.jinja') + + result = Parser().parse(content) + generated_code = protodantic_template.render(result=result) + code_outpath.write_text(generated_code) + + import_path = compute_import_path(code_outpath, test_outpath) + generated_tests = hypothesis_template.render(result=result, import_path=import_path) + test_outpath.write_text(generated_tests) From 537073da62a6a37526497e9187d27f34bed791f9 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 12:53:10 +0100 Subject: [PATCH 011/189] chore: cleanup protodantic.py --- auto_dev/protocols/protodantic.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 122a28b0..2752c42d 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -24,26 +24,22 @@ def get_repo_root() -> Path: return Path(repo_root.decode("utf-8")) -repo_root = get_repo_root() -path = repo_root / "tests" / "data" / "protocols" / "protobuf" -assert path.exists() -proto_files = {file.name: file for file in path.glob("*.proto")} - -env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa - - -def compute_import_path(file_path: Path, repo_root: Path) -> str: +def _compute_import_path(file_path: Path, repo_root: Path) -> str: if file_path.is_relative_to(repo_root): relative_path = file_path.relative_to(repo_root) return ".".join(relative_path.with_suffix('').parts) return f".{file_path.stem}" -def create_pydantic( +def create( proto_inpath: Path, code_outpath: Path, test_outpath: Path, ) -> None: + + repo_root = get_repo_root() + env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa + content = proto_inpath.read_text() protodantic_template = env.get_template('protocols/protodantic.jinja') @@ -53,6 +49,6 @@ def create_pydantic( generated_code = protodantic_template.render(result=result) code_outpath.write_text(generated_code) - import_path = compute_import_path(code_outpath, test_outpath) + import_path = _compute_import_path(code_outpath, test_outpath) generated_tests = hypothesis_template.render(result=result, import_path=import_path) test_outpath.write_text(generated_tests) From ed75c9a2b6341da057551e1b3226e3833a1a1752 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 12:56:21 +0100 Subject: [PATCH 012/189] tests: add integration tests for protodantic.create --- tests/test_protocol.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/test_protocol.py diff --git a/tests/test_protocol.py b/tests/test_protocol.py new file mode 100644 index 00000000..cfbcc34d --- /dev/null +++ b/tests/test_protocol.py @@ -0,0 +1,34 @@ +import os +import tempfile +import subprocess +import functools +from pathlib import Path + +import pytest +from jinja2 import Template, Environment, FileSystemLoader + +from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER +from auto_dev.protocols import protodantic + + +@functools.lru_cache() +def _get_proto_files() -> dict[str, Path]: + repo_root = protodantic.get_repo_root() + path = repo_root / "tests" / "data" / "protocols" / "protobuf" + assert path.exists() + proto_files = {file.name: file for file in path.glob("*.proto")} + return proto_files + + +def test_protodantic(): + proto_files = _get_proto_files() + proto_path = proto_files["primitives.proto"] + + with tempfile.TemporaryDirectory() as tmp_dir: + tmp_path = Path(tmp_dir) + code_out = tmp_path / "models.py" + test_out = tmp_path / "test_models.py" + (tmp_path / "__init__.py").touch() + protodantic.create(proto_path, code_out, test_out) + exit_code = pytest.main([tmp_dir, "-v", "-s", "--tb=long", "-p", "no:warnings"]) + assert exit_code == 0 From f6cb91c79a0cdec94826ccaadb19ef8e7900bb4a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 13:10:44 +0100 Subject: [PATCH 013/189] fix: import path from repo_root --- auto_dev/protocols/protodantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 2752c42d..e2113353 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -49,6 +49,6 @@ def create( generated_code = protodantic_template.render(result=result) code_outpath.write_text(generated_code) - import_path = _compute_import_path(code_outpath, test_outpath) + import_path = _compute_import_path(code_outpath, repo_root) generated_tests = hypothesis_template.render(result=result, import_path=import_path) test_outpath.write_text(generated_tests) From f8e286a245a1edb7d2c2b75189c2a8c079b6cf5d Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 14:44:53 +0100 Subject: [PATCH 014/189] feat: add .encode and .decode to protodantic.jinja --- .../templates/protocols/protodantic.jinja | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 1a1c869e..0911d5ef 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -56,5 +56,32 @@ class {{ message.name }}(BaseModel): {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} {%- endif %} {%- endfor %} + + @staticmethod + def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: + {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + {%- endif %} + {%- endfor %} + + @classmethod + def decode(cls, proto_obj) -> "{{ message.name }}": + {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + decoded_{{ element.name }} = cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {%- else %} + decoded_{{ element.name }} = proto_obj.{{ element.name }} + {%- endif %} + {%- endfor %} + + return cls( + {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {{ element.name }}=decoded_{{ element.name }}{{ "," if not loop.last else "" }} + {%- endfor %} + ) + {% endif %} {% endfor %} From 2d116d08b73d09f73f9acd3a7bb583509d8bae8f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 14:45:33 +0100 Subject: [PATCH 015/189] tests: add .encode and .decode invocation to hypothesis.jinja --- auto_dev/data/templates/protocols/hypothesis.jinja | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index b189e21a..662091d2 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -2,6 +2,8 @@ from hypothesis import given from hypothesis import strategies as st import pytest +from {{ message_path }} import {{ messages_pb2 }} + from {{ import_path }} import ( min_int32, max_int32, @@ -64,4 +66,9 @@ from {{ import_path }} import ( @given({{ message.name|lower }}_strategy) def test_{{ message.name|lower }}({{ message.name|lower }}: {{ message.name }}): assert isinstance({{ message.name|lower }}, {{ message.name }}) + proto_obj = {{ message.name|lower }}_pb2.{{ message.name }}() + {{ message.name|lower }}.encode(proto_obj, {{ message.name|lower }}) + result = {{ message.name }}.decode(proto_obj) + assert id({{ message.name|lower }}) != id(result) + assert {{ message.name|lower }} == result {%- endfor %} From 77bd673c1f41c6c8a184d1e462d68da0824d3a73 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 24 Mar 2025 14:45:54 +0100 Subject: [PATCH 016/189] feat: add messages_pb2 generation via protoc --- auto_dev/protocols/protodantic.py | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index e2113353..7ee05317 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -31,6 +31,12 @@ def _compute_import_path(file_path: Path, repo_root: Path) -> str: return f".{file_path.stem}" +def _remove_runtime_version_code(pb2_content: str) -> str: + pb2_content = re.sub(r'^from\s+google\.protobuf\s+import\s+runtime_version\s+as\s+_runtime_version\s*\n', '', pb2_content, flags=re.MULTILINE) + pb2_content = re.sub(r'_runtime_version\.ValidateProtobufRuntimeVersion\s*\(\s*[^)]*\)\s*\n?', '', pb2_content, flags=re.DOTALL) + return pb2_content + + def create( proto_inpath: Path, code_outpath: Path, @@ -49,6 +55,31 @@ def create( generated_code = protodantic_template.render(result=result) code_outpath.write_text(generated_code) + subprocess.run( + [ + "protoc", + f"--python_out={code_outpath.parent}", + f"--proto_path={proto_inpath.parent}", + proto_inpath.name, + ], + cwd=proto_inpath.parent, + check=True + ) + import_path = _compute_import_path(code_outpath, repo_root) - generated_tests = hypothesis_template.render(result=result, import_path=import_path) + message_path = str(Path(import_path).parent) + + pb2_path = code_outpath.parent / f"{proto_inpath.stem}_pb2.py" + pb2_content = pb2_path.read_text() + pb2_content = _remove_runtime_version_code(pb2_content) + pb2_path.write_text(pb2_content) + + messages_pb2 = pb2_path.with_suffix("").name + + generated_tests = hypothesis_template.render( + result=result, + import_path=import_path, + message_path=message_path, + messages_pb2=messages_pb2, + ) test_outpath.write_text(generated_tests) From e75f51cb52bd7d3ddd5d2de2b77eb16efb46bf66 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 11:41:36 +0100 Subject: [PATCH 017/189] tests: add optional_primitives.proto --- tests/test_protocol.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index cfbcc34d..21e3d261 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -20,9 +20,13 @@ def _get_proto_files() -> dict[str, Path]: return proto_files -def test_protodantic(): - proto_files = _get_proto_files() - proto_path = proto_files["primitives.proto"] +PROTO_FILES = _get_proto_files() + +@pytest.mark.parametrize("proto_path", [ + PROTO_FILES["primitives.proto"], + PROTO_FILES["optional_primitives.proto"], + ]) +def test_protodantic(proto_path: Path): with tempfile.TemporaryDirectory() as tmp_dir: tmp_path = Path(tmp_dir) From c4eba2f6a8d7b851f6b845041c178f7f97f37234 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 11:42:25 +0100 Subject: [PATCH 018/189] feat: update protodantic.jinja and hypothesis.jinja to handle optional values --- .../data/templates/protocols/hypothesis.jinja | 6 +++--- .../templates/protocols/protodantic.jinja | 21 ++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 662091d2..a8867702 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -51,11 +51,11 @@ from {{ import_path }} import ( {{ element.name|lower }}=st.builds( {{ message.name }}.{{ element.name }}, {%- for field in element.elements %} - {{ field.name }}={{ scalar_map.get(field.type, field.type) }}, + {{ field.name }}={% if field.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ scalar_map.get(field.type, field.type) }}){% else %}{{ scalar_map.get(field.type, field.type) }}{% endif %}, {%- endfor %} ), {%- elif element.__class__.__name__ == "Field" %} - {{ element.name }}={% if element.cardinality == 'REPEATED' %}st.lists({{ scalar_map.get(element.type, element.type) }}){% else %}{{ scalar_map.get(element.type, element.type) }}{% endif %}, + {{ element.name }}={% if element.cardinality == 'REPEATED' %}st.lists({{ scalar_map.get(element.type, element.type) }}){% elif element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ scalar_map.get(element.type, element.type) }}){% else %}{{ scalar_map.get(element.type, element.type) }}{% endif %}, {%- endif %} {%- endfor %} ) @@ -66,7 +66,7 @@ from {{ import_path }} import ( @given({{ message.name|lower }}_strategy) def test_{{ message.name|lower }}({{ message.name|lower }}: {{ message.name }}): assert isinstance({{ message.name|lower }}, {{ message.name }}) - proto_obj = {{ message.name|lower }}_pb2.{{ message.name }}() + proto_obj = {{ messages_pb2 }}.{{ message.name }}() {{ message.name|lower }}.encode(proto_obj, {{ message.name|lower }}) result = {{ message.name }}.decode(proto_obj) assert id({{ message.name|lower }}) != id(result) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 0911d5ef..9e17b44b 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -45,7 +45,7 @@ class {{ message.name }}(BaseModel): {%- for element in message.elements if element.__class__.__name__ == "Message" %} class {{ element.name }}(BaseModel): {%- for field in element.elements %} - {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} + {{ field.name }}: {{ scalar_map.get(field.type, field.type) }}{% if field.cardinality == "OPTIONAL" %} | None{% endif %} {%- endfor %} {%- endfor %} {#- Now handle top-level fields only #} @@ -53,7 +53,7 @@ class {{ message.name }}(BaseModel): {%- if field.cardinality == 'REPEATED' %} {{ field.name }}: list[{{ scalar_map.get(field.type, field.type) }}] {%- else %} - {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} + {{ field.name }}: {{ scalar_map.get(field.type, field.type) }}{% if field.cardinality == "OPTIONAL" %} | None{% endif %} {%- endif %} {%- endfor %} @@ -61,20 +61,34 @@ class {{ message.name }}(BaseModel): def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + if {{ message.name|lower }}.{{ element.name }} is not None: + {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {%- else %} + {%- if element.cardinality == "OPTIONAL" %} + if {{ message.name|lower }}.{{ element.name }} is not None: + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- else %} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif %} + {%- endif %} {%- endfor %} @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {%- if element.cardinality == "OPTIONAL" %} + decoded_{{ element.name }} = cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None + {%- else %} decoded_{{ element.name }} = cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {%- endif %} + {%- else %} + {%- if element.cardinality == "OPTIONAL" %} + decoded_{{ element.name }} = proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None {%- else %} decoded_{{ element.name }} = proto_obj.{{ element.name }} {%- endif %} + {%- endif %} {%- endfor %} return cls( @@ -83,5 +97,6 @@ class {{ message.name }}(BaseModel): {%- endfor %} ) + {% endif %} {% endfor %} From 9444d8560b5cc2aac5747ff32ff75584c949fbb8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 11:47:21 +0100 Subject: [PATCH 019/189] refactor: simplify protodantic.jinja .decode and .encode --- .../templates/protocols/protodantic.jinja | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 9e17b44b..f8ab5a30 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -60,34 +60,37 @@ class {{ message.name }}(BaseModel): @staticmethod def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {%- if element.cardinality == "OPTIONAL" %} if {{ message.name|lower }}.{{ element.name }} is not None: + {%- endif %} + {%- if scalar_map.get(element.type) not in scalar_map.values() %} {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) {%- else %} - {%- if element.cardinality == "OPTIONAL" %} - if {{ message.name|lower }}.{{ element.name }} is not None: proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} - {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif %} + {%- if element.cardinality == "OPTIONAL" %} {%- endif %} {%- endfor %} @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if scalar_map.get(element.type) not in scalar_map.values() %} {%- if element.cardinality == "OPTIONAL" %} - decoded_{{ element.name }} = cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None - {%- else %} - decoded_{{ element.name }} = cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) - {%- endif %} - {%- else %} - {%- if element.cardinality == "OPTIONAL" %} - decoded_{{ element.name }} = proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None + decoded_{{ element.name }} = ( + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None + {%- else %} + proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None + {%- endif %} + ) {%- else %} - decoded_{{ element.name }} = proto_obj.{{ element.name }} - {%- endif %} + decoded_{{ element.name }} = ( + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} + {%- endif %} + ) {%- endif %} {%- endfor %} @@ -97,6 +100,5 @@ class {{ message.name }}(BaseModel): {%- endfor %} ) - {% endif %} {% endfor %} From 8cc27f523e34cd9bdaa4f3b98bf76d40b4b6f2b4 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 12:28:51 +0100 Subject: [PATCH 020/189] chore: rename fields repeated_primitives.proto --- .../protobuf/repeated_primitives.proto | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/data/protocols/protobuf/repeated_primitives.proto b/tests/data/protocols/protobuf/repeated_primitives.proto index 4454e3ef..23531f8b 100644 --- a/tests/data/protocols/protobuf/repeated_primitives.proto +++ b/tests/data/protocols/protobuf/repeated_primitives.proto @@ -3,19 +3,19 @@ syntax = "proto3"; message RepeatedPrimitives { - repeated double double_field = 1; - repeated float float_field = 2; - repeated int32 int32_field = 3; - repeated int64 int64_field = 4; - repeated uint32 uint32_field = 5; - repeated uint64 uint64_field = 6; - repeated sint32 sint32_field = 7; - repeated sint64 sint64_field = 8; - repeated fixed32 fixed32_field = 9; - repeated fixed64 fixed64_field = 10; - repeated sfixed32 sfixed32_field = 11; - repeated sfixed64 sfixed64_field = 12; - repeated bool bool_field = 13; - repeated string string_field = 14; - repeated bytes bytes_field = 15; + repeated double repeated_double_field = 1; + repeated float repeated_float_field = 2; + repeated int32 repeated_int32_field = 3; + repeated int64 repeated_int64_field = 4; + repeated uint32 repeated_uint32_field = 5; + repeated uint64 repeated_uint64_field = 6; + repeated sint32 repeated_sint32_field = 7; + repeated sint64 repeated_sint64_field = 8; + repeated fixed32 repeated_fixed32_field = 9; + repeated fixed64 repeated_fixed64_field = 10; + repeated sfixed32 repeated_sfixed32_field = 11; + repeated sfixed64 repeated_sfixed64_field = 12; + repeated bool repeated_bool_field = 13; + repeated string repeated_string_field = 14; + repeated bytes repeated_bytes_field = 15; } From 17599f016aaad7c742ff9daf1a28190d0c71fd14 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 12:29:41 +0100 Subject: [PATCH 021/189] tests: add repeated_primitives.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 21e3d261..73a92439 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -25,6 +25,7 @@ def _get_proto_files() -> dict[str, Path]: @pytest.mark.parametrize("proto_path", [ PROTO_FILES["primitives.proto"], PROTO_FILES["optional_primitives.proto"], + PROTO_FILES["repeated_primitives.proto"], ]) def test_protodantic(proto_path: Path): From c7d848c7246f69c13156ff34c5c89b1bf0b8ec59 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 12:30:14 +0100 Subject: [PATCH 022/189] feat: update protodantic.jinja and hypothesis.jinja to handle repeated values --- .../templates/protocols/protodantic.jinja | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index f8ab5a30..eac237e6 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -60,22 +60,42 @@ class {{ message.name }}(BaseModel): @staticmethod def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.cardinality == "OPTIONAL" %} - if {{ message.name|lower }}.{{ element.name }} is not None: - {%- endif %} + {%- if element.cardinality == "REPEATED" %} {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + for item in {{ message.name|lower }}.{{ element.name }}: + {{ element.type }}.encode(proto_obj.{{ element.name }}.add(), item) {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + proto_obj.{{ element.name }}.extend({{ message.name|lower }}.{{ element.name }}) {%- endif %} - {%- if element.cardinality == "OPTIONAL" %} + {%- elif element.cardinality == "OPTIONAL" %} + if {{ message.name|lower }}.{{ element.name }} is not None: + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + {%- endif %} + {%- else %} + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif %} + {%- endif %} {%- endfor %} @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.cardinality == "OPTIONAL" %} + {%- if element.cardinality == "REPEATED" %} + decoded_{{ element.name }} = [ + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + cls.{{ element.type }}.decode(item) + {%- else %} + item + {%- endif %} + for item in proto_obj.{{ element.name }} + ] + {%- elif element.cardinality == "OPTIONAL" %} decoded_{{ element.name }} = ( {%- if scalar_map.get(element.type) not in scalar_map.values() %} cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None @@ -83,7 +103,7 @@ class {{ message.name }}(BaseModel): proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None {%- endif %} ) - {%- else %} + {%- else %} decoded_{{ element.name }} = ( {%- if scalar_map.get(element.type) not in scalar_map.values() %} cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) @@ -91,7 +111,7 @@ class {{ message.name }}(BaseModel): proto_obj.{{ element.name }} {%- endif %} ) - {%- endif %} + {%- endif %} {%- endfor %} return cls( From 510581d751c8f6d7deec9366ee9ae6832c6ebcf6 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 14:27:23 +0100 Subject: [PATCH 023/189] tests: add basic_enum.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 73a92439..1cb48985 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -26,6 +26,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["primitives.proto"], PROTO_FILES["optional_primitives.proto"], PROTO_FILES["repeated_primitives.proto"], + PROTO_FILES["basic_enum.proto"], ]) def test_protodantic(proto_path: Path): From 00b0b33c33db0cd3525f74795d9f1c52d7a90740 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 14:45:20 +0100 Subject: [PATCH 024/189] feat: update protodantic.jinja and hypothesis.jinja to handle basic enum values --- .../data/templates/protocols/hypothesis.jinja | 19 +++++++++++ .../templates/protocols/protodantic.jinja | 33 +++++++++++++++---- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index a8867702..b3a541ff 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -17,6 +17,9 @@ from {{ import_path }} import ( max_float32, min_float64, max_float64, + {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} + {{ enum.name }}, + {%- endfor %} {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} {{ message.name }}, {%- endfor %} @@ -42,6 +45,17 @@ from {{ import_path }} import ( } %} {#-#} +{# Define a list of enum names #} +{%- set enum_names = [] %} +{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{%- set enum_names = enum_names.append( enum.name ) %} +{%- endfor %} + +{# Define strategies for Enums at the top level #} +{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) +{%- endfor %} + {# Define strategies for each message #} {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} {{ message.name|lower }}_strategy = st.builds( @@ -55,12 +69,17 @@ from {{ import_path }} import ( {%- endfor %} ), {%- elif element.__class__.__name__ == "Field" %} + {%- if element.type in enum_names %} + {{ element.name }}={% if element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ element.type|lower }}_strategy){% else %}{{ element.type|lower }}_strategy{% endif %}, + {%- else %} {{ element.name }}={% if element.cardinality == 'REPEATED' %}st.lists({{ scalar_map.get(element.type, element.type) }}){% elif element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ scalar_map.get(element.type, element.type) }}){% else %}{{ scalar_map.get(element.type, element.type) }}{% endif %}, + {%- endif %} {%- endif %} {%- endfor %} ) {%- endfor %} + {# Define tests for each message #} {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} @given({{ message.name|lower }}_strategy) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index eac237e6..d789c18d 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -1,4 +1,5 @@ import struct +from enum import Enum from pydantic import BaseModel, confloat, conint @@ -38,17 +39,32 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] "bytes": "bytes", } %} {#-#} -{%- for message in result.file_elements %} -{%- if message.__class__.__name__ == "Message" %} + +{# Define a list of enum names #} +{%- set enum_names = [] %} +{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{%- set enum_names = enum_names.append( enum.name ) %} +{%- endfor %} + +{#- First, generate Enums #} +{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +class {{ enum.name }}(Enum): +{%- for value in enum.elements %} + {{ value.name }} = {{ value.number }} +{%- endfor %} +{%- endfor %} + +{#- Now generate message classes #} +{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} class {{ message.name }}(BaseModel): -{#- First handle nested messages only #} +{#- Handle nested messages #} {%- for element in message.elements if element.__class__.__name__ == "Message" %} class {{ element.name }}(BaseModel): {%- for field in element.elements %} {{ field.name }}: {{ scalar_map.get(field.type, field.type) }}{% if field.cardinality == "OPTIONAL" %} | None{% endif %} {%- endfor %} {%- endfor %} -{#- Now handle top-level fields only #} +{#- Handle fields, including enums #} {%- for field in message.elements if field.__class__.__name__ == "Field" %} {%- if field.cardinality == 'REPEATED' %} {{ field.name }}: list[{{ scalar_map.get(field.type, field.type) }}] @@ -60,7 +76,9 @@ class {{ message.name }}(BaseModel): @staticmethod def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.cardinality == "REPEATED" %} + {%- if element.type in enum_names %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- elif element.cardinality == "REPEATED" %} {%- if scalar_map.get(element.type) not in scalar_map.values() %} for item in {{ message.name|lower }}.{{ element.name }}: {{ element.type }}.encode(proto_obj.{{ element.name }}.add(), item) @@ -86,7 +104,9 @@ class {{ message.name }}(BaseModel): @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.cardinality == "REPEATED" %} + {%- if element.type in enum_names %} + decoded_{{ element.name }} = proto_obj.{{ element.name }} + {%- elif element.cardinality == "REPEATED" %} decoded_{{ element.name }} = [ {%- if scalar_map.get(element.type) not in scalar_map.values() %} cls.{{ element.type }}.decode(item) @@ -120,5 +140,4 @@ class {{ message.name }}(BaseModel): {%- endfor %} ) -{% endif %} {% endfor %} From 5d82d19ac956acacaeb73cb11c767dd334118d15 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 15:02:10 +0100 Subject: [PATCH 025/189] tests: add optional_enum.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 1cb48985..4ca003ae 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -27,6 +27,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["optional_primitives.proto"], PROTO_FILES["repeated_primitives.proto"], PROTO_FILES["basic_enum.proto"], + PROTO_FILES["optional_enum.proto"], ]) def test_protodantic(proto_path: Path): From 139340229ef00f2523882c2198cd0e98a0c2cec8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 15:04:17 +0100 Subject: [PATCH 026/189] feat: update protodantic.jinja to handle optional enum values --- auto_dev/data/templates/protocols/protodantic.jinja | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index d789c18d..83edcc5e 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -77,7 +77,12 @@ class {{ message.name }}(BaseModel): def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} + {%- if element.cardinality == "OPTIONAL" %} + if {{ message.name|lower }}.{{ element.name }} is not None: + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- else %} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- endif %} {%- elif element.cardinality == "REPEATED" %} {%- if scalar_map.get(element.type) not in scalar_map.values() %} for item in {{ message.name|lower }}.{{ element.name }}: @@ -105,7 +110,13 @@ class {{ message.name }}(BaseModel): def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} - decoded_{{ element.name }} = proto_obj.{{ element.name }} + {%- if element.cardinality == "OPTIONAL" %} + decoded_{{ element.name }} = ( + (proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None + ) + {%- else %} + decoded_{{ element.name }} = (proto_obj.{{ element.name }}) + {%- endif %} {%- elif element.cardinality == "REPEATED" %} decoded_{{ element.name }} = [ {%- if scalar_map.get(element.type) not in scalar_map.values() %} From 8792f1a49995931ce39a669cab04c30df5874582 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 15:05:16 +0100 Subject: [PATCH 027/189] chore: make enum .decode strict --- auto_dev/data/templates/protocols/hypothesis.jinja | 4 ++++ auto_dev/data/templates/protocols/protodantic.jinja | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index b3a541ff..b1db0f65 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -53,7 +53,11 @@ from {{ import_path }} import ( {# Define strategies for Enums at the top level #} {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{%- if enum.cardinality == "OPTIONAL" %} +{{ enum.name|lower }}_strategy = st.one_of(st.none(), st.sampled_from({{ enum.name }})) +{%- else %} {{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) +{%- endif %} {%- endfor %} {# Define strategies for each message #} diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 83edcc5e..7ad7f816 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -112,10 +112,10 @@ class {{ message.name }}(BaseModel): {%- if element.type in enum_names %} {%- if element.cardinality == "OPTIONAL" %} decoded_{{ element.name }} = ( - (proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None + {{ element.type }}(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None ) {%- else %} - decoded_{{ element.name }} = (proto_obj.{{ element.name }}) + decoded_{{ element.name }} = {{ element.type }}(proto_obj.{{ element.name }}) {%- endif %} {%- elif element.cardinality == "REPEATED" %} decoded_{{ element.name }} = [ From 94352dba2174ca0b82c8bcb3a3b676325f5a1cd9 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 15:30:54 +0100 Subject: [PATCH 028/189] tests: add repeated_enum.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 4ca003ae..e7919fb5 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -28,6 +28,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["repeated_primitives.proto"], PROTO_FILES["basic_enum.proto"], PROTO_FILES["optional_enum.proto"], + PROTO_FILES["repeated_enum.proto"], ]) def test_protodantic(proto_path: Path): From 91547e37ed3fdef02011b6c500927539ca96e68b Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 15:32:08 +0100 Subject: [PATCH 029/189] feat: update protodantic.jinja to handle repeated enum values --- .../data/templates/protocols/protodantic.jinja | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 7ad7f816..00ef4639 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -77,7 +77,10 @@ class {{ message.name }}(BaseModel): def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} - {%- if element.cardinality == "OPTIONAL" %} + {%- if element.cardinality == "REPEATED" %} + for item in {{ message.name|lower }}.{{ element.name }}: + proto_obj.{{ element.name }}.append(item.value) + {%- elif element.cardinality == "OPTIONAL" %} if {{ message.name|lower }}.{{ element.name }} is not None: proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value {%- else %} @@ -110,7 +113,16 @@ class {{ message.name }}(BaseModel): def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} - {%- if element.cardinality == "OPTIONAL" %} + {%- if element.cardinality == "REPEATED" %} + decoded_{{ element.name }} = [ + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}(item) + {%- else %} + item + {%- endif %} + for item in proto_obj.{{ element.name }} + ] + {%- elif element.cardinality == "OPTIONAL" %} decoded_{{ element.name }} = ( {{ element.type }}(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None ) From 0aa9e2e736f63e6b0ea8dfd6c5544ef3a7b5bd2c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 15:32:57 +0100 Subject: [PATCH 030/189] fix: enum strategies based on field cardinality in hypothesis.jinja --- auto_dev/data/templates/protocols/hypothesis.jinja | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index b1db0f65..5a4f9cfa 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -53,11 +53,7 @@ from {{ import_path }} import ( {# Define strategies for Enums at the top level #} {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} -{%- if enum.cardinality == "OPTIONAL" %} -{{ enum.name|lower }}_strategy = st.one_of(st.none(), st.sampled_from({{ enum.name }})) -{%- else %} {{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) -{%- endif %} {%- endfor %} {# Define strategies for each message #} @@ -74,7 +70,7 @@ from {{ import_path }} import ( ), {%- elif element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} - {{ element.name }}={% if element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ element.type|lower }}_strategy){% else %}{{ element.type|lower }}_strategy{% endif %}, + {{ element.name }}={% if element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ element.type|lower }}_strategy){% elif element.cardinality == "REPEATED" %}st.lists({{ element.type|lower }}_strategy){% else %}{{ element.type|lower }}_strategy{% endif %}, {%- else %} {{ element.name }}={% if element.cardinality == 'REPEATED' %}st.lists({{ scalar_map.get(element.type, element.type) }}){% elif element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ scalar_map.get(element.type, element.type) }}){% else %}{{ scalar_map.get(element.type, element.type) }}{% endif %}, {%- endif %} From 20e152ccd62fc18859f3d82a939052c9f30a2fe7 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 21:24:40 +0100 Subject: [PATCH 031/189] refactor: introduce macros in protodantic --- .../templates/protocols/protodantic.jinja | 166 +++++++++++------- 1 file changed, 101 insertions(+), 65 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 00ef4639..0e416002 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -46,6 +46,98 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} +{%- macro encode_scalar(element, message) -%} + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + {%- endif %} +{%- endmacro -%} + +{%- macro decode_scalar(element, message) -%} + {%- set result -%} + decoded_{{ element.name }} = ( + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} + {%- endif %} + ) + {%- endset -%}{{ result }} +{%- endmacro -%} + +{%- macro encode_enum(element, message) -%} + {%- if element.cardinality == "REPEATED" %} + for item in {{ message.name|lower }}.{{ element.name }}: + proto_obj.{{ element.name }}.append(item.value) + {%- elif element.cardinality == "OPTIONAL" %} + if {{ message.name|lower }}.{{ element.name }} is not None: + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- else %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- endif %} +{%- endmacro -%} + +{%- macro decode_enum(element) -%} + {%- if element.cardinality == "REPEATED" %} + decoded_{{ element.name }} = [ + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}(item) + {%- else %} + item + {%- endif %} + for item in proto_obj.{{ element.name }} + ] + {%- elif element.cardinality == "OPTIONAL" %} + decoded_{{ element.name }} = ( + {{ element.type }}(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None + ) + {%- else %} + decoded_{{ element.name }} = {{ element.type }}(proto_obj.{{ element.name }}) + {%- endif %} +{%- endmacro -%} + +{%- macro encode_optional(element, message) -%} + if {{ message.name|lower }}.{{ element.name }} is not None: + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {%- else %} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + {%- endif %} +{%- endmacro -%} + +{%- macro decode_optional(element) -%} + {%- set result -%} + decoded_{{ element.name }} = ( + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None + {%- else %} + proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None + {%- endif %} + ) + {%- endset -%}{{ result }} +{%- endmacro -%} + +{%- macro encode_repeated(element, message) -%} + {%- if scalar_map.get(element.type) not in scalar_map.values() %} + for item in {{ message.name|lower }}.{{ element.name }}: + {{ element.type }}.encode(proto_obj.{{ element.name }}.add(), item) + {%- else %} + proto_obj.{{ element.name }}.extend({{ message.name|lower }}.{{ element.name }}) + {%- endif %} +{%- endmacro -%} + +{%- macro decode_repeated(element) -%} + decoded_{{ element.name }} = [ + {%- if scalar_map.get(element.type) not in scalar_map.values() -%} + cls.{{ element.type }}.decode(item) + {%- else %} + item + {%- endif %} + for item in proto_obj.{{ element.name }} + ] +{%- endmacro -%} + {#- First, generate Enums #} {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} class {{ enum.name }}(Enum): @@ -54,7 +146,7 @@ class {{ enum.name }}(Enum): {%- endfor %} {%- endfor %} -{#- Now generate message classes #} +{#Now generate message classes #} {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} class {{ message.name }}(BaseModel): {#- Handle nested messages #} @@ -77,35 +169,13 @@ class {{ message.name }}(BaseModel): def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} - {%- if element.cardinality == "REPEATED" %} - for item in {{ message.name|lower }}.{{ element.name }}: - proto_obj.{{ element.name }}.append(item.value) - {%- elif element.cardinality == "OPTIONAL" %} - if {{ message.name|lower }}.{{ element.name }} is not None: - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value - {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value - {%- endif %} + {{ encode_enum(element, message) }} {%- elif element.cardinality == "REPEATED" %} - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - for item in {{ message.name|lower }}.{{ element.name }}: - {{ element.type }}.encode(proto_obj.{{ element.name }}.add(), item) - {%- else %} - proto_obj.{{ element.name }}.extend({{ message.name|lower }}.{{ element.name }}) - {%- endif %} + {{ encode_repeated(element, message) }} {%- elif element.cardinality == "OPTIONAL" %} - if {{ message.name|lower }}.{{ element.name }} is not None: - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) - {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} - {%- endif %} + {{ encode_optional(element, message) }} {%- else %} - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) - {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} - {%- endif %} + {{ encode_scalar(element, message) }} {%- endif %} {%- endfor %} @@ -113,47 +183,13 @@ class {{ message.name }}(BaseModel): def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} {%- if element.type in enum_names %} - {%- if element.cardinality == "REPEATED" %} - decoded_{{ element.name }} = [ - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}(item) - {%- else %} - item - {%- endif %} - for item in proto_obj.{{ element.name }} - ] - {%- elif element.cardinality == "OPTIONAL" %} - decoded_{{ element.name }} = ( - {{ element.type }}(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None - ) - {%- else %} - decoded_{{ element.name }} = {{ element.type }}(proto_obj.{{ element.name }}) - {%- endif %} + {{ decode_enum(element) }} {%- elif element.cardinality == "REPEATED" %} - decoded_{{ element.name }} = [ - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - cls.{{ element.type }}.decode(item) - {%- else %} - item - {%- endif %} - for item in proto_obj.{{ element.name }} - ] + {{ decode_repeated(element) }} {%- elif element.cardinality == "OPTIONAL" %} - decoded_{{ element.name }} = ( - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None - {%- else %} - proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None - {%- endif %} - ) + {{ decode_optional(element) }} {%- else %} - decoded_{{ element.name }} = ( - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) - {%- else %} - proto_obj.{{ element.name }} - {%- endif %} - ) + {{ decode_scalar(element) }} {%- endif %} {%- endfor %} From f1c9455fd0a68539e3908e5f8e08fd0f280e1c87 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 21:27:08 +0100 Subject: [PATCH 032/189] refactor: reuse scalar marcros in optional macros --- .../templates/protocols/protodantic.jinja | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 0e416002..9881656c 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -46,16 +46,16 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} -{%- macro encode_scalar(element, message) -%} +{%- macro encode_scalar(element, message, indent_level = 1) -%} + {%- set indent = ' ' * indent_level -%} {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {{ indent }}{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + {{ indent }}proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif %} {%- endmacro -%} {%- macro decode_scalar(element, message) -%} - {%- set result -%} decoded_{{ element.name }} = ( {%- if scalar_map.get(element.type) not in scalar_map.values() %} cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) @@ -63,7 +63,6 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] proto_obj.{{ element.name }} {%- endif %} ) - {%- endset -%}{{ result }} {%- endmacro -%} {%- macro encode_enum(element, message) -%} @@ -99,23 +98,11 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- macro encode_optional(element, message) -%} if {{ message.name|lower }}.{{ element.name }} is not None: - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) - {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} - {%- endif %} + {{ encode_scalar(element, message, indent_level=2) }} {%- endmacro -%} {%- macro decode_optional(element) -%} - {%- set result -%} - decoded_{{ element.name }} = ( - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None - {%- else %} - proto_obj.{{ element.name }} if proto_obj.HasField("{{ element.name }}") else None - {%- endif %} - ) - {%- endset -%}{{ result }} + decoded_{{ element.name }} = {{ decode_scalar(element, message) }} if proto_obj.HasField("{{ element.name }}") else None {%- endmacro -%} {%- macro encode_repeated(element, message) -%} From cd73f8caef9d51881580d4bfb06279350d6cc2ad Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 25 Mar 2025 21:36:32 +0100 Subject: [PATCH 033/189] refactor: simplify repeated macros --- .../data/templates/protocols/protodantic.jinja | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 9881656c..e7a7c9d4 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -106,23 +106,11 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- endmacro -%} {%- macro encode_repeated(element, message) -%} - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - for item in {{ message.name|lower }}.{{ element.name }}: - {{ element.type }}.encode(proto_obj.{{ element.name }}.add(), item) - {%- else %} - proto_obj.{{ element.name }}.extend({{ message.name|lower }}.{{ element.name }}) - {%- endif %} + proto_obj.{{ element.name }}.extend({{ message.name|lower }}.{{ element.name }}) {%- endmacro -%} {%- macro decode_repeated(element) -%} - decoded_{{ element.name }} = [ - {%- if scalar_map.get(element.type) not in scalar_map.values() -%} - cls.{{ element.type }}.decode(item) - {%- else %} - item - {%- endif %} - for item in proto_obj.{{ element.name }} - ] + decoded_{{ element.name }} = [item for item in proto_obj.{{ element.name }}] {%- endmacro -%} {#- First, generate Enums #} From 8ca18d08539337e46efe4ad037feedfab1ac7f50 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 16:07:45 +0100 Subject: [PATCH 034/189] refactor: unify scalar and enum handling in macros --- .../templates/protocols/protodantic.jinja | 98 +++++++------------ 1 file changed, 36 insertions(+), 62 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index e7a7c9d4..8212c408 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -46,71 +46,49 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} -{%- macro encode_scalar(element, message, indent_level = 1) -%} - {%- set indent = ' ' * indent_level -%} - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ indent }}{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) - {%- else %} - {{ indent }}proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} - {%- endif %} +{%- macro encode_scalar(element, message) -%} + {%- if element.type in enum_names -%} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- else -%} + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} + {%- endif -%} {%- endmacro -%} {%- macro decode_scalar(element, message) -%} - decoded_{{ element.name }} = ( - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - cls.{{ element.type }}.decode(proto_obj.{{ element.name }}) - {%- else %} - proto_obj.{{ element.name }} - {%- endif %} - ) -{%- endmacro -%} - -{%- macro encode_enum(element, message) -%} - {%- if element.cardinality == "REPEATED" %} - for item in {{ message.name|lower }}.{{ element.name }}: - proto_obj.{{ element.name }}.append(item.value) - {%- elif element.cardinality == "OPTIONAL" %} - if {{ message.name|lower }}.{{ element.name }} is not None: - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value - {%- else %} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value - {%- endif %} + decoded_{{ element.name }} = {%if element.type in enum_names -%} + {{ element.type }}(proto_obj.{{ element.name }}) + {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} + {{ element.type }}.decode(proto_obj.{{ element.name }}) + {%- else -%} + proto_obj.{{ element.name }} + {%- endif -%} {%- endmacro -%} -{%- macro decode_enum(element) -%} - {%- if element.cardinality == "REPEATED" %} - decoded_{{ element.name }} = [ - {%- if scalar_map.get(element.type) not in scalar_map.values() %} - {{ element.type }}(item) - {%- else %} - item - {%- endif %} - for item in proto_obj.{{ element.name }} - ] - {%- elif element.cardinality == "OPTIONAL" %} - decoded_{{ element.name }} = ( - {{ element.type }}(proto_obj.{{ element.name }}) if proto_obj.HasField("{{ element.name }}") else None - ) - {%- else %} - decoded_{{ element.name }} = {{ element.type }}(proto_obj.{{ element.name }}) - {%- endif %} -{%- endmacro -%} - -{%- macro encode_optional(element, message) -%} +{%- macro encode_optional(element, message, indent_level=2) -%} + {%- set indent = ' ' * indent_level -%} if {{ message.name|lower }}.{{ element.name }} is not None: - {{ encode_scalar(element, message, indent_level=2) }} + {{ indent }}{{ encode_scalar(element, message) }} {%- endmacro -%} -{%- macro decode_optional(element) -%} - decoded_{{ element.name }} = {{ decode_scalar(element, message) }} if proto_obj.HasField("{{ element.name }}") else None +{%- macro decode_optional(element, message) -%} + {{ decode_scalar(element, message) }} if proto_obj.HasField("{{ element.name }}") else None {%- endmacro -%} {%- macro encode_repeated(element, message) -%} - proto_obj.{{ element.name }}.extend({{ message.name|lower }}.{{ element.name }}) + proto_obj.{{ element.name }}.extend({%- if element.type in enum_names -%} + item.value + {%- else -%} + item + {%- endif -%} + {{ ' ' }}for item in {{ message.name|lower }}.{{ element.name }}) {%- endmacro -%} -{%- macro decode_repeated(element) -%} - decoded_{{ element.name }} = [item for item in proto_obj.{{ element.name }}] +{%- macro decode_repeated(element, message) -%} + {%- if element.type in enum_names -%} + decoded_{{ element.name }} = [{{ element.type }}(item) for item in proto_obj.{{ element.name }}] + {%- else -%} + decoded_{{ element.name }} = list(proto_obj.{{ element.name }}) + {%- endif -%} {%- endmacro -%} {#- First, generate Enums #} @@ -143,9 +121,7 @@ class {{ message.name }}(BaseModel): @staticmethod def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.type in enum_names %} - {{ encode_enum(element, message) }} - {%- elif element.cardinality == "REPEATED" %} + {%- if element.cardinality == "REPEATED" %} {{ encode_repeated(element, message) }} {%- elif element.cardinality == "OPTIONAL" %} {{ encode_optional(element, message) }} @@ -157,14 +133,12 @@ class {{ message.name }}(BaseModel): @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.type in enum_names %} - {{ decode_enum(element) }} - {%- elif element.cardinality == "REPEATED" %} - {{ decode_repeated(element) }} + {%- if element.cardinality == "REPEATED" %} + {{ decode_repeated(element, message) }} {%- elif element.cardinality == "OPTIONAL" %} - {{ decode_optional(element) }} + {{ decode_optional(element, message) }} {%- else %} - {{ decode_scalar(element) }} + {{ decode_scalar(element, message) }} {%- endif %} {%- endfor %} @@ -174,4 +148,4 @@ class {{ message.name }}(BaseModel): {%- endfor %} ) -{% endfor %} +{% endfor %} \ No newline at end of file From d2bbba5e83c5bb1292fcb000ec9107afe4203d21 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 20:02:54 +0100 Subject: [PATCH 035/189] tests: add simple_message.proto --- tests/test_protocol.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index e7919fb5..5775850b 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -29,7 +29,8 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["basic_enum.proto"], PROTO_FILES["optional_enum.proto"], PROTO_FILES["repeated_enum.proto"], - ]) + PROTO_FILES["simple_message.proto"], +]) def test_protodantic(proto_path: Path): with tempfile.TemporaryDirectory() as tmp_dir: From 9574ce50a6186eb28dc551df6192f9275b2596c7 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 20:03:05 +0100 Subject: [PATCH 036/189] tests: add nested_message.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 5775850b..c8d61cf2 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -30,6 +30,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["optional_enum.proto"], PROTO_FILES["repeated_enum.proto"], PROTO_FILES["simple_message.proto"], + PROTO_FILES["nested_message.proto"], ]) def test_protodantic(proto_path: Path): From 972efc2ac4704cbce73c82f249b8a0795a1b089a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 20:04:27 +0100 Subject: [PATCH 037/189] feat: introduce render_message macro for nested messages in protodantic.jinja --- .../templates/protocols/protodantic.jinja | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 8212c408..9b5aa570 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -99,24 +99,24 @@ class {{ enum.name }}(Enum): {%- endfor %} {%- endfor %} -{#Now generate message classes #} -{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{%- macro render_message(message, indent_level = 1) %} class {{ message.name }}(BaseModel): -{#- Handle nested messages #} -{%- for element in message.elements if element.__class__.__name__ == "Message" %} - class {{ element.name }}(BaseModel): - {%- for field in element.elements %} - {{ field.name }}: {{ scalar_map.get(field.type, field.type) }}{% if field.cardinality == "OPTIONAL" %} | None{% endif %} - {%- endfor %} -{%- endfor %} -{#- Handle fields, including enums #} -{%- for field in message.elements if field.__class__.__name__ == "Field" %} - {%- if field.cardinality == 'REPEATED' %} + {%- set indent = ' ' * indent_level -%} + {# Handle nested messages recursively #} + {%- for nested in message.elements if nested.__class__.__name__ == "Message" %} + {{indent}}{{ render_message(nested, indent_level + 1) | indent(indent_level * 4) }} + {% endfor %} + + {#- Handle fields of the message -#} + {%- for field in message.elements if field.__class__.__name__ == "Field" %} + {%- if field.cardinality == "REPEATED" %} {{ field.name }}: list[{{ scalar_map.get(field.type, field.type) }}] + {%- elif field.cardinality == "OPTIONAL" %} + {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} | None {%- else %} - {{ field.name }}: {{ scalar_map.get(field.type, field.type) }}{% if field.cardinality == "OPTIONAL" %} | None{% endif %} + {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} {%- endif %} -{%- endfor %} + {%- endfor %} @staticmethod def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: @@ -148,4 +148,9 @@ class {{ message.name }}(BaseModel): {%- endfor %} ) -{% endfor %} \ No newline at end of file +{%- endmacro %} + +{# Now generate all message classes #} +{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{{ render_message(message) }} +{%- endfor %} From fc8bad0d2ed7068ab898a909dec7e0c5c2c4119b Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 20:19:28 +0100 Subject: [PATCH 038/189] feat: introduce macros for nested messages in hypothesis.jinja --- .../data/templates/protocols/hypothesis.jinja | 66 +++++++++++++------ 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 5a4f9cfa..e533b799 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -51,34 +51,60 @@ from {{ import_path }} import ( {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} -{# Define strategies for Enums at the top level #} -{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} -{{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) +{%- macro scalar_strategy(field) -%} + {%- if field.type in enum_names -%} + {{ field.type|lower }}_strategy + {%- else -%} + {{ scalar_map.get(field.type, field.type) }} + {%- endif -%} +{%- endmacro -%} + +{%- macro optional_strategy(field) -%} + st.one_of(st.none(), {{ scalar_strategy(field) }}) +{%- endmacro -%} + +{%- macro repeated_strategy(field) -%} + st.lists({{ scalar_strategy(field) }}) +{%- endmacro -%} + +{%- macro message_strategy(message, prefix="") -%} +{#- Build a list of nested message names in this message -#} +{%- set nested_names = [] -%} +{%- for m in message.elements if m.__class__.__name__ == "Message" %} +{%- set enum_names = nested_names.append(m.name) %} +{%- endfor %} + +{#- Generate strategies for inner messages first -#} +{%- for element in message.elements if element.__class__.__name__ == "Message" %} +{{ message_strategy(element, message.name + ".") }} {%- endfor %} -{# Define strategies for each message #} -{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} {{ message.name|lower }}_strategy = st.builds( - {{ message.name }}, - {%- for element in message.elements %} - {%- if element.__class__.__name__ == "Message" %} - {{ element.name|lower }}=st.builds( - {{ message.name }}.{{ element.name }}, - {%- for field in element.elements %} - {{ field.name }}={% if field.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ scalar_map.get(field.type, field.type) }}){% else %}{{ scalar_map.get(field.type, field.type) }}{% endif %}, - {%- endfor %} - ), - {%- elif element.__class__.__name__ == "Field" %} - {%- if element.type in enum_names %} - {{ element.name }}={% if element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ element.type|lower }}_strategy){% elif element.cardinality == "REPEATED" %}st.lists({{ element.type|lower }}_strategy){% else %}{{ element.type|lower }}_strategy{% endif %}, - {%- else %} - {{ element.name }}={% if element.cardinality == 'REPEATED' %}st.lists({{ scalar_map.get(element.type, element.type) }}){% elif element.cardinality == "OPTIONAL" %}st.one_of(st.none(), {{ scalar_map.get(element.type, element.type) }}){% else %}{{ scalar_map.get(element.type, element.type) }}{% endif %}, - {%- endif %} + {{ prefix }}{{ message.name }}, + {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {%- if element.type in nested_names %} + {{ element.name }}={{ element.type|lower }}_strategy, + {%- elif element.cardinality == "OPTIONAL" %} + {{ element.name }}={{ optional_strategy(element) }}, + {%- elif element.cardinality == "REPEATED" %} + {{ element.name }}={{ repeated_strategy(element) }}, + {%- else %} + {{ element.name }}={{ scalar_strategy(element) }}, {%- endif %} {%- endfor %} ) +{%- endmacro %} + + +{# Define strategies for Enums at the top level #} +{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) {%- endfor %} +{# Define strategies for each message #} +{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{{ message_strategy(message) }} +{%- endfor %} {# Define tests for each message #} {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} From abd9d5d5e3cf4a5c7c3bb7d4d136baa94a20cd47 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 20:20:04 +0100 Subject: [PATCH 039/189] fix: encoding / decoding logic for nested messages in protodantic.jinja --- auto_dev/data/templates/protocols/protodantic.jinja | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 9b5aa570..224256bb 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -49,6 +49,8 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- macro encode_scalar(element, message) -%} {%- if element.type in enum_names -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value + {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} + {{ message.name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif -%} @@ -58,7 +60,7 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] decoded_{{ element.name }} = {%if element.type in enum_names -%} {{ element.type }}(proto_obj.{{ element.name }}) {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ element.type }}.decode(proto_obj.{{ element.name }}) + {{ message.name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} {%- endif -%} From e4ba0507b835684cbc7c82bd312e7f21bfe8f6b8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 21:16:15 +0100 Subject: [PATCH 040/189] fix: nested message indentation protodantic.jinja --- auto_dev/data/templates/protocols/protodantic.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 224256bb..11e15068 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -101,12 +101,12 @@ class {{ enum.name }}(Enum): {%- endfor %} {%- endfor %} -{%- macro render_message(message, indent_level = 1) %} +{%- macro render_message(message, indent_level=1, prefix="") %} class {{ message.name }}(BaseModel): {%- set indent = ' ' * indent_level -%} {# Handle nested messages recursively #} {%- for nested in message.elements if nested.__class__.__name__ == "Message" %} - {{indent}}{{ render_message(nested, indent_level + 1) | indent(indent_level * 4) }} + {{indent}}{{ render_message(nested, indent_level + 1) | indent(4, true) }} {% endfor %} {#- Handle fields of the message -#} From 8d73eea956347aebe7ef4c957e60ce074b5cc6d0 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 21:17:16 +0100 Subject: [PATCH 041/189] fix: fully qualified path for nested messages in hypothesis.jinja --- auto_dev/data/templates/protocols/hypothesis.jinja | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index e533b799..0187d006 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -76,7 +76,7 @@ from {{ import_path }} import ( {#- Generate strategies for inner messages first -#} {%- for element in message.elements if element.__class__.__name__ == "Message" %} -{{ message_strategy(element, message.name + ".") }} +{{ message_strategy(element, prefix + message.name + ".") }} {%- endfor %} {{ message.name|lower }}_strategy = st.builds( @@ -95,7 +95,6 @@ from {{ import_path }} import ( ) {%- endmacro %} - {# Define strategies for Enums at the top level #} {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} {{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) From c51aef9d283280b1e5c2065f990786db453f3092 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 21:28:31 +0100 Subject: [PATCH 042/189] tests: add deeply_nested_message.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index c8d61cf2..2bed4812 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -31,6 +31,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["repeated_enum.proto"], PROTO_FILES["simple_message.proto"], PROTO_FILES["nested_message.proto"], + PROTO_FILES["deeply_nested_message.proto"], ]) def test_protodantic(proto_path: Path): From f428269d34bce70f7a735892f82e7b07df51b1ce Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 21:28:54 +0100 Subject: [PATCH 043/189] fix: fully qualified path for nested messages in protodantic.jinja --- .../templates/protocols/protodantic.jinja | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 11e15068..189c0570 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -46,21 +46,21 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} -{%- macro encode_scalar(element, message) -%} +{%- macro encode_scalar(element, message, full_name) -%} {%- if element.type in enum_names -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ message.name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {{ full_name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif -%} {%- endmacro -%} -{%- macro decode_scalar(element, message) -%} - decoded_{{ element.name }} = {%if element.type in enum_names -%} +{%- macro decode_scalar(element, message, full_name) -%} + decoded_{{ element.name }} = {% if element.type in enum_names -%} {{ element.type }}(proto_obj.{{ element.name }}) {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ message.name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {{ full_name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} {%- endif -%} @@ -101,12 +101,13 @@ class {{ enum.name }}(Enum): {%- endfor %} {%- endfor %} -{%- macro render_message(message, indent_level=1, prefix="") %} +{%- macro render_message(message, prefix="", indent_level=1) %} class {{ message.name }}(BaseModel): {%- set indent = ' ' * indent_level -%} + {%- set prefix = (prefix + '.' if prefix else '') + message.name -%} {# Handle nested messages recursively #} {%- for nested in message.elements if nested.__class__.__name__ == "Message" %} - {{indent}}{{ render_message(nested, indent_level + 1) | indent(4, true) }} + {{indent}}{{ render_message(nested, prefix, indent_level + 1) | indent(4, true) }} {% endfor %} {#- Handle fields of the message -#} @@ -128,7 +129,7 @@ class {{ message.name }}(BaseModel): {%- elif element.cardinality == "OPTIONAL" %} {{ encode_optional(element, message) }} {%- else %} - {{ encode_scalar(element, message) }} + {{ encode_scalar(element, message, prefix) }} {%- endif %} {%- endfor %} @@ -140,7 +141,7 @@ class {{ message.name }}(BaseModel): {%- elif element.cardinality == "OPTIONAL" %} {{ decode_optional(element, message) }} {%- else %} - {{ decode_scalar(element, message) }} + {{ decode_scalar(element, message, prefix) }} {%- endif %} {%- endfor %} From d772c55c0a181d2b9fb672a6866e4497e19ae326 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 21:56:08 +0100 Subject: [PATCH 044/189] tests: add regualr, optional and repeated fields to nested_message.proto --- tests/data/protocols/protobuf/nested_message.proto | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/data/protocols/protobuf/nested_message.proto b/tests/data/protocols/protobuf/nested_message.proto index 8fddb981..f020a33a 100644 --- a/tests/data/protocols/protobuf/nested_message.proto +++ b/tests/data/protocols/protobuf/nested_message.proto @@ -4,7 +4,12 @@ syntax = "proto3"; message NestedMessage { message InnerMessage { - string label = 1; + string inner_label = 1; + optional string optional_inner_label = 2; + repeated string repeated_inner_label = 3; } InnerMessage nested = 1; + string label = 2; + optional string optional_label = 3; + repeated string repeated_label = 4; } From 000fcb9090ee87dbad2aa6a45a5c3fb98fccb1dd Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 21:56:29 +0100 Subject: [PATCH 045/189] tests: add regualr, optional and repeated fields to deeply_nested_message.proto --- .../protocols/protobuf/deeply_nested_message.proto | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/data/protocols/protobuf/deeply_nested_message.proto b/tests/data/protocols/protobuf/deeply_nested_message.proto index 99d2c486..dfa61b9d 100644 --- a/tests/data/protocols/protobuf/deeply_nested_message.proto +++ b/tests/data/protocols/protobuf/deeply_nested_message.proto @@ -4,15 +4,26 @@ syntax = "proto3"; message DeeplyNestedMessage { NestedLevel1 nested = 1; + int32 int32_field = 2; + optional int32 optional_int32_field = 3; + repeated int32 repeated_int32_field = 4; message NestedLevel1 { NestedLevel2 nested = 1; + int32 level1_int32_field = 2; + optional int32 level1_optional_int32_field = 3; + repeated int32 level1_repeated_int32_field = 4; message NestedLevel2 { NestedLevel3 nested = 1; + int32 level2_int32_field = 2; + optional int32 level2_optional_int32_field = 3; + repeated int32 level2_repeated_int32_field = 4; message NestedLevel3 { - int32 value = 1; + int32 level3_int32_field = 2; + optional int32 level3_optional_int32_field = 3; + repeated int32 level3_repeated_int32_field = 4; } } } From b96459f84a6bb007d7871cd44bd9547d776252b1 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 23:43:39 +0100 Subject: [PATCH 046/189] tests: add oneof_value.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 2bed4812..66b7ff22 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -32,6 +32,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["simple_message.proto"], PROTO_FILES["nested_message.proto"], PROTO_FILES["deeply_nested_message.proto"], + PROTO_FILES["oneof_value.proto"], ]) def test_protodantic(proto_path: Path): From 72f7d7dbdfaf7ecce9b5fdb5a2cf6f25cdf9d457 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 27 Mar 2025 23:45:27 +0100 Subject: [PATCH 047/189] feat: add oneof to protodantic.jinja --- .../templates/protocols/protodantic.jinja | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 189c0570..7c19a2a0 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -39,6 +39,24 @@ max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] "bytes": "bytes", } %} {#-#} +{%- set type_map = { + "double": "float", + "float": "float", + "int32": "int", + "int64": "int", + "uint32": "int", + "uint64": "int", + "sint32": "int", + "sint64": "int", + "fixed32": "int", + "fixed64": "int", + "sfixed32": "int", + "sfixed64": "int", + "bool": "bool", + "string": "str", + "bytes": "bytes", +} %} +{#-#} {# Define a list of enum names #} {%- set enum_names = [] %} @@ -110,6 +128,13 @@ class {{ message.name }}(BaseModel): {{indent}}{{ render_message(nested, prefix, indent_level + 1) | indent(4, true) }} {% endfor %} + {%- for oneof in message.elements if oneof.__class__.__name__ == "OneOf" %} + {{ oneof.name }}: + {%- for field in oneof.elements -%} + {{ ' ' }}{{ scalar_map.get(field.type, field.type) }}{{ " | " if not loop.last else "" }} + {%- endfor %} + {%- endfor %} + {#- Handle fields of the message -#} {%- for field in message.elements if field.__class__.__name__ == "Field" %} {%- if field.cardinality == "REPEATED" %} @@ -133,6 +158,13 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} + {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} + {%- for field in element.elements %} + if isinstance({{ message.name|lower }}.{{ element.name }}, {{ type_map.get(field.type, field.type) }}): + proto_obj.{{ field.name }} = {{ message.name|lower }}.{{ element.name }} + {%- endfor %} + {%- endfor %} + @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": {%- for element in message.elements if element.__class__.__name__ == "Field" %} @@ -145,10 +177,21 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} + {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} + oneof_data = {} + {%- for field in element.elements %} + if proto_obj.HasField("{{ field.name }}"): + oneof_data["{{ element.name }}"] = proto_obj.{{ field.name }} + {%- endfor %} + {%- endfor %} + return cls( {%- for element in message.elements if element.__class__.__name__ == "Field" %} {{ element.name }}=decoded_{{ element.name }}{{ "," if not loop.last else "" }} {%- endfor %} + {%- if message.elements | selectattr("__class__.__name__", "equalto", "OneOf") | list | length > 0 -%} + **oneof_data + {%- endif -%} ) {%- endmacro %} From 5fe8c5994f3bdae346d2028de5227b430053a904 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 16:33:17 +0100 Subject: [PATCH 048/189] feat: custom primitives.jinja --- .../data/templates/protocols/primitives.jinja | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 auto_dev/data/templates/protocols/primitives.jinja diff --git a/auto_dev/data/templates/protocols/primitives.jinja b/auto_dev/data/templates/protocols/primitives.jinja new file mode 100644 index 00000000..b314f319 --- /dev/null +++ b/auto_dev/data/templates/protocols/primitives.jinja @@ -0,0 +1,158 @@ +import struct +from abc import ABC, abstractmethod +from pydantic_core import SchemaValidator, core_schema + + +min_int32 = -1 << 31 +max_int32 = (1 << 31) - 1 +min_uint32 = 0 +max_uint32 = (1 << 32) - 1 + +min_int64 = -1 << 63 +max_int64 = (1 << 63) - 1 +min_uint64 = 0 +max_uint64 = (1 << 64) - 1 + +min_float32 = struct.unpack('f', struct.pack('I', 0xFF7FFFFF))[0] +max_float32 = struct.unpack('f', struct.pack('I', 0x7F7FFFFF))[0] +min_float64 = struct.unpack('d', struct.pack('Q', 0xFFEFFFFFFFFFFFFF))[0] +max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] + + +class BaseConstrainedFloat(float, ABC): + """Base class for constrained float types.""" + + @classmethod + @abstractmethod + def min(cls) -> float: + raise NotImplementedError(f"{cls.__name__}.min() is not implemented.") + + @classmethod + @abstractmethod + def max(cls) -> float: + raise NotImplementedError(f"{cls.__name__}.max() is not implemented.") + + def __new__(cls, value: float = 0.0, *args, **kwargs) -> "BaseConstrainedFloat": + schema = core_schema.float_schema(strict=True, ge=cls.min(), le=cls.max()) + validator = SchemaValidator(schema) + validated_value = validator.validate_python(value) + return super().__new__(cls, validated_value) + + def __new__(cls, value: float = 0.0, *args, **kwargs) -> "BaseConstrainedInt": + schema = core_schema.float_schema(strict=True, ge=cls.min(), le=cls.max()) + validator = SchemaValidator(schema) + validated_value = validator.validate_python(value) + return super().__new__(cls, validated_value) + + @classmethod + def __get_pydantic_core_schema__(cls, source, handler): + schema = core_schema.float_schema(strict=True, ge=cls.min(), le=cls.max()) + return core_schema.no_info_wrap_validator_function(cls, schema) + + +class BaseConstrainedInt(int, ABC): + """Base class for constrained integer types.""" + @classmethod + @abstractmethod + def min(cls) -> int: + raise NotImplementedError(f"{cls.__name__}.min() is not implemented.") + + @classmethod + @abstractmethod + def max(cls) -> int: + raise NotImplementedError(f"{cls.__name__}.max() is not implemented.") + + def __new__(cls, value: int = 0, *args, **kwargs) -> "BaseConstrainedInt": + schema = core_schema.int_schema(strict=True, ge=cls.min(), le=cls.max()) + validator = SchemaValidator(schema) + validated_value = validator.validate_python(value) + return super().__new__(cls, validated_value) + + @classmethod + def __get_pydantic_core_schema__(cls, source, handler): + schema = core_schema.int_schema(strict=True, ge=cls.min(), le=cls.max()) + return core_schema.no_info_wrap_validator_function(cls, schema) + + +class Double(BaseConstrainedFloat): + @classmethod + def min(cls): return min_float64 + @classmethod + def max(cls): return max_float64 + + +class Float(BaseConstrainedFloat): + @classmethod + def min(cls): return min_float32 + @classmethod + def max(cls): return max_float32 + + +class Int32(BaseConstrainedInt): + @classmethod + def min(cls): return min_int32 + @classmethod + def max(cls): return max_int32 + + +class Int64(BaseConstrainedInt): + @classmethod + def min(cls): return min_int64 + @classmethod + def max(cls): return max_int64 + + +class UInt32(BaseConstrainedInt): + @classmethod + def min(cls): return min_uint32 + @classmethod + def max(cls): return max_uint32 + + +class UInt64(BaseConstrainedInt): + @classmethod + def min(cls): return min_uint64 + @classmethod + def max(cls): return max_uint64 + + +class SInt32(BaseConstrainedInt): + @classmethod + def min(cls): return min_int32 + @classmethod + def max(cls): return max_int32 + + +class SInt64(BaseConstrainedInt): + @classmethod + def min(cls): return min_int64 + @classmethod + def max(cls): return max_int64 + + +class Fixed32(BaseConstrainedInt): + @classmethod + def min(cls): return min_uint32 + @classmethod + def max(cls): return max_uint32 + + +class Fixed64(BaseConstrainedInt): + @classmethod + def min(cls): return min_uint64 + @classmethod + def max(cls): return max_uint64 + + +class SFixed32(BaseConstrainedInt): + @classmethod + def min(cls): return min_int32 + @classmethod + def max(cls): return max_int32 + + +class SFixed64(BaseConstrainedInt): + @classmethod + def min(cls): return min_int64 + @classmethod + def max(cls): return max_int64 From a1a63f0e57e15f6438147f43a13e3f4bebcff301 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 16:38:12 +0100 Subject: [PATCH 049/189] feat: remove type_map and replace values in scalar_map with custom primitives in protodantic.jinja --- .../templates/protocols/protodantic.jinja | 69 ++++++------------- 1 file changed, 22 insertions(+), 47 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 7c19a2a0..6080ddd9 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -1,57 +1,32 @@ -import struct from enum import Enum -from pydantic import BaseModel, confloat, conint +from pydantic import BaseModel +from {{ primitives_import_path }} import ( + {%- for primitive in float_primitives %} + {{ primitive }}, + {%- endfor %} + {%- for primitive in integer_primitives %} + {{ primitive }}, + {%- endfor %} +) MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes -min_int32 = -1 << 31 -max_int32 = (1 << 31) - 1 -min_uint32 = 0 -max_uint32 = (1 << 32) - 1 - -min_int64 = -1 << 63 -max_int64 = (1 << 63) - 1 -min_uint64 = 0 -max_uint64 = (1 << 64) - 1 - -min_float32 = struct.unpack('f', struct.pack('I', 0xFF7FFFFF))[0] -max_float32 = struct.unpack('f', struct.pack('I', 0x7F7FFFFF))[0] -min_float64 = struct.unpack('d', struct.pack('Q', 0xFFEFFFFFFFFFFFFF))[0] -max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] {#-#} {%- set scalar_map = { - "double": "confloat(ge=min_float64, le=max_float64)", - "float": "confloat(ge=min_float32, le=max_float32)", - "int32": "conint(ge=min_int32, le=max_int32)", - "int64": "conint(ge=min_int64, le=max_int64)", - "uint32": "conint(ge=min_uint32, le=max_uint32)", - "uint64": "conint(ge=min_uint64, le=max_uint64)", - "sint32": "conint(ge=min_int32, le=max_int32)", - "sint64": "conint(ge=min_int64, le=max_int64)", - "fixed32": "conint(ge=min_uint32, le=max_uint32)", - "fixed64": "conint(ge=min_uint64, le=max_uint64)", - "sfixed32": "conint(ge=min_int32, le=max_int32)", - "sfixed64": "conint(ge=min_int64, le=max_int64)", - "bool": "bool", - "string": "str", - "bytes": "bytes", -} %} -{#-#} -{%- set type_map = { - "double": "float", - "float": "float", - "int32": "int", - "int64": "int", - "uint32": "int", - "uint64": "int", - "sint32": "int", - "sint64": "int", - "fixed32": "int", - "fixed64": "int", - "sfixed32": "int", - "sfixed64": "int", + "double": "Double", + "float": "Float", + "int32": "Int32", + "int64": "Int64", + "uint32": "UInt32", + "uint64": "UInt64", + "sint32": "SInt32", + "sint64": "SInt64", + "fixed32": "Fixed32", + "fixed64": "Fixed64", + "sfixed32": "SFixed32", + "sfixed64": "SFixed64", "bool": "bool", "string": "str", "bytes": "bytes", @@ -160,7 +135,7 @@ class {{ message.name }}(BaseModel): {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} {%- for field in element.elements %} - if isinstance({{ message.name|lower }}.{{ element.name }}, {{ type_map.get(field.type, field.type) }}): + if isinstance({{ message.name|lower }}.{{ element.name }}, {{ scalar_map.get(field.type, field.type) }}): proto_obj.{{ field.name }} = {{ message.name|lower }}.{{ element.name }} {%- endfor %} {%- endfor %} From da6cf0100734dd7277be5d91b3affdb98dd649fc Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 16:39:25 +0100 Subject: [PATCH 050/189] tests: add all primitive types to oneof_value.proto --- .../data/protocols/protobuf/oneof_value.proto | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/data/protocols/protobuf/oneof_value.proto b/tests/data/protocols/protobuf/oneof_value.proto index 160d6510..a3d8f3aa 100644 --- a/tests/data/protocols/protobuf/oneof_value.proto +++ b/tests/data/protocols/protobuf/oneof_value.proto @@ -4,8 +4,20 @@ syntax = "proto3"; message OneofValue { oneof value { - int32 int_value = 1; - string string_value = 2; - bool bool_value = 3; + double double_field = 1; + float float_field = 2; + int32 int32_field = 3; + int64 int64_field = 4; + uint32 uint32_field = 5; + uint64 uint64_field = 6; + sint32 sint32_field = 7; + sint64 sint64_field = 8; + fixed32 fixed32_field = 9; + fixed64 fixed64_field = 10; + sfixed32 sfixed32_field = 11; + sfixed64 sfixed64_field = 12; + bool bool_field = 13; + string string_field = 14; + bytes bytes_field = 15; } } From 31314d7f3011e46c4ce26db808be28d2a6ebe407 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 16:40:17 +0100 Subject: [PATCH 051/189] feat: replace values in scalar_map with st.builds of custom primitives in hypothesis.jinja --- .../data/templates/protocols/hypothesis.jinja | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 0187d006..d7ee1614 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -4,19 +4,15 @@ import pytest from {{ message_path }} import {{ messages_pb2 }} -from {{ import_path }} import ( - min_int32, - max_int32, - min_uint32, - max_uint32, - min_int64, - max_int64, - min_uint64, - max_uint64, - min_float32, - max_float32, - min_float64, - max_float64, +from {{ primitives_import_path }} import ( + {%- for primitive in float_primitives %} + {{ primitive }}, + {%- endfor %} + {%- for primitive in integer_primitives %} + {{ primitive }}, + {%- endfor %} +) +from {{ models_import_path }} import ( {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} {{ enum.name }}, {%- endfor %} @@ -25,20 +21,36 @@ from {{ import_path }} import ( {%- endfor %} ) +{# Register strategies for floating-point types #} +{%- for primitive in float_primitives %} +st.register_type_strategy( + {{ primitive }}, + st.floats(min_value={{ primitive }}.min(), max_value={{ primitive }}.max(), allow_nan=False, allow_infinity=False).map({{ primitive }}) +) +{%- endfor %} +{# Register strategies for integer types #} +{%- for primitive in integer_primitives %} +st.register_type_strategy( + {{ primitive }}, + st.integers(min_value={{ primitive }}.min(), max_value={{ primitive }}.max()).map({{ primitive }}) +) +{%- endfor %} + + {#- Primitive type mappings to hypothesis strategies #} {%- set scalar_map = { - "double": "st.floats(min_value=min_float64, max_value=max_float64, allow_nan=False, allow_infinity=False, width=64)", - "float": "st.floats(min_value=min_float32, max_value=max_float32, allow_nan=False, allow_infinity=False, width=32)", - "int32": "st.integers(min_value=min_int32, max_value=max_int32)", - "int64": "st.integers(min_value=min_int64, max_value=max_int64)", - "uint32": "st.integers(min_value=min_uint32, max_value=max_uint32)", - "uint64": "st.integers(min_value=min_uint64, max_value=max_uint64)", - "sint32": "st.integers(min_value=min_int32, max_value=max_int32)", - "sint64": "st.integers(min_value=min_int64, max_value=max_int64)", - "fixed32": "st.integers(min_value=min_uint32, max_value=max_uint32)", - "fixed64": "st.integers(min_value=min_uint64, max_value=max_uint64)", - "sfixed32": "st.integers(min_value=min_int32, max_value=max_int32)", - "sfixed64": "st.integers(min_value=min_int64, max_value=max_int64)", + "double": "st.builds(Double)", + "float": "st.builds(Float)", + "int32": "st.builds(Int32)", + "int64": "st.builds(Int64)", + "uint32": "st.builds(UInt32)", + "uint64": "st.builds(UInt64)", + "sint32": "st.builds(SInt32)", + "sint64": "st.builds(SInt64)", + "fixed32": "st.builds(Fixed32)", + "fixed64": "st.builds(Fixed64)", + "sfixed32": "st.builds(SFixed32)", + "sfixed64": "st.builds(SFixed64)", "bool": "st.booleans()", "string": "st.text()", "bytes": "st.binary()", From 416eb80bea2f8bf469d606ff645440b0d607d238 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 16:41:06 +0100 Subject: [PATCH 052/189] feat: create primitives.py and pass necesary rendering variables in protodantic.py --- auto_dev/protocols/protodantic.py | 52 ++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 7ee05317..e8fac4a2 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -2,22 +2,32 @@ import os import subprocess # nosec: B404 from pathlib import Path -from pprint import pprint -from collections import defaultdict -from typing import Union -from typing import Generic, TypeVar from jinja2 import Template, Environment, FileSystemLoader -from pydantic import BaseModel - -from hypothesis import strategies as st - from proto_schema_parser.parser import Parser -from proto_schema_parser.ast import Message, Enum, OneOf, Field from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER +FLOAT_PRIMITIVES = [ + "Double", + "Float", +] + +INTEGER_PRIMITIVES = [ + "Int32", + "Int64", + "UInt32", + "UInt64", + "SInt32", + "SInt64", + "Fixed32", + "Fixed64", + "SFixed32", + "SFixed64", +] + + def get_repo_root() -> Path: command = ["git", "rev-parse", "--show-toplevel"] repo_root = subprocess.check_output(command, stderr=subprocess.STDOUT).strip() # nosec: B603 @@ -48,11 +58,22 @@ def create( content = proto_inpath.read_text() + primitives_template = env.get_template('protocols/primitives.jinja') protodantic_template = env.get_template('protocols/protodantic.jinja') hypothesis_template = env.get_template('protocols/hypothesis.jinja') + primitives = primitives_template.render() + primitives_outpath = code_outpath.parent / "primitives.py" + primitives_outpath.write_text(primitives) + primitives_import_path = _compute_import_path(primitives_outpath, repo_root) + result = Parser().parse(content) - generated_code = protodantic_template.render(result=result) + code = generated_code = protodantic_template.render( + result=result, + float_primitives=FLOAT_PRIMITIVES, + integer_primitives=INTEGER_PRIMITIVES, + primitives_import_path=primitives_import_path, + ) code_outpath.write_text(generated_code) subprocess.run( @@ -66,8 +87,8 @@ def create( check=True ) - import_path = _compute_import_path(code_outpath, repo_root) - message_path = str(Path(import_path).parent) + models_import_path = _compute_import_path(code_outpath, repo_root) + message_path = str(Path(models_import_path).parent) pb2_path = code_outpath.parent / f"{proto_inpath.stem}_pb2.py" pb2_content = pb2_path.read_text() @@ -76,9 +97,12 @@ def create( messages_pb2 = pb2_path.with_suffix("").name - generated_tests = hypothesis_template.render( + tests = generated_tests = hypothesis_template.render( result=result, - import_path=import_path, + float_primitives=FLOAT_PRIMITIVES, + integer_primitives=INTEGER_PRIMITIVES, + primitives_import_path=primitives_import_path, + models_import_path=models_import_path, message_path=message_path, messages_pb2=messages_pb2, ) From aa8e21b4fe5aecf45179d7f7cd4d267e875ea724 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 17:02:31 +0100 Subject: [PATCH 053/189] chore: cleanup jinja templates --- auto_dev/data/templates/protocols/hypothesis.jinja | 1 - auto_dev/data/templates/protocols/primitives.jinja | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index d7ee1614..da8e2052 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -1,6 +1,5 @@ from hypothesis import given from hypothesis import strategies as st -import pytest from {{ message_path }} import {{ messages_pb2 }} diff --git a/auto_dev/data/templates/protocols/primitives.jinja b/auto_dev/data/templates/protocols/primitives.jinja index b314f319..c4f715ea 100644 --- a/auto_dev/data/templates/protocols/primitives.jinja +++ b/auto_dev/data/templates/protocols/primitives.jinja @@ -32,12 +32,6 @@ class BaseConstrainedFloat(float, ABC): def max(cls) -> float: raise NotImplementedError(f"{cls.__name__}.max() is not implemented.") - def __new__(cls, value: float = 0.0, *args, **kwargs) -> "BaseConstrainedFloat": - schema = core_schema.float_schema(strict=True, ge=cls.min(), le=cls.max()) - validator = SchemaValidator(schema) - validated_value = validator.validate_python(value) - return super().__new__(cls, validated_value) - def __new__(cls, value: float = 0.0, *args, **kwargs) -> "BaseConstrainedInt": schema = core_schema.float_schema(strict=True, ge=cls.min(), le=cls.max()) validator = SchemaValidator(schema) @@ -52,6 +46,7 @@ class BaseConstrainedFloat(float, ABC): class BaseConstrainedInt(int, ABC): """Base class for constrained integer types.""" + @classmethod @abstractmethod def min(cls) -> int: From daa5f087c7b3f3632c16e61c093eae0caff231b2 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 17:54:19 +0100 Subject: [PATCH 054/189] refactor: read in custom primitive classes from generated code --- .../data/templates/protocols/hypothesis.jinja | 12 ++-- .../templates/protocols/protodantic.jinja | 4 +- auto_dev/protocols/protodantic.py | 58 +++++++++++-------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index da8e2052..14657026 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -5,10 +5,10 @@ from {{ message_path }} import {{ messages_pb2 }} from {{ primitives_import_path }} import ( {%- for primitive in float_primitives %} - {{ primitive }}, + {{ primitive.__name__ }}, {%- endfor %} {%- for primitive in integer_primitives %} - {{ primitive }}, + {{ primitive.__name__ }}, {%- endfor %} ) from {{ models_import_path }} import ( @@ -23,15 +23,15 @@ from {{ models_import_path }} import ( {# Register strategies for floating-point types #} {%- for primitive in float_primitives %} st.register_type_strategy( - {{ primitive }}, - st.floats(min_value={{ primitive }}.min(), max_value={{ primitive }}.max(), allow_nan=False, allow_infinity=False).map({{ primitive }}) + {{ primitive.__name__ }}, + st.floats(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max(), allow_nan=False, allow_infinity=False).map({{ primitive.__name__ }}) ) {%- endfor %} {# Register strategies for integer types #} {%- for primitive in integer_primitives %} st.register_type_strategy( - {{ primitive }}, - st.integers(min_value={{ primitive }}.min(), max_value={{ primitive }}.max()).map({{ primitive }}) + {{ primitive.__name__ }}, + st.integers(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max()).map({{ primitive.__name__ }}) ) {%- endfor %} diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 6080ddd9..44117dbf 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -4,10 +4,10 @@ from pydantic import BaseModel from {{ primitives_import_path }} import ( {%- for primitive in float_primitives %} - {{ primitive }}, + {{ primitive.__name__ }}, {%- endfor %} {%- for primitive in integer_primitives %} - {{ primitive }}, + {{ primitive.__name__ }}, {%- endfor %} ) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index e8fac4a2..2dd2871c 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -1,33 +1,18 @@ import re import os +import sys +import inspect import subprocess # nosec: B404 +import importlib.util from pathlib import Path +from types import ModuleType -from jinja2 import Template, Environment, FileSystemLoader from proto_schema_parser.parser import Parser +from jinja2 import Template, Environment, FileSystemLoader from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER -FLOAT_PRIMITIVES = [ - "Double", - "Float", -] - -INTEGER_PRIMITIVES = [ - "Int32", - "Int64", - "UInt32", - "UInt64", - "SInt32", - "SInt64", - "Fixed32", - "Fixed64", - "SFixed32", - "SFixed64", -] - - def get_repo_root() -> Path: command = ["git", "rev-parse", "--show-toplevel"] repo_root = subprocess.check_output(command, stderr=subprocess.STDOUT).strip() # nosec: B603 @@ -47,6 +32,23 @@ def _remove_runtime_version_code(pb2_content: str) -> str: return pb2_content +def _dynamic_import(module_outpath: Path) -> ModuleType: + module_name = module_outpath.stem + spec = importlib.util.spec_from_file_location(module_name, module_outpath) + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) + return module + + +def _get_locally_defined_classes(module: ModuleType) -> list[type]: + + def locally_defined(obj): + return isinstance(obj, type) and obj.__module__ == module.__name__ + + return list(filter(locally_defined, vars(module).values())) + + def create( proto_inpath: Path, code_outpath: Path, @@ -65,13 +67,19 @@ def create( primitives = primitives_template.render() primitives_outpath = code_outpath.parent / "primitives.py" primitives_outpath.write_text(primitives) + primitives_module = _dynamic_import(primitives_outpath) primitives_import_path = _compute_import_path(primitives_outpath, repo_root) + custom_primitives = _get_locally_defined_classes(primitives_module) + primitives = [cls for cls in custom_primitives if not inspect.isabstract(cls)] + float_primitives = [p for p in primitives if issubclass(p, float)] + integer_primitives = [p for p in primitives if issubclass(p, int)] + result = Parser().parse(content) code = generated_code = protodantic_template.render( result=result, - float_primitives=FLOAT_PRIMITIVES, - integer_primitives=INTEGER_PRIMITIVES, + float_primitives=float_primitives, + integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, ) code_outpath.write_text(generated_code) @@ -99,11 +107,11 @@ def create( tests = generated_tests = hypothesis_template.render( result=result, - float_primitives=FLOAT_PRIMITIVES, - integer_primitives=INTEGER_PRIMITIVES, + float_primitives=float_primitives, + integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, models_import_path=models_import_path, message_path=message_path, messages_pb2=messages_pb2, ) - test_outpath.write_text(generated_tests) + test_outpath.write_text(generated_tests) \ No newline at end of file From 3323c769b421abeebe10df8ba54a383ceb48aa78 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 18:13:11 +0100 Subject: [PATCH 055/189] refactor: gemerate scalar_map dynamically from custom primitive classes --- .../data/templates/protocols/hypothesis.jinja | 27 ++++-------------- .../templates/protocols/protodantic.jinja | 28 +++++-------------- auto_dev/protocols/protodantic.py | 2 +- 3 files changed, 14 insertions(+), 43 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 14657026..02931112 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -35,26 +35,11 @@ st.register_type_strategy( ) {%- endfor %} - -{#- Primitive type mappings to hypothesis strategies #} -{%- set scalar_map = { - "double": "st.builds(Double)", - "float": "st.builds(Float)", - "int32": "st.builds(Int32)", - "int64": "st.builds(Int64)", - "uint32": "st.builds(UInt32)", - "uint64": "st.builds(UInt64)", - "sint32": "st.builds(SInt32)", - "sint64": "st.builds(SInt64)", - "fixed32": "st.builds(Fixed32)", - "fixed64": "st.builds(Fixed64)", - "sfixed32": "st.builds(SFixed32)", - "sfixed64": "st.builds(SFixed64)", - "bool": "st.booleans()", - "string": "st.text()", - "bytes": "st.binary()", -} %} -{#-#} +{#- Define a map of scalars -#} +{%- set scalar_map = {"bool": "bool", "string": "str", "bytes": "bytes"} %} +{%- for primitive in integer_primitives + float_primitives %} + {%- set scalar_map = scalar_map.update({primitive.__name__.lower(): primitive.__name__}) %} +{%- endfor %} {# Define a list of enum names #} {%- set enum_names = [] %} @@ -66,7 +51,7 @@ st.register_type_strategy( {%- if field.type in enum_names -%} {{ field.type|lower }}_strategy {%- else -%} - {{ scalar_map.get(field.type, field.type) }} + st.builds({{ scalar_map.get(field.type, field.type) }}) {%- endif -%} {%- endmacro -%} diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 44117dbf..04c2687c 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -13,27 +13,13 @@ from {{ primitives_import_path }} import ( MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes -{#-#} -{%- set scalar_map = { - "double": "Double", - "float": "Float", - "int32": "Int32", - "int64": "Int64", - "uint32": "UInt32", - "uint64": "UInt64", - "sint32": "SInt32", - "sint64": "SInt64", - "fixed32": "Fixed32", - "fixed64": "Fixed64", - "sfixed32": "SFixed32", - "sfixed64": "SFixed64", - "bool": "bool", - "string": "str", - "bytes": "bytes", -} %} -{#-#} - -{# Define a list of enum names #} +{#- Define a map of scalars -#} +{%- set scalar_map = {"bool": "bool", "string": "str", "bytes": "bytes"} %} +{%- for primitive in integer_primitives + float_primitives %} + {%- set scalar_map = scalar_map.update({primitive.__name__.lower(): primitive.__name__}) %} +{%- endfor %} + +{#- Define a list of enum names -#} {%- set enum_names = [] %} {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} {%- set enum_names = enum_names.append( enum.name ) %} diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 2dd2871c..4f783d9e 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -114,4 +114,4 @@ def create( message_path=message_path, messages_pb2=messages_pb2, ) - test_outpath.write_text(generated_tests) \ No newline at end of file + test_outpath.write_text(generated_tests) From 5dec49720c8af1f0899c752045a8076b49d81641 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 19:59:45 +0100 Subject: [PATCH 056/189] tests: add all primitive types to map_primitive_values.proto --- .../protobuf/map_primitive_values.proto | 21 +++++++++++++++++++ tests/test_protocol.py | 7 +++---- 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 tests/data/protocols/protobuf/map_primitive_values.proto diff --git a/tests/data/protocols/protobuf/map_primitive_values.proto b/tests/data/protocols/protobuf/map_primitive_values.proto new file mode 100644 index 00000000..742fd221 --- /dev/null +++ b/tests/data/protocols/protobuf/map_primitive_values.proto @@ -0,0 +1,21 @@ +// map_primitive_values.proto + +syntax = "proto3"; + +message PrimitiveValuesMap { + map int32_map = 1; + map int64_map = 2; + map uint32_map = 3; + map uint64_map = 4; + map sint32_map = 5; + map sint64_map = 6; + map fixed32_map = 7; + map fixed64_map = 8; + map sfixed32_map = 9; + map sfixed64_map = 10; + map float_map = 11; + map double_map = 12; + map bool_map = 13; + map string_map = 14; + map bytes_map = 15; +} diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 66b7ff22..f5cad518 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1,13 +1,10 @@ -import os import tempfile -import subprocess import functools from pathlib import Path import pytest from jinja2 import Template, Environment, FileSystemLoader -from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER from auto_dev.protocols import protodantic @@ -22,6 +19,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES = _get_proto_files() + @pytest.mark.parametrize("proto_path", [ PROTO_FILES["primitives.proto"], PROTO_FILES["optional_primitives.proto"], @@ -33,6 +31,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["nested_message.proto"], PROTO_FILES["deeply_nested_message.proto"], PROTO_FILES["oneof_value.proto"], + PROTO_FILES["map_primitive_values.proto"], ]) def test_protodantic(proto_path: Path): @@ -42,5 +41,5 @@ def test_protodantic(proto_path: Path): test_out = tmp_path / "test_models.py" (tmp_path / "__init__.py").touch() protodantic.create(proto_path, code_out, test_out) - exit_code = pytest.main([tmp_dir, "-v", "-s", "--tb=long", "-p", "no:warnings"]) + exit_code = pytest.main([tmp_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) assert exit_code == 0 From 267107e4c6a4a2156983f35c29fd3c958976949a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 20:06:39 +0100 Subject: [PATCH 057/189] feat: add map to protodantic.jinja --- .../templates/protocols/protodantic.jinja | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 04c2687c..07c2a971 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -72,6 +72,16 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- endif -%} {%- endmacro -%} +{%- macro encode_map_field(map_field, message) -%} + for key, val in {{ message.name|lower }}.{{ map_field.name }}.items(): + proto_obj.{{ map_field.name }}[key] = val +{%- endmacro %} + +{%- macro decode_map_field(map_field) -%} + {%- set value_type_str = scalar_map.get(map_field.value_type) -%} + {{ "decoded_" ~ map_field.name }} = dict(proto_obj.{{ map_field.name }}) +{%- endmacro %} + {#- First, generate Enums #} {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} class {{ enum.name }}(Enum): @@ -84,11 +94,16 @@ class {{ enum.name }}(Enum): class {{ message.name }}(BaseModel): {%- set indent = ' ' * indent_level -%} {%- set prefix = (prefix + '.' if prefix else '') + message.name -%} - {# Handle nested messages recursively #} + + {#- Handle nested messages recursively -#} {%- for nested in message.elements if nested.__class__.__name__ == "Message" %} {{indent}}{{ render_message(nested, prefix, indent_level + 1) | indent(4, true) }} {% endfor %} + {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} + {{ map_field.name }}: dict[{{ scalar_map.get(map_field.key_type) }}, {{ scalar_map.get(map_field.value_type, map_field.value_type) }}] + {%- endfor %} + {%- for oneof in message.elements if oneof.__class__.__name__ == "OneOf" %} {{ oneof.name }}: {%- for field in oneof.elements -%} @@ -119,6 +134,10 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} + {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} + {{ encode_map_field(map_field, message) }} + {%- endfor %} + {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} {%- for field in element.elements %} if isinstance({{ message.name|lower }}.{{ element.name }}, {{ scalar_map.get(field.type, field.type) }}): @@ -138,6 +157,10 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} + {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} + {{ decode_map_field(map_field) }} + {%- endfor %} + {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} oneof_data = {} {%- for field in element.elements %} @@ -150,6 +173,9 @@ class {{ message.name }}(BaseModel): {%- for element in message.elements if element.__class__.__name__ == "Field" %} {{ element.name }}=decoded_{{ element.name }}{{ "," if not loop.last else "" }} {%- endfor %} + {%- for element in message.elements if element.__class__.__name__ == "MapField" %} + {{ element.name }}=decoded_{{ element.name }}{{ "," if not loop.last else "" }} + {%- endfor %} {%- if message.elements | selectattr("__class__.__name__", "equalto", "OneOf") | list | length > 0 -%} **oneof_data {%- endif -%} From 124a9dcc8f754e0431543e38f583697d20caa64a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 20:07:31 +0100 Subject: [PATCH 058/189] fix: add to_float32 in custom Float for managing precision in primitives.jinja --- auto_dev/data/templates/protocols/primitives.jinja | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/auto_dev/data/templates/protocols/primitives.jinja b/auto_dev/data/templates/protocols/primitives.jinja index c4f715ea..858e4cd2 100644 --- a/auto_dev/data/templates/protocols/primitives.jinja +++ b/auto_dev/data/templates/protocols/primitives.jinja @@ -19,6 +19,11 @@ min_float64 = struct.unpack('d', struct.pack('Q', 0xFFEFFFFFFFFFFFFF))[0] max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] +def to_float32(value: float) -> float: + """Pack the value as a 32-bit float then unpack it.""" + return struct.unpack("f", struct.pack("f", value))[0] + + class BaseConstrainedFloat(float, ABC): """Base class for constrained float types.""" @@ -82,6 +87,9 @@ class Float(BaseConstrainedFloat): @classmethod def max(cls): return max_float32 + def __new__(cls, value: float = 0.0, *args, **kwargs) -> "Float": + return super().__new__(cls, to_float32(float(value))) + class Int32(BaseConstrainedInt): @classmethod From 0dc4d1c021ef87fe6dd7e99986ee98ddc63ed970 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 22:43:45 +0100 Subject: [PATCH 059/189] tests: add all primitive types to map_optional_primitive_values.proto --- .../map_optional_primitive_values.proto | 25 +++++++++++++++++++ tests/test_protocol.py | 1 + 2 files changed, 26 insertions(+) create mode 100644 tests/data/protocols/protobuf/map_optional_primitive_values.proto diff --git a/tests/data/protocols/protobuf/map_optional_primitive_values.proto b/tests/data/protocols/protobuf/map_optional_primitive_values.proto new file mode 100644 index 00000000..06d80f22 --- /dev/null +++ b/tests/data/protocols/protobuf/map_optional_primitive_values.proto @@ -0,0 +1,25 @@ +// map_optional_primitive_values.proto + +syntax = "proto3"; + +message OptionalPrimitiveValuesMap { + map optional_map = 1; + + message OptionalValues { + optional double optional_double_field = 1; + optional float optional_float_field = 2; + optional int32 optional_int32_field = 3; + optional int64 optional_int64_field = 4; + optional uint32 optional_uint32_field = 5; + optional uint64 optional_uint64_field = 6; + optional sint32 optional_sint32_field = 7; + optional sint64 optional_sint64_field = 8; + optional fixed32 optional_fixed32_field = 9; + optional fixed64 optional_fixed64_field = 10; + optional sfixed32 optional_sfixed32_field = 11; + optional sfixed64 optional_sfixed64_field = 12; + optional bool optional_bool_field = 13; + optional string optional_string_field = 14; + optional bytes optional_bytes_field = 15; + } +} diff --git a/tests/test_protocol.py b/tests/test_protocol.py index f5cad518..f4adce77 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -32,6 +32,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["deeply_nested_message.proto"], PROTO_FILES["oneof_value.proto"], PROTO_FILES["map_primitive_values.proto"], + PROTO_FILES["map_optional_primitive_values.proto"], ]) def test_protodantic(proto_path: Path): From 7e28191c57fb3a9cb717d93a9e8a172e8fbd351b Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 28 Mar 2025 22:44:58 +0100 Subject: [PATCH 060/189] feat: add optional map values to protodantic.jinja --- .../templates/protocols/protodantic.jinja | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 07c2a971..128c3699 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -74,12 +74,21 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- macro encode_map_field(map_field, message) -%} for key, val in {{ message.name|lower }}.{{ map_field.name }}.items(): + {%- if scalar_map.get(map_field.value_type) %} proto_obj.{{ map_field.name }}[key] = val + {%- else %} + {{message.name}}.{{ map_field.value_type }}.encode(proto_obj.{{ map_field.name }}[key], val) + {%- endif %} {%- endmacro %} -{%- macro decode_map_field(map_field) -%} - {%- set value_type_str = scalar_map.get(map_field.value_type) -%} - {{ "decoded_" ~ map_field.name }} = dict(proto_obj.{{ map_field.name }}) +{%- macro decode_map_field(map_field, message) -%} + {%- if scalar_map.get(map_field.value_type) %} + decoded_{{ map_field.name }} = dict(proto_obj.{{ map_field.name }}) + {%- else %} + decoded_{{ map_field.name }} = {} + for key, item in proto_obj.{{ map_field.name }}.items(): + decoded_{{ map_field.name }}[key] = {{ message.name }}.{{ map_field.value_type }}.decode(item) + {%- endif %} {%- endmacro %} {#- First, generate Enums #} @@ -158,7 +167,7 @@ class {{ message.name }}(BaseModel): {%- endfor %} {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} - {{ decode_map_field(map_field) }} + {{ decode_map_field(map_field, message) }} {%- endfor %} {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} @@ -178,7 +187,7 @@ class {{ message.name }}(BaseModel): {%- endfor %} {%- if message.elements | selectattr("__class__.__name__", "equalto", "OneOf") | list | length > 0 -%} **oneof_data - {%- endif -%} + {%- endif %} ) {%- endmacro %} From d42d6decff5c009c2607e95c7f9bebf870874c04 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 29 Mar 2025 09:28:30 +0100 Subject: [PATCH 061/189] tests: add all primitive types and rename to map_repeated_primitive_values.proto --- .../map_repeated_primitive_values.proto | 27 +++++++++++++++++++ .../protobuf/map_repeated_value.proto | 11 -------- 2 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 tests/data/protocols/protobuf/map_repeated_primitive_values.proto delete mode 100644 tests/data/protocols/protobuf/map_repeated_value.proto diff --git a/tests/data/protocols/protobuf/map_repeated_primitive_values.proto b/tests/data/protocols/protobuf/map_repeated_primitive_values.proto new file mode 100644 index 00000000..dd855d24 --- /dev/null +++ b/tests/data/protocols/protobuf/map_repeated_primitive_values.proto @@ -0,0 +1,27 @@ +// map_repeated_primitive_values.proto + +syntax = "proto3"; + +message MapRepeatedValues { + map data = 1; + + message RepeatedValues { + repeated double repeated_double_field = 1; + repeated float repeated_float_field = 2; + repeated int32 repeated_int32_field = 3; + repeated int64 repeated_int64_field = 4; + repeated uint32 repeated_uint32_field = 5; + repeated uint64 repeated_uint64_field = 6; + repeated sint32 repeated_sint32_field = 7; + repeated sint64 repeated_sint64_field = 8; + repeated fixed32 repeated_fixed32_field = 9; + repeated fixed64 repeated_fixed64_field = 10; + repeated sfixed32 repeated_sfixed32_field = 11; + repeated sfixed64 repeated_sfixed64_field = 12; + repeated bool repeated_bool_field = 13; + repeated string repeated_string_field = 14; + repeated bytes repeated_bytes_field = 15; + } +} + + diff --git a/tests/data/protocols/protobuf/map_repeated_value.proto b/tests/data/protocols/protobuf/map_repeated_value.proto deleted file mode 100644 index 859d7304..00000000 --- a/tests/data/protocols/protobuf/map_repeated_value.proto +++ /dev/null @@ -1,11 +0,0 @@ -// map_repeated_value.proto - -syntax = "proto3"; - -message MapRepeatedValue { - map data = 1; - - message RepeatedInts { - repeated int32 values = 1; - } -} From 234eed5c30f7196613729c8cf8b227209f109be6 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 29 Mar 2025 09:29:10 +0100 Subject: [PATCH 062/189] tests: add map_repeated_primitive_values.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index f4adce77..f8e0b390 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -33,6 +33,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["oneof_value.proto"], PROTO_FILES["map_primitive_values.proto"], PROTO_FILES["map_optional_primitive_values.proto"], + PROTO_FILES["map_repeated_primitive_values.proto"], ]) def test_protodantic(proto_path: Path): From f750d860de8561eaadf3307903ede15aa8f0501a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 29 Mar 2025 12:02:08 +0100 Subject: [PATCH 063/189] tests: add map_message.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index f8e0b390..5d06c197 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -32,6 +32,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["deeply_nested_message.proto"], PROTO_FILES["oneof_value.proto"], PROTO_FILES["map_primitive_values.proto"], + PROTO_FILES["map_message.proto"], PROTO_FILES["map_optional_primitive_values.proto"], PROTO_FILES["map_repeated_primitive_values.proto"], ]) From b6f7ea4063d2c4ab00c349b0d4022007025fb15c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 29 Mar 2025 12:02:44 +0100 Subject: [PATCH 064/189] feat: add direct_nested to protodantic.jinja --- .../templates/protocols/protodantic.jinja | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 128c3699..abf13fd2 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -29,7 +29,7 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- if element.type in enum_names -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ full_name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {{ full_name }}{{ message.name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif -%} @@ -39,7 +39,7 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes decoded_{{ element.name }} = {% if element.type in enum_names -%} {{ element.type }}(proto_obj.{{ element.name }}) {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ full_name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {{ full_name }}{{ message.name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} {%- endif -%} @@ -72,22 +72,22 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- endif -%} {%- endmacro -%} -{%- macro encode_map_field(map_field, message) -%} +{%- macro encode_map_field(map_field, message, full_name) -%} for key, val in {{ message.name|lower }}.{{ map_field.name }}.items(): {%- if scalar_map.get(map_field.value_type) %} proto_obj.{{ map_field.name }}[key] = val {%- else %} - {{message.name}}.{{ map_field.value_type }}.encode(proto_obj.{{ map_field.name }}[key], val) + {{ full_name }}{{ map_field.value_type }}.encode(proto_obj.{{ map_field.name }}[key], val) {%- endif %} {%- endmacro %} -{%- macro decode_map_field(map_field, message) -%} +{%- macro decode_map_field(map_field, message, full_name) -%} {%- if scalar_map.get(map_field.value_type) %} decoded_{{ map_field.name }} = dict(proto_obj.{{ map_field.name }}) {%- else %} decoded_{{ map_field.name }} = {} for key, item in proto_obj.{{ map_field.name }}.items(): - decoded_{{ map_field.name }}[key] = {{ message.name }}.{{ map_field.value_type }}.decode(item) + decoded_{{ map_field.name }}[key] = {{ full_name }}{{ map_field.value_type }}.decode(item) {%- endif %} {%- endmacro %} @@ -100,13 +100,17 @@ class {{ enum.name }}(Enum): {%- endfor %} {%- macro render_message(message, prefix="", indent_level=1) %} +{#- Define a list of directly nested mesasges -#} +{%- set directly_nested = [] %} +{%- for nested in message.elements if nested.__class__.__name__ == "Message" %} +{%- set directly_nested = directly_nested.append(nested.name) %} +{%- endfor %} class {{ message.name }}(BaseModel): {%- set indent = ' ' * indent_level -%} - {%- set prefix = (prefix + '.' if prefix else '') + message.name -%} {#- Handle nested messages recursively -#} {%- for nested in message.elements if nested.__class__.__name__ == "Message" %} - {{indent}}{{ render_message(nested, prefix, indent_level + 1) | indent(4, true) }} + {{indent}}{{ render_message(nested, prefix + message.name + ".", indent_level + 1) | indent(4, true) }} {% endfor %} {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} @@ -144,7 +148,11 @@ class {{ message.name }}(BaseModel): {%- endfor %} {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} - {{ encode_map_field(map_field, message) }} + {%- if map_field.value_type in directly_nested %} + {{ encode_map_field(map_field, message, message.name + "." + prefix) }} + {%- else %} + {{ encode_map_field(map_field, message, prefix) }} + {%- endif %} {%- endfor %} {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} @@ -167,7 +175,11 @@ class {{ message.name }}(BaseModel): {%- endfor %} {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} - {{ decode_map_field(map_field, message) }} + {%- if map_field.value_type in directly_nested %} + {{ decode_map_field(map_field, message, message.name + "." + prefix) }} + {%- else %} + {{ decode_map_field(map_field, message, prefix) }} + {%- endif %} {%- endfor %} {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} From a4f6f673b80f10923cb850c2ef1d2eef60a3adff Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 29 Mar 2025 12:25:51 +0100 Subject: [PATCH 065/189] refactor: remove `decoded_` prefix from variable names --- .../data/templates/protocols/protodantic.jinja | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index abf13fd2..b6a0e277 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -36,7 +36,7 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- endmacro -%} {%- macro decode_scalar(element, message, full_name) -%} - decoded_{{ element.name }} = {% if element.type in enum_names -%} + {{ element.name }} = {% if element.type in enum_names -%} {{ element.type }}(proto_obj.{{ element.name }}) {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} {{ full_name }}{{ message.name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) @@ -66,9 +66,9 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- macro decode_repeated(element, message) -%} {%- if element.type in enum_names -%} - decoded_{{ element.name }} = [{{ element.type }}(item) for item in proto_obj.{{ element.name }}] + {{ element.name }} = [{{ element.type }}(item) for item in proto_obj.{{ element.name }}] {%- else -%} - decoded_{{ element.name }} = list(proto_obj.{{ element.name }}) + {{ element.name }} = list(proto_obj.{{ element.name }}) {%- endif -%} {%- endmacro -%} @@ -83,11 +83,11 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- macro decode_map_field(map_field, message, full_name) -%} {%- if scalar_map.get(map_field.value_type) %} - decoded_{{ map_field.name }} = dict(proto_obj.{{ map_field.name }}) + {{ map_field.name }} = dict(proto_obj.{{ map_field.name }}) {%- else %} - decoded_{{ map_field.name }} = {} + {{ map_field.name }} = {} for key, item in proto_obj.{{ map_field.name }}.items(): - decoded_{{ map_field.name }}[key] = {{ full_name }}{{ map_field.value_type }}.decode(item) + {{ map_field.name }}[key] = {{ full_name }}{{ map_field.value_type }}.decode(item) {%- endif %} {%- endmacro %} @@ -192,10 +192,10 @@ class {{ message.name }}(BaseModel): return cls( {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {{ element.name }}=decoded_{{ element.name }}{{ "," if not loop.last else "" }} + {{ element.name }}={{ element.name }}{{ "," if not loop.last else "" }} {%- endfor %} {%- for element in message.elements if element.__class__.__name__ == "MapField" %} - {{ element.name }}=decoded_{{ element.name }}{{ "," if not loop.last else "" }} + {{ element.name }}={{ element.name }}{{ "," if not loop.last else "" }} {%- endfor %} {%- if message.elements | selectattr("__class__.__name__", "equalto", "OneOf") | list | length > 0 -%} **oneof_data From 78119e570c160cc3ae7650b553592681a28d1eec Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 31 Mar 2025 22:29:37 +0200 Subject: [PATCH 066/189] feat: proto schema parser adapters --- auto_dev/protocols/adapters.py | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 auto_dev/protocols/adapters.py diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py new file mode 100644 index 00000000..4de0f9d0 --- /dev/null +++ b/auto_dev/protocols/adapters.py @@ -0,0 +1,118 @@ +from __future__ import annotations + +import re +from typing_extensions import TypeAliasType +from dataclasses import dataclass, field + +from proto_schema_parser.ast import ( + FileElement, + File, + Import, + Package, + Option, + Extension, + Service, + MessageElement, + Comment, + Field as ProtoField, + Group, + OneOf, + ExtensionRange, + Reserved, + Message, + Enum, + MapField, + MessageValue, + EnumElement, +) + + +def camel_to_snake(name: str) -> str: + """Convert CamelCase to snake_case.""" + return re.sub(r'(? MessageAdapter: + """Convert a `Message` into `MessageAdapter`, handling recursion.""" + + elements = {camel_to_snake(t.__name__): [] for t in MessageElement.__args__} + + for element in message.elements: + key = camel_to_snake(element.__class__.__name__) + elements[key].append(element) + + return cls( + wrapped=message, + fully_qualified_name=f"{parent_prefix}{message.name}", + comments=elements["comment"], + fields=elements["field"], + groups=elements["group"], + oneofs=elements["one_of"], + options=elements["option"], + extension_ranges=elements["extension_range"], + reserved=elements["reserved"], + messages=[cls.from_message(m, parent_prefix=f"{parent_prefix}{message.name}.") for m in elements["message"]], + enums=elements["enum"], + extensions=elements["extension"], + map_fields=elements["map_field"] + ) + + +@dataclass +class FileAdapter: + wrapped: File = field(repr=False) + syntax: str | None + imports: list[Import] = field(default_factory=list) + packages: list[Package] = field(default_factory=list) + options: list[Option] = field(default_factory=list) + messages: list[Message] = field(default_factory=list) + enums: list[Enum] = field(default_factory=list) + extensions: list[Extension] = field(default_factory=list) + services: list[Service] = field(default_factory=list) + comments: list[Comment] = field(default_factory=list) + + def __getattr__(self, name: str): + return getattr(self.wrapped, name) + + @classmethod + def from_file(cls, file: File) -> FileAdapter: + """Convert a `File` into `FileAdapter`, handling messages recursively.""" + + elements = {camel_to_snake(t.__name__): [] for t in FileElement.__args__} + + for element in file.file_elements: + key = camel_to_snake(element.__class__.__name__) + elements[key].append(element) + + return cls( + wrapped=file, + syntax=file.syntax, + imports=elements["import"], + packages=elements["package"], + options=elements["option"], + messages=[MessageAdapter.from_message(m) for m in elements["message"]], + enums=elements["enum"], + extensions=elements["extension"], + services=elements["service"], + comments=elements["comment"] + ) From 8c89bb2911c84f081b3654e38d7ad9d98575faee Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 31 Mar 2025 22:31:18 +0200 Subject: [PATCH 067/189] refactor: use proto schema adapters in protodantic and hypothesis jinja templates --- .../data/templates/protocols/hypothesis.jinja | 18 ++--- .../templates/protocols/protodantic.jinja | 68 +++++++++---------- auto_dev/protocols/protodantic.py | 8 ++- 3 files changed, 48 insertions(+), 46 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 02931112..ddefdb91 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -12,10 +12,10 @@ from {{ primitives_import_path }} import ( {%- endfor %} ) from {{ models_import_path }} import ( - {%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} + {%- for enum in file.enums %} {{ enum.name }}, {%- endfor %} - {%- for message in result.file_elements if message.__class__.__name__ == "Message" %} + {%- for message in file.messages %} {{ message.name }}, {%- endfor %} ) @@ -43,7 +43,7 @@ st.register_type_strategy( {# Define a list of enum names #} {%- set enum_names = [] %} -{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{%- for enum in file.enums %} {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} @@ -71,13 +71,13 @@ st.register_type_strategy( {%- endfor %} {#- Generate strategies for inner messages first -#} -{%- for element in message.elements if element.__class__.__name__ == "Message" %} -{{ message_strategy(element, prefix + message.name + ".") }} +{%- for nested in message.messages %} +{{ message_strategy(nested, prefix + message.name + ".") }} {%- endfor %} {{ message.name|lower }}_strategy = st.builds( {{ prefix }}{{ message.name }}, - {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {%- for element in message.fields %} {%- if element.type in nested_names %} {{ element.name }}={{ element.type|lower }}_strategy, {%- elif element.cardinality == "OPTIONAL" %} @@ -92,17 +92,17 @@ st.register_type_strategy( {%- endmacro %} {# Define strategies for Enums at the top level #} -{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{%- for enum in file.enums %} {{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) {%- endfor %} {# Define strategies for each message #} -{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{%- for message in file.messages %} {{ message_strategy(message) }} {%- endfor %} {# Define tests for each message #} -{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{%- for message in file.messages %} @given({{ message.name|lower }}_strategy) def test_{{ message.name|lower }}({{ message.name|lower }}: {{ message.name }}): assert isinstance({{ message.name|lower }}, {{ message.name }}) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index b6a0e277..1a4deed2 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -21,7 +21,7 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {#- Define a list of enum names -#} {%- set enum_names = [] %} -{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} +{%- for enum in file.enums %} {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} @@ -91,14 +91,6 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- endif %} {%- endmacro %} -{#- First, generate Enums #} -{%- for enum in result.file_elements if enum.__class__.__name__ == "Enum" %} -class {{ enum.name }}(Enum): -{%- for value in enum.elements %} - {{ value.name }} = {{ value.number }} -{%- endfor %} -{%- endfor %} - {%- macro render_message(message, prefix="", indent_level=1) %} {#- Define a list of directly nested mesasges -#} {%- set directly_nested = [] %} @@ -109,15 +101,15 @@ class {{ message.name }}(BaseModel): {%- set indent = ' ' * indent_level -%} {#- Handle nested messages recursively -#} - {%- for nested in message.elements if nested.__class__.__name__ == "Message" %} + {%- for nested in message.messages %} {{indent}}{{ render_message(nested, prefix + message.name + ".", indent_level + 1) | indent(4, true) }} {% endfor %} - {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} + {%- for map_field in message.map_fields %} {{ map_field.name }}: dict[{{ scalar_map.get(map_field.key_type) }}, {{ scalar_map.get(map_field.value_type, map_field.value_type) }}] {%- endfor %} - {%- for oneof in message.elements if oneof.__class__.__name__ == "OneOf" %} + {%- for oneof in message.oneofs %} {{ oneof.name }}: {%- for field in oneof.elements -%} {{ ' ' }}{{ scalar_map.get(field.type, field.type) }}{{ " | " if not loop.last else "" }} @@ -125,7 +117,7 @@ class {{ message.name }}(BaseModel): {%- endfor %} {#- Handle fields of the message -#} - {%- for field in message.elements if field.__class__.__name__ == "Field" %} + {%- for field in message.fields %} {%- if field.cardinality == "REPEATED" %} {{ field.name }}: list[{{ scalar_map.get(field.type, field.type) }}] {%- elif field.cardinality == "OPTIONAL" %} @@ -137,7 +129,7 @@ class {{ message.name }}(BaseModel): @staticmethod def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: - {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {%- for element in message.fields %} {%- if element.cardinality == "REPEATED" %} {{ encode_repeated(element, message) }} {%- elif element.cardinality == "OPTIONAL" %} @@ -147,7 +139,7 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} - {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} + {%- for map_field in message.map_fields %} {%- if map_field.value_type in directly_nested %} {{ encode_map_field(map_field, message, message.name + "." + prefix) }} {%- else %} @@ -155,26 +147,26 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} - {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} - {%- for field in element.elements %} - if isinstance({{ message.name|lower }}.{{ element.name }}, {{ scalar_map.get(field.type, field.type) }}): - proto_obj.{{ field.name }} = {{ message.name|lower }}.{{ element.name }} + {%- for oneof in message.oneofs %} + {%- for element in oneof.elements %} + if isinstance({{ message.name|lower }}.{{ oneof.name }}, {{ scalar_map.get(element.type, element.type) }}): + proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ oneof.name }} {%- endfor %} {%- endfor %} @classmethod def decode(cls, proto_obj) -> "{{ message.name }}": - {%- for element in message.elements if element.__class__.__name__ == "Field" %} - {%- if element.cardinality == "REPEATED" %} - {{ decode_repeated(element, message) }} - {%- elif element.cardinality == "OPTIONAL" %} - {{ decode_optional(element, message) }} + {%- for field in message.fields %} + {%- if field.cardinality == "REPEATED" %} + {{ decode_repeated(field, message) }} + {%- elif field.cardinality == "OPTIONAL" %} + {{ decode_optional(field, message) }} {%- else %} - {{ decode_scalar(element, message, prefix) }} + {{ decode_scalar(field, message, prefix) }} {%- endif %} {%- endfor %} - {%- for map_field in message.elements if map_field.__class__.__name__ == "MapField" %} + {%- for map_field in message.map_fields %} {%- if map_field.value_type in directly_nested %} {{ decode_map_field(map_field, message, message.name + "." + prefix) }} {%- else %} @@ -182,29 +174,37 @@ class {{ message.name }}(BaseModel): {%- endif %} {%- endfor %} - {%- for element in message.elements if element.__class__.__name__ == "OneOf" %} + {%- for oneof in message.oneofs %} oneof_data = {} - {%- for field in element.elements %} - if proto_obj.HasField("{{ field.name }}"): - oneof_data["{{ element.name }}"] = proto_obj.{{ field.name }} + {%- for element in oneof.elements %} + if proto_obj.HasField("{{ element.name }}"): + oneof_data["{{ oneof.name }}"] = proto_obj.{{ element.name }} {%- endfor %} {%- endfor %} return cls( - {%- for element in message.elements if element.__class__.__name__ == "Field" %} + {%- for element in message.fields %} {{ element.name }}={{ element.name }}{{ "," if not loop.last else "" }} {%- endfor %} - {%- for element in message.elements if element.__class__.__name__ == "MapField" %} + {%- for element in message.map_fields %} {{ element.name }}={{ element.name }}{{ "," if not loop.last else "" }} {%- endfor %} - {%- if message.elements | selectattr("__class__.__name__", "equalto", "OneOf") | list | length > 0 -%} + {%- if message.oneofs -%} **oneof_data {%- endif %} ) {%- endmacro %} +{#- First, generate top-level Enums #} +{%- for enum in file.enums %} +class {{ enum.name }}(Enum): +{%- for value in enum.elements %} + {{ value.name }} = {{ value.number }} +{%- endfor %} +{%- endfor %} + {# Now generate all message classes #} -{%- for message in result.file_elements if message.__class__.__name__ == "Message" %} +{%- for message in file.messages %} {{ render_message(message) }} {%- endfor %} diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 4f783d9e..ed2c71fb 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -11,6 +11,7 @@ from jinja2 import Template, Environment, FileSystemLoader from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER +from auto_dev.protocols.adapters import FileAdapter, MessageAdapter def get_repo_root() -> Path: @@ -75,9 +76,10 @@ def create( float_primitives = [p for p in primitives if issubclass(p, float)] integer_primitives = [p for p in primitives if issubclass(p, int)] - result = Parser().parse(content) + file = FileAdapter.from_file(Parser().parse(content)) + code = generated_code = protodantic_template.render( - result=result, + file=file, float_primitives=float_primitives, integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, @@ -106,7 +108,7 @@ def create( messages_pb2 = pb2_path.with_suffix("").name tests = generated_tests = hypothesis_template.render( - result=result, + file=file, float_primitives=float_primitives, integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, From ec74317d65be51777863e3f18158ffb2e0f70fa4 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 31 Mar 2025 23:20:58 +0200 Subject: [PATCH 068/189] refactor: use Message.fully_qualified_name in protodantic.jinja --- auto_dev/data/templates/protocols/protodantic.jinja | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 1a4deed2..f81ddb8e 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -25,21 +25,21 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- set enum_names = enum_names.append( enum.name ) %} {%- endfor %} -{%- macro encode_scalar(element, message, full_name) -%} +{%- macro encode_scalar(element, message) -%} {%- if element.type in enum_names -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ full_name }}{{ message.name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) + {{ message.fully_qualified_name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} {%- endif -%} {%- endmacro -%} -{%- macro decode_scalar(element, message, full_name) -%} +{%- macro decode_scalar(element, message) -%} {{ element.name }} = {% if element.type in enum_names -%} {{ element.type }}(proto_obj.{{ element.name }}) {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ full_name }}{{ message.name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) + {{ message.fully_qualified_name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) {%- else -%} proto_obj.{{ element.name }} {%- endif -%} @@ -135,7 +135,7 @@ class {{ message.name }}(BaseModel): {%- elif element.cardinality == "OPTIONAL" %} {{ encode_optional(element, message) }} {%- else %} - {{ encode_scalar(element, message, prefix) }} + {{ encode_scalar(element, message) }} {%- endif %} {%- endfor %} @@ -162,7 +162,7 @@ class {{ message.name }}(BaseModel): {%- elif field.cardinality == "OPTIONAL" %} {{ decode_optional(field, message) }} {%- else %} - {{ decode_scalar(field, message, prefix) }} + {{ decode_scalar(field, message) }} {%- endif %} {%- endfor %} From 4056f3d62542cc1fe6bac514eca61f0b9dbeab28 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 31 Mar 2025 23:26:17 +0200 Subject: [PATCH 069/189] feat: add qualified_type() method to protodantic MessageAdapter --- auto_dev/protocols/adapters.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 4de0f9d0..7daeb063 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -51,6 +51,15 @@ class MessageAdapter: def __getattr__(self, name: str): return getattr(self.wrapped, name) + @property + def nested_names(self) -> set[str]: + return {m.name for m in self.messages} | {e.name for e in self.enums} + + def qualified_type(self, type_name: str) -> str: + if type_name in self.nested_names: + return f"{self.fully_qualified_name}.{type_name}" + return type_name + @classmethod def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: """Convert a `Message` into `MessageAdapter`, handling recursion.""" From 9b1f13150bddc7d47a0092ed9602aef69efffb21 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 31 Mar 2025 23:26:56 +0200 Subject: [PATCH 070/189] refactor: use Message.qualified_type to simplify protodantic.jinja template --- .../templates/protocols/protodantic.jinja | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index f81ddb8e..b4e46ab5 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -72,37 +72,32 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {%- endif -%} {%- endmacro -%} -{%- macro encode_map_field(map_field, message, full_name) -%} +{%- macro encode_map_field(map_field, message) -%} for key, val in {{ message.name|lower }}.{{ map_field.name }}.items(): {%- if scalar_map.get(map_field.value_type) %} proto_obj.{{ map_field.name }}[key] = val {%- else %} - {{ full_name }}{{ map_field.value_type }}.encode(proto_obj.{{ map_field.name }}[key], val) + {{ message.qualified_type(map_field.value_type) }}.encode(proto_obj.{{ map_field.name }}[key], val) {%- endif %} {%- endmacro %} -{%- macro decode_map_field(map_field, message, full_name) -%} +{%- macro decode_map_field(map_field, message) -%} {%- if scalar_map.get(map_field.value_type) %} {{ map_field.name }} = dict(proto_obj.{{ map_field.name }}) {%- else %} {{ map_field.name }} = {} for key, item in proto_obj.{{ map_field.name }}.items(): - {{ map_field.name }}[key] = {{ full_name }}{{ map_field.value_type }}.decode(item) + {{ map_field.name }}[key] = {{ message.qualified_type(map_field.value_type) }}.decode(item) {%- endif %} {%- endmacro %} -{%- macro render_message(message, prefix="", indent_level=1) %} -{#- Define a list of directly nested mesasges -#} -{%- set directly_nested = [] %} -{%- for nested in message.elements if nested.__class__.__name__ == "Message" %} -{%- set directly_nested = directly_nested.append(nested.name) %} -{%- endfor %} +{%- macro render_message(message, indent_level=1) %} class {{ message.name }}(BaseModel): {%- set indent = ' ' * indent_level -%} {#- Handle nested messages recursively -#} {%- for nested in message.messages %} - {{indent}}{{ render_message(nested, prefix + message.name + ".", indent_level + 1) | indent(4, true) }} + {{indent}}{{ render_message(nested, indent_level + 1) | indent(4, true) }} {% endfor %} {%- for map_field in message.map_fields %} @@ -140,11 +135,7 @@ class {{ message.name }}(BaseModel): {%- endfor %} {%- for map_field in message.map_fields %} - {%- if map_field.value_type in directly_nested %} - {{ encode_map_field(map_field, message, message.name + "." + prefix) }} - {%- else %} - {{ encode_map_field(map_field, message, prefix) }} - {%- endif %} + {{ encode_map_field(map_field, message) }} {%- endfor %} {%- for oneof in message.oneofs %} @@ -167,11 +158,7 @@ class {{ message.name }}(BaseModel): {%- endfor %} {%- for map_field in message.map_fields %} - {%- if map_field.value_type in directly_nested %} - {{ decode_map_field(map_field, message, message.name + "." + prefix) }} - {%- else %} - {{ decode_map_field(map_field, message, prefix) }} - {%- endif %} + {{ decode_map_field(map_field, message) }} {%- endfor %} {%- for oneof in message.oneofs %} From f2bc2f67bd70df6d77b612ba3bdd19f535d391a1 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 31 Mar 2025 23:34:22 +0200 Subject: [PATCH 071/189] fix: ensure consistent trailing commas in generated constructor --- auto_dev/data/templates/protocols/protodantic.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index b4e46ab5..e7b70e16 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -171,10 +171,10 @@ class {{ message.name }}(BaseModel): return cls( {%- for element in message.fields %} - {{ element.name }}={{ element.name }}{{ "," if not loop.last else "" }} + {{ element.name }}={{ element.name }}, {%- endfor %} {%- for element in message.map_fields %} - {{ element.name }}={{ element.name }}{{ "," if not loop.last else "" }} + {{ element.name }}={{ element.name }}, {%- endfor %} {%- if message.oneofs -%} **oneof_data From d7c14616c651a3029c93ba2ebbef20f73e66b0a8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 1 Apr 2025 14:15:29 +0200 Subject: [PATCH 072/189] feat: formatter.render_attribute --- auto_dev/protocols/formatter.py | 71 +++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 auto_dev/protocols/formatter.py diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py new file mode 100644 index 00000000..7c3bca06 --- /dev/null +++ b/auto_dev/protocols/formatter.py @@ -0,0 +1,71 @@ +import textwrap + +from proto_schema_parser import ast +from proto_schema_parser.ast import ( + FileElement, + File, + Import, + Package, + Option, + Extension, + Service, + MessageElement, + Comment, + Field, + Group, + OneOf, + ExtensionRange, + Reserved, + Message, + Enum, + MapField, + MessageValue, + EnumElement, + FieldCardinality, +) + +from auto_dev.protocols.adapters import MessageAdapter +from auto_dev.protocols.primitives import PRIMITIVE_TYPE_MAP + + +def render_field(field: Field) -> str: + field_type = PRIMITIVE_TYPE_MAP.get(field.type, field.type) + match field.cardinality: + case FieldCardinality.REQUIRED | None: + return f"{field_type}" + case FieldCardinality.OPTIONAL: + return f"{field_type} | None" + case FieldCardinality.REPEATED: + return f"list[{field_type}]" + case _: + raise TypeError(f"Unexpected cardinality: {field.cardinality}") + + +def render_attribute(element: MessageElement, prefix=""): + match type(element): + case ast.Comment: + return f"# {element.text}" + case ast.Field: + return f"{element.name}: {render_field(element)}" + case ast.OneOf: + if not all(isinstance(e, Field) for e in element.elements): + raise NotImplementedError("Only implemented OneOf for Field") + inner = " | ".join(render_field(e) for e in element.elements) + return f"{element.name}: {inner}" + case ast.Message: + elements = sorted(element.elements, key=lambda e: not isinstance(e, ast.Message)) + inner = "\n".join(render_attribute(e, prefix + element.name + ".") for e in elements) + indented_inner = textwrap.indent(inner, " ") + return f"\nclass {element.name}(BaseModel):\n{indented_inner}\n" + case ast.Enum: + members = "\n".join(f"{val.name} = {val.number}" for val in element.elements) + indented_members = textwrap.indent(members, " ") + return f"class {prefix}{element.name}(Enum):\n{indented_members}\n" + case ast.MapField: + key_type = PRIMITIVE_TYPE_MAP.get(element.key_type, element.key_type) + value_type = PRIMITIVE_TYPE_MAP.get(element.value_type, element.value_type) + return f"{element.name}: dict[{key_type}, {value_type}]" + case ast.Group | ast.Option | ast.ExtensionRange | ast.Reserved | ast.Extension: + raise NotImplementedError(f"{element}") + case _: + raise TypeError(f"Unexpected message type: {element}") From 4487598307cd67f91db395faa669fcb06b840934 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 1 Apr 2025 22:31:36 +0200 Subject: [PATCH 073/189] feat: FileAdapter.file_elements, MessageAdapter.elements and MessageAdapter.file --- auto_dev/protocols/adapters.py | 106 ++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 35 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 7daeb063..f60e4cf0 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -14,7 +14,7 @@ Service, MessageElement, Comment, - Field as ProtoField, + Field, Group, OneOf, ExtensionRange, @@ -34,16 +34,19 @@ def camel_to_snake(name: str) -> str: @dataclass class MessageAdapter: + file: FileAdapter | None = field(repr=False) wrapped: Message = field(repr=False) fully_qualified_name: str + elements: list[MessageElement | MessageAdapter] = field(default_factory=list, repr=False) + comments: list[Comment] = field(default_factory=list) - fields: list[ProtoField] = field(default_factory=list) + fields: list[Field] = field(default_factory=list) groups: list[Group] = field(default_factory=list) oneofs: list[OneOf] = field(default_factory=list) options: list[Option] = field(default_factory=list) extension_ranges: list[ExtensionRange] = field(default_factory=list) reserved: list[Reserved] = field(default_factory=list) - messages: list[Message] = field(default_factory=list) + messages: list[MessageAdapter] = field(default_factory=list) enums: list[Enum] = field(default_factory=list) extensions: list[Extension] = field(default_factory=list) map_fields: list[MapField] = field(default_factory=list) @@ -52,11 +55,15 @@ def __getattr__(self, name: str): return getattr(self.wrapped, name) @property - def nested_names(self) -> set[str]: - return {m.name for m in self.messages} | {e.name for e in self.enums} + def enum_names(self) -> set[str]: + return {m.name for m in self.enums} + + @property + def message_names(self) -> set[str]: + return {m.name for m in self.messages} def qualified_type(self, type_name: str) -> str: - if type_name in self.nested_names: + if type_name in self.enum_names or type_name in self.message_names: return f"{self.fully_qualified_name}.{type_name}" return type_name @@ -64,37 +71,44 @@ def qualified_type(self, type_name: str) -> str: def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: """Convert a `Message` into `MessageAdapter`, handling recursion.""" - elements = {camel_to_snake(t.__name__): [] for t in MessageElement.__args__} - - for element in message.elements: + elements = [] + grouped_elements = {camel_to_snake(t.__name__): [] for t in MessageElement.__args__} + for i, element in enumerate(message.elements): key = camel_to_snake(element.__class__.__name__) - elements[key].append(element) + if isinstance(element, Message): + element = cls.from_message(element, parent_prefix=f"{parent_prefix}{message.name}.") + elements.append(element) + grouped_elements[key].append(element) return cls( + file=None, wrapped=message, fully_qualified_name=f"{parent_prefix}{message.name}", - comments=elements["comment"], - fields=elements["field"], - groups=elements["group"], - oneofs=elements["one_of"], - options=elements["option"], - extension_ranges=elements["extension_range"], - reserved=elements["reserved"], - messages=[cls.from_message(m, parent_prefix=f"{parent_prefix}{message.name}.") for m in elements["message"]], - enums=elements["enum"], - extensions=elements["extension"], - map_fields=elements["map_field"] + elements=elements, + comments=grouped_elements["comment"], + fields=grouped_elements["field"], + groups=grouped_elements["group"], + oneofs=grouped_elements["one_of"], + options=grouped_elements["option"], + extension_ranges=grouped_elements["extension_range"], + reserved=grouped_elements["reserved"], + messages=grouped_elements["message"], + enums=grouped_elements["enum"], + extensions=grouped_elements["extension"], + map_fields=grouped_elements["map_field"] ) @dataclass class FileAdapter: wrapped: File = field(repr=False) + file_elements: list[FileElement | MessageAdapter] = field(repr=False) + syntax: str | None imports: list[Import] = field(default_factory=list) packages: list[Package] = field(default_factory=list) options: list[Option] = field(default_factory=list) - messages: list[Message] = field(default_factory=list) + messages: list[MessageAdapter] = field(default_factory=list) enums: list[Enum] = field(default_factory=list) extensions: list[Extension] = field(default_factory=list) services: list[Service] = field(default_factory=list) @@ -103,25 +117,47 @@ class FileAdapter: def __getattr__(self, name: str): return getattr(self.wrapped, name) + @property + def enum_names(self) -> set[str]: + return {m.name for m in self.enums} + + @property + def message_names(self) -> set[str]: + return {m.name for m in self.messages} + @classmethod def from_file(cls, file: File) -> FileAdapter: """Convert a `File` into `FileAdapter`, handling messages recursively.""" - elements = {camel_to_snake(t.__name__): [] for t in FileElement.__args__} - - for element in file.file_elements: + file_elements = [] + grouped_elements = {camel_to_snake(t.__name__): [] for t in FileElement.__args__} + for i, element in enumerate(file.file_elements): key = camel_to_snake(element.__class__.__name__) - elements[key].append(element) + if isinstance(element, Message): + element = MessageAdapter.from_message(element) + file_elements.append(element) + grouped_elements[key].append(element) - return cls( + file_adapter = cls( wrapped=file, + file_elements=file_elements, syntax=file.syntax, - imports=elements["import"], - packages=elements["package"], - options=elements["option"], - messages=[MessageAdapter.from_message(m) for m in elements["message"]], - enums=elements["enum"], - extensions=elements["extension"], - services=elements["service"], - comments=elements["comment"] + imports=grouped_elements["import"], + packages=grouped_elements["package"], + options=grouped_elements["option"], + messages=grouped_elements["message"], + enums=grouped_elements["enum"], + extensions=grouped_elements["extension"], + services=grouped_elements["service"], + comments=grouped_elements["comment"] ) + + def set_file_adapter(message: MessageAdapter): + message.file = file_adapter + for nested_message in message.messages: + set_file_adapter(nested_message) + + for message in file_adapter.messages: + set_file_adapter(message) + + return file_adapter From fc2a85e650db91b423e9d4c94ab1baaea30f7503 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 1 Apr 2025 22:33:40 +0200 Subject: [PATCH 074/189] feat: formatter.render_encoder and formatter.render --- auto_dev/protocols/formatter.py | 79 +++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 7c3bca06..7e1ea63a 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -24,7 +24,8 @@ FieldCardinality, ) -from auto_dev.protocols.adapters import MessageAdapter +from auto_dev.protocols import adapters +from auto_dev.protocols.adapters import FileAdapter, MessageAdapter from auto_dev.protocols.primitives import PRIMITIVE_TYPE_MAP @@ -41,7 +42,7 @@ def render_field(field: Field) -> str: raise TypeError(f"Unexpected cardinality: {field.cardinality}") -def render_attribute(element: MessageElement, prefix=""): +def render_attribute(element: MessageElement | MessageAdapter, prefix: str = "") -> str: match type(element): case ast.Comment: return f"# {element.text}" @@ -52,15 +53,17 @@ def render_attribute(element: MessageElement, prefix=""): raise NotImplementedError("Only implemented OneOf for Field") inner = " | ".join(render_field(e) for e in element.elements) return f"{element.name}: {inner}" - case ast.Message: - elements = sorted(element.elements, key=lambda e: not isinstance(e, ast.Message)) - inner = "\n".join(render_attribute(e, prefix + element.name + ".") for e in elements) - indented_inner = textwrap.indent(inner, " ") - return f"\nclass {element.name}(BaseModel):\n{indented_inner}\n" + case adapters.MessageAdapter: + elements = sorted(element.elements, key=lambda e: not isinstance(e, (MessageAdapter, ast.Enum))) + body = inner = "\n".join(render_attribute(e, prefix + element.name + ".") for e in elements) + encoder = render_encoder(element, prefix) + body = f"{inner}\n\n{encoder}" + indented_body = textwrap.indent(body, " ") + return f"\nclass {element.name}(BaseModel):\n{indented_body}\n" case ast.Enum: members = "\n".join(f"{val.name} = {val.number}" for val in element.elements) indented_members = textwrap.indent(members, " ") - return f"class {prefix}{element.name}(Enum):\n{indented_members}\n" + return f"class {element.name}(IntEnum):\n{indented_members}\n" case ast.MapField: key_type = PRIMITIVE_TYPE_MAP.get(element.key_type, element.key_type) value_type = PRIMITIVE_TYPE_MAP.get(element.value_type, element.value_type) @@ -69,3 +72,63 @@ def render_attribute(element: MessageElement, prefix=""): raise NotImplementedError(f"{element}") case _: raise TypeError(f"Unexpected message type: {element}") + + +def render(file: FileAdapter): + + enums = "\n".join(render_attribute(e) for e in file.enums) + messages = "\n".join(render_attribute(e) for e in file.messages) + + return f"{enums}\n{messages}" + + +def encode_field(element, message, prefix): + instance_attr = f"{message.name.lower()}.{element.name}" + if element.type in PRIMITIVE_TYPE_MAP: + value = instance_attr + elif element.type in message.enum_names: + value = f"{message.name.lower()}.{element.name}" + elif element.type in message.file.enum_names: + value = f"{message.name.lower()}.{element.name}" + elif element.type in message.message_names: + value = f"{prefix}{message.name}.{element.type}.encode(proto_obj.{element.name}, {instance_attr})" + return value + elif element.type in message.file.message_names: + value = f"{element.type}.encode(proto_obj.{element.name}, {instance_attr})" + return value + else: + raise ValueError(f"Unexpected element: {element}") + + match element.cardinality: + case FieldCardinality.REPEATED: + return f"proto_obj.{element.name}.extend({value})" + case FieldCardinality.OPTIONAL: + return f"if {instance_attr} is not None:\n proto_obj.{element.name} = {instance_attr}" + case _: + return f"proto_obj.{element.name} = {value}" + + +def render_encoder(message: MessageAdapter, prefix="") -> str: + + def encode_element(element, prefix) -> str: + match type(element): + case ast.Field: + return encode_field(element, message, prefix) + case ast.OneOf: + return "\n".join( + f"if isinstance({message.name.lower()}.{element.name}, {PRIMITIVE_TYPE_MAP.get(e.type, e.type)}):\n proto_obj.{e.name} = {message.name.lower()}.{element.name}" + for e in element.elements + ) + case ast.MapField: + iter_items = f"for key, value in {message.name.lower()}.{element.name}.items():" + if element.value_type in PRIMITIVE_TYPE_MAP: + return f"{iter_items}\n proto_obj.{element.name}[key] = value" + else: + return f"{iter_items}\n {message.qualified_type(element.value_type)}.encode(proto_obj.{element.name}[key], value)" + case _: + raise TypeError(f"Unexpected message type: {element}") + + elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) + inner = "\n".join(encode_element(e, prefix) for e in elements) + indented_inner = textwrap.indent(inner, " ") + return f"@staticmethod\ndef encode(proto_obj, {message.name.lower()}: \"{message.name}\") -> None:\n{indented_inner}" From 3165af5334f93f8b1c4b38dfe19488fda6ab0c7c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 1 Apr 2025 23:18:57 +0200 Subject: [PATCH 075/189] feat: formatter.render_decoder --- auto_dev/protocols/formatter.py | 60 ++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 7e1ea63a..5c07e8d1 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -57,7 +57,8 @@ def render_attribute(element: MessageElement | MessageAdapter, prefix: str = "") elements = sorted(element.elements, key=lambda e: not isinstance(e, (MessageAdapter, ast.Enum))) body = inner = "\n".join(render_attribute(e, prefix + element.name + ".") for e in elements) encoder = render_encoder(element, prefix) - body = f"{inner}\n\n{encoder}" + decoder = render_decoder(element, prefix) + body = f"{inner}\n\n{encoder}#\n\n{decoder}" indented_body = textwrap.indent(body, " ") return f"\nclass {element.name}(BaseModel):\n{indented_body}\n" case ast.Enum: @@ -132,3 +133,60 @@ def encode_element(element, prefix) -> str: inner = "\n".join(encode_element(e, prefix) for e in elements) indented_inner = textwrap.indent(inner, " ") return f"@staticmethod\ndef encode(proto_obj, {message.name.lower()}: \"{message.name}\") -> None:\n{indented_inner}" + + +def decode_field(field: ast.Field, message: MessageAdapter, prefix="") -> str: + instance_field = f"proto_obj.{field.name}" + if field.type in PRIMITIVE_TYPE_MAP: + value = instance_field + elif field.type in message.enum_names: + value = instance_field + elif field.type in message.message_names: + value = f"{field.name} = {message.qualified_type(field.type)}.decode({instance_field})" + elif field.type in message.file.message_names: + value = f"{field.name} = {field.type}.decode({instance_field})" + else: + value = instance_field + + match field.cardinality: + case FieldCardinality.REPEATED: + return f"{field.name} = list({value})" + case FieldCardinality.OPTIONAL: + return (f"{field.name} = {value} " + f"if {instance_field} is not None and proto_obj.HasField(\"{field.name}\") " + f"else None") + case FieldCardinality.REQUIRED | None: + return f"{field.name} = {value}" + case _: + raise TypeError(f"Unexpected cardinality: {field.cardinality}") + + +def render_decoder(message: MessageAdapter, prefix="") -> str: + + def decode_element(element, prefix) -> str: + match type(element): + case ast.Field: + return decode_field(element, message, prefix) + case ast.OneOf: + return "\n".join( + f"if proto_obj.HasField(\"{e.name}\"):\n {element.name} = proto_obj.{e.name}" + for e in element.elements + ) + case ast.MapField: + if element.value_type in PRIMITIVE_TYPE_MAP: + return f"{element.name} = dict(proto_obj.{element.name})" + else: + return (f"{element.name} = {{ key: {message.qualified_type(element.value_type)}.decode(item) " + f"for key, item in proto_obj.{element.name}.items() }}") + case _: + raise TypeError(f"Unexpected message element type: {element}") + + def constructor_kwargs(elements) -> str: + types = (ast.Field, ast.MapField, ast.OneOf) + return ",\n ".join(f"{e.name}={e.name}" for e in elements if isinstance(e, types)) + + constructor = f"return cls(\n {constructor_kwargs(message.elements)}\n)" + elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) + inner = "\n".join(decode_element(e, prefix) for e in elements) + "\n\n" + constructor + indented_inner = textwrap.indent(inner, " ") + return (f"@classmethod\ndef decode(cls, proto_obj) -> \"{message.name}\":\n{indented_inner}") From 74f5d1af9e57f8330b867ba6c4a3388baf320089 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Tue, 1 Apr 2025 23:23:44 +0200 Subject: [PATCH 076/189] refactor: remove logic from protodantic.jinja and pass formatter instead --- .../templates/protocols/protodantic.jinja | 185 +----------------- auto_dev/protocols/protodantic.py | 5 +- 2 files changed, 5 insertions(+), 185 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index e7b70e16..9986eb74 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -1,4 +1,4 @@ -from enum import Enum +from enum import IntEnum from pydantic import BaseModel @@ -13,185 +13,4 @@ from {{ primitives_import_path }} import ( MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes -{#- Define a map of scalars -#} -{%- set scalar_map = {"bool": "bool", "string": "str", "bytes": "bytes"} %} -{%- for primitive in integer_primitives + float_primitives %} - {%- set scalar_map = scalar_map.update({primitive.__name__.lower(): primitive.__name__}) %} -{%- endfor %} - -{#- Define a list of enum names -#} -{%- set enum_names = [] %} -{%- for enum in file.enums %} -{%- set enum_names = enum_names.append( enum.name ) %} -{%- endfor %} - -{%- macro encode_scalar(element, message) -%} - {%- if element.type in enum_names -%} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }}.value - {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ message.fully_qualified_name }}.{{ element.type }}.encode(proto_obj.{{ element.name }}, {{ message.name|lower }}.{{ element.name }}) - {%- else -%} - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ element.name }} - {%- endif -%} -{%- endmacro -%} - -{%- macro decode_scalar(element, message) -%} - {{ element.name }} = {% if element.type in enum_names -%} - {{ element.type }}(proto_obj.{{ element.name }}) - {%- elif scalar_map.get(element.type) not in scalar_map.values() -%} - {{ message.fully_qualified_name }}.{{ element.type }}.decode(proto_obj.{{ element.name }}) - {%- else -%} - proto_obj.{{ element.name }} - {%- endif -%} -{%- endmacro -%} - -{%- macro encode_optional(element, message, indent_level=2) -%} - {%- set indent = ' ' * indent_level -%} - if {{ message.name|lower }}.{{ element.name }} is not None: - {{ indent }}{{ encode_scalar(element, message) }} -{%- endmacro -%} - -{%- macro decode_optional(element, message) -%} - {{ decode_scalar(element, message) }} if proto_obj.HasField("{{ element.name }}") else None -{%- endmacro -%} - -{%- macro encode_repeated(element, message) -%} - proto_obj.{{ element.name }}.extend({%- if element.type in enum_names -%} - item.value - {%- else -%} - item - {%- endif -%} - {{ ' ' }}for item in {{ message.name|lower }}.{{ element.name }}) -{%- endmacro -%} - -{%- macro decode_repeated(element, message) -%} - {%- if element.type in enum_names -%} - {{ element.name }} = [{{ element.type }}(item) for item in proto_obj.{{ element.name }}] - {%- else -%} - {{ element.name }} = list(proto_obj.{{ element.name }}) - {%- endif -%} -{%- endmacro -%} - -{%- macro encode_map_field(map_field, message) -%} - for key, val in {{ message.name|lower }}.{{ map_field.name }}.items(): - {%- if scalar_map.get(map_field.value_type) %} - proto_obj.{{ map_field.name }}[key] = val - {%- else %} - {{ message.qualified_type(map_field.value_type) }}.encode(proto_obj.{{ map_field.name }}[key], val) - {%- endif %} -{%- endmacro %} - -{%- macro decode_map_field(map_field, message) -%} - {%- if scalar_map.get(map_field.value_type) %} - {{ map_field.name }} = dict(proto_obj.{{ map_field.name }}) - {%- else %} - {{ map_field.name }} = {} - for key, item in proto_obj.{{ map_field.name }}.items(): - {{ map_field.name }}[key] = {{ message.qualified_type(map_field.value_type) }}.decode(item) - {%- endif %} -{%- endmacro %} - -{%- macro render_message(message, indent_level=1) %} -class {{ message.name }}(BaseModel): - {%- set indent = ' ' * indent_level -%} - - {#- Handle nested messages recursively -#} - {%- for nested in message.messages %} - {{indent}}{{ render_message(nested, indent_level + 1) | indent(4, true) }} - {% endfor %} - - {%- for map_field in message.map_fields %} - {{ map_field.name }}: dict[{{ scalar_map.get(map_field.key_type) }}, {{ scalar_map.get(map_field.value_type, map_field.value_type) }}] - {%- endfor %} - - {%- for oneof in message.oneofs %} - {{ oneof.name }}: - {%- for field in oneof.elements -%} - {{ ' ' }}{{ scalar_map.get(field.type, field.type) }}{{ " | " if not loop.last else "" }} - {%- endfor %} - {%- endfor %} - - {#- Handle fields of the message -#} - {%- for field in message.fields %} - {%- if field.cardinality == "REPEATED" %} - {{ field.name }}: list[{{ scalar_map.get(field.type, field.type) }}] - {%- elif field.cardinality == "OPTIONAL" %} - {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} | None - {%- else %} - {{ field.name }}: {{ scalar_map.get(field.type, field.type) }} - {%- endif %} - {%- endfor %} - - @staticmethod - def encode(proto_obj, {{ message.name|lower }}: "{{ message.name }}") -> None: - {%- for element in message.fields %} - {%- if element.cardinality == "REPEATED" %} - {{ encode_repeated(element, message) }} - {%- elif element.cardinality == "OPTIONAL" %} - {{ encode_optional(element, message) }} - {%- else %} - {{ encode_scalar(element, message) }} - {%- endif %} - {%- endfor %} - - {%- for map_field in message.map_fields %} - {{ encode_map_field(map_field, message) }} - {%- endfor %} - - {%- for oneof in message.oneofs %} - {%- for element in oneof.elements %} - if isinstance({{ message.name|lower }}.{{ oneof.name }}, {{ scalar_map.get(element.type, element.type) }}): - proto_obj.{{ element.name }} = {{ message.name|lower }}.{{ oneof.name }} - {%- endfor %} - {%- endfor %} - - @classmethod - def decode(cls, proto_obj) -> "{{ message.name }}": - {%- for field in message.fields %} - {%- if field.cardinality == "REPEATED" %} - {{ decode_repeated(field, message) }} - {%- elif field.cardinality == "OPTIONAL" %} - {{ decode_optional(field, message) }} - {%- else %} - {{ decode_scalar(field, message) }} - {%- endif %} - {%- endfor %} - - {%- for map_field in message.map_fields %} - {{ decode_map_field(map_field, message) }} - {%- endfor %} - - {%- for oneof in message.oneofs %} - oneof_data = {} - {%- for element in oneof.elements %} - if proto_obj.HasField("{{ element.name }}"): - oneof_data["{{ oneof.name }}"] = proto_obj.{{ element.name }} - {%- endfor %} - {%- endfor %} - - return cls( - {%- for element in message.fields %} - {{ element.name }}={{ element.name }}, - {%- endfor %} - {%- for element in message.map_fields %} - {{ element.name }}={{ element.name }}, - {%- endfor %} - {%- if message.oneofs -%} - **oneof_data - {%- endif %} - ) - -{%- endmacro %} - -{#- First, generate top-level Enums #} -{%- for enum in file.enums %} -class {{ enum.name }}(Enum): -{%- for value in enum.elements %} - {{ value.name }} = {{ value.number }} -{%- endfor %} -{%- endfor %} - -{# Now generate all message classes #} -{%- for message in file.messages %} -{{ render_message(message) }} -{%- endfor %} +{{ formatter.render(file) }} diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index ed2c71fb..8a440514 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -11,7 +11,8 @@ from jinja2 import Template, Environment, FileSystemLoader from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER -from auto_dev.protocols.adapters import FileAdapter, MessageAdapter +from auto_dev.protocols.adapters import FileAdapter +from auto_dev.protocols import formatter def get_repo_root() -> Path: @@ -77,9 +78,9 @@ def create( integer_primitives = [p for p in primitives if issubclass(p, int)] file = FileAdapter.from_file(Parser().parse(content)) - code = generated_code = protodantic_template.render( file=file, + formatter=formatter, float_primitives=float_primitives, integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, From 05e4142cc3f758980aef0ce5a5685867f9157e78 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 10:24:59 +0200 Subject: [PATCH 077/189] tests: add message_reference.proto --- .../protocols/protobuf/message_reference.proto | 16 ++++++++++++++++ tests/test_protocol.py | 1 + 2 files changed, 17 insertions(+) create mode 100644 tests/data/protocols/protobuf/message_reference.proto diff --git a/tests/data/protocols/protobuf/message_reference.proto b/tests/data/protocols/protobuf/message_reference.proto new file mode 100644 index 00000000..14a369d6 --- /dev/null +++ b/tests/data/protocols/protobuf/message_reference.proto @@ -0,0 +1,16 @@ +// message_reference.proto + +syntax = "proto3"; + +message Message1 { + string message1_label = 1; + optional string optional_message1_label = 2; + repeated string repeated_message1_label = 3; +} + +message Message2 { + Message1 message1 = 1; + string message2_label = 2; + optional string optional_message2_label = 3; + repeated string repeated_message2_label = 4; +} diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 5d06c197..9964e6bf 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -28,6 +28,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["optional_enum.proto"], PROTO_FILES["repeated_enum.proto"], PROTO_FILES["simple_message.proto"], + PROTO_FILES["message_reference.proto"], PROTO_FILES["nested_message.proto"], PROTO_FILES["deeply_nested_message.proto"], PROTO_FILES["oneof_value.proto"], From 2fae96d6591a0124724a14560b454194245c016c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 10:26:27 +0200 Subject: [PATCH 078/189] tests: add nested_enum.proto --- tests/data/protocols/protobuf/nested_enum.proto | 13 +++++++++++++ tests/test_protocol.py | 1 + 2 files changed, 14 insertions(+) create mode 100644 tests/data/protocols/protobuf/nested_enum.proto diff --git a/tests/data/protocols/protobuf/nested_enum.proto b/tests/data/protocols/protobuf/nested_enum.proto new file mode 100644 index 00000000..2899c02d --- /dev/null +++ b/tests/data/protocols/protobuf/nested_enum.proto @@ -0,0 +1,13 @@ +// nested_enum.proto + +syntax = "proto3"; + +message NestedEnum { + Status status = 1; + + enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; + } +} diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 9964e6bf..8325fcf3 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -27,6 +27,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["basic_enum.proto"], PROTO_FILES["optional_enum.proto"], PROTO_FILES["repeated_enum.proto"], + PROTO_FILES["nested_enum.proto"], PROTO_FILES["simple_message.proto"], PROTO_FILES["message_reference.proto"], PROTO_FILES["nested_message.proto"], From 47887aaaa2c03614cff2baa139c47ec79a65f112 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 10:27:27 +0200 Subject: [PATCH 079/189] feat: hypothesis strategy for nested enum --- .../data/templates/protocols/hypothesis.jinja | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index ddefdb91..8bbbc3e1 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -63,14 +63,21 @@ st.register_type_strategy( st.lists({{ scalar_strategy(field) }}) {%- endmacro -%} +{%- macro enum_strategy(enum, prefix="") -%} +{{ enum.name|lower }}_strategy = st.sampled_from({{ prefix + enum.name }}) +{%- endmacro -%} + {%- macro message_strategy(message, prefix="") -%} -{#- Build a list of nested message names in this message -#} +{#- Build a list of nested enum and message names -#} {%- set nested_names = [] -%} -{%- for m in message.elements if m.__class__.__name__ == "Message" %} -{%- set enum_names = nested_names.append(m.name) %} +{%- for m in message.enums + message.messages %} +{%- set nested_names = nested_names.append(m.name) %} +{%- endfor %} + +{%- for nested in message.enums %} +{{ enum_strategy(nested, prefix + message.name + ".") }} {%- endfor %} -{#- Generate strategies for inner messages first -#} {%- for nested in message.messages %} {{ message_strategy(nested, prefix + message.name + ".") }} {%- endfor %} @@ -93,7 +100,7 @@ st.register_type_strategy( {# Define strategies for Enums at the top level #} {%- for enum in file.enums %} -{{ enum.name|lower }}_strategy = st.sampled_from({{ enum.name }}) +{{ enum_strategy(enum) }} {%- endfor %} {# Define strategies for each message #} From 5854f6df36e7b674aaec5eb79fa09501e9700a9c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 13:24:39 +0200 Subject: [PATCH 080/189] fix: update map_enum.proto to prevent protobuf discriptor naming collision --- tests/data/protocols/protobuf/map_enum.proto | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/data/protocols/protobuf/map_enum.proto b/tests/data/protocols/protobuf/map_enum.proto index 0fcaa6c5..cce9d700 100644 --- a/tests/data/protocols/protobuf/map_enum.proto +++ b/tests/data/protocols/protobuf/map_enum.proto @@ -2,12 +2,12 @@ syntax = "proto3"; -enum Status { - UNKNOWN = 0; - ACTIVE = 1; - INACTIVE = 2; +enum State { + STATE_UNKNOWN = 0; + STATE_ACTIVE = 1; + STATE_INACTIVE = 2; } message MapEnum { - map status_map = 1; + map status_map = 1; } From e0c2c754e24b8682f4e0ab4a5ef2a5f291b83ff7 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 13:25:58 +0200 Subject: [PATCH 081/189] tests: add map_enum.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 8325fcf3..7b07be9f 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -34,6 +34,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["deeply_nested_message.proto"], PROTO_FILES["oneof_value.proto"], PROTO_FILES["map_primitive_values.proto"], + PROTO_FILES["map_enum.proto"], PROTO_FILES["map_message.proto"], PROTO_FILES["map_optional_primitive_values.proto"], PROTO_FILES["map_repeated_primitive_values.proto"], From cbdf7414ca22c6f99732d681ffdb3d84d15c761f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 13:26:42 +0200 Subject: [PATCH 082/189] feat: add logic for enum values in map to formatter --- auto_dev/protocols/formatter.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 5c07e8d1..4e852bd1 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -58,7 +58,7 @@ def render_attribute(element: MessageElement | MessageAdapter, prefix: str = "") body = inner = "\n".join(render_attribute(e, prefix + element.name + ".") for e in elements) encoder = render_encoder(element, prefix) decoder = render_decoder(element, prefix) - body = f"{inner}\n\n{encoder}#\n\n{decoder}" + body = f"{inner}\n\n{encoder}\n\n{decoder}" indented_body = textwrap.indent(body, " ") return f"\nclass {element.name}(BaseModel):\n{indented_body}\n" case ast.Enum: @@ -124,6 +124,8 @@ def encode_element(element, prefix) -> str: iter_items = f"for key, value in {message.name.lower()}.{element.name}.items():" if element.value_type in PRIMITIVE_TYPE_MAP: return f"{iter_items}\n proto_obj.{element.name}[key] = value" + elif element.value_type in message.file.enum_names: + return f"{iter_items}\n proto_obj.{element.name}[key] = {element.value_type}(value)" else: return f"{iter_items}\n {message.qualified_type(element.value_type)}.encode(proto_obj.{element.name}[key], value)" case _: @@ -173,8 +175,11 @@ def decode_element(element, prefix) -> str: for e in element.elements ) case ast.MapField: + iter_items = f"{element.name} = {{}}\nfor key, value in proto_obj.{element.name}.items():" if element.value_type in PRIMITIVE_TYPE_MAP: return f"{element.name} = dict(proto_obj.{element.name})" + elif element.value_type in message.file.enum_names: + return f"{iter_items}\n {element.name}[key] = {element.value_type}(value)" else: return (f"{element.name} = {{ key: {message.qualified_type(element.value_type)}.decode(item) " f"for key, item in proto_obj.{element.name}.items() }}") From fe53c8ed44df25e5baad7fd4df9443cdb5e21fd7 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 13:27:24 +0200 Subject: [PATCH 083/189] tests: add logic for handling map_enum test generation --- auto_dev/data/templates/protocols/hypothesis.jinja | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 8bbbc3e1..389533a7 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -95,6 +95,11 @@ st.register_type_strategy( {{ element.name }}={{ scalar_strategy(element) }}, {%- endif %} {%- endfor %} + {%- for element in message.map_fields %} + {%- if element.value_type in message.file.enum_names %} + {{ element.name }}=st.dictionaries(keys=st.text(), values=st.sampled_from({{ element.value_type }})), + {%- endif %} + {%- endfor %} ) {%- endmacro %} From 4c30350c1c0e9eae0148c0cc7de11185f65fac02 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 13:58:35 +0200 Subject: [PATCH 084/189] refactor: move protoc call upward to detect .proto errors before rendering code --- auto_dev/protocols/protodantic.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 8a440514..1e584257 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -72,6 +72,17 @@ def create( primitives_module = _dynamic_import(primitives_outpath) primitives_import_path = _compute_import_path(primitives_outpath, repo_root) + subprocess.run( + [ + "protoc", + f"--python_out={code_outpath.parent}", + f"--proto_path={proto_inpath.parent}", + proto_inpath.name, + ], + cwd=proto_inpath.parent, + check=True + ) + custom_primitives = _get_locally_defined_classes(primitives_module) primitives = [cls for cls in custom_primitives if not inspect.isabstract(cls)] float_primitives = [p for p in primitives if issubclass(p, float)] @@ -87,17 +98,6 @@ def create( ) code_outpath.write_text(generated_code) - subprocess.run( - [ - "protoc", - f"--python_out={code_outpath.parent}", - f"--proto_path={proto_inpath.parent}", - proto_inpath.name, - ], - cwd=proto_inpath.parent, - check=True - ) - models_import_path = _compute_import_path(code_outpath, repo_root) message_path = str(Path(models_import_path).parent) From c0c10719f6b0c2b544b617dbdecb10068e661670 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 14:59:08 +0200 Subject: [PATCH 085/189] refactor: remove passing prefix in formatter --- auto_dev/protocols/formatter.py | 34 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 4e852bd1..b0c8173e 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -42,7 +42,7 @@ def render_field(field: Field) -> str: raise TypeError(f"Unexpected cardinality: {field.cardinality}") -def render_attribute(element: MessageElement | MessageAdapter, prefix: str = "") -> str: +def render_attribute(element: MessageElement | MessageAdapter) -> str: match type(element): case ast.Comment: return f"# {element.text}" @@ -55,9 +55,9 @@ def render_attribute(element: MessageElement | MessageAdapter, prefix: str = "") return f"{element.name}: {inner}" case adapters.MessageAdapter: elements = sorted(element.elements, key=lambda e: not isinstance(e, (MessageAdapter, ast.Enum))) - body = inner = "\n".join(render_attribute(e, prefix + element.name + ".") for e in elements) - encoder = render_encoder(element, prefix) - decoder = render_decoder(element, prefix) + body = inner = "\n".join(map(render_attribute, elements)) + encoder = render_encoder(element) + decoder = render_decoder(element) body = f"{inner}\n\n{encoder}\n\n{decoder}" indented_body = textwrap.indent(body, " ") return f"\nclass {element.name}(BaseModel):\n{indented_body}\n" @@ -83,7 +83,7 @@ def render(file: FileAdapter): return f"{enums}\n{messages}" -def encode_field(element, message, prefix): +def encode_field(element, message): instance_attr = f"{message.name.lower()}.{element.name}" if element.type in PRIMITIVE_TYPE_MAP: value = instance_attr @@ -92,7 +92,7 @@ def encode_field(element, message, prefix): elif element.type in message.file.enum_names: value = f"{message.name.lower()}.{element.name}" elif element.type in message.message_names: - value = f"{prefix}{message.name}.{element.type}.encode(proto_obj.{element.name}, {instance_attr})" + value = f"{message.qualified_type(element.type)}.encode(proto_obj.{element.name}, {instance_attr})" return value elif element.type in message.file.message_names: value = f"{element.type}.encode(proto_obj.{element.name}, {instance_attr})" @@ -109,12 +109,12 @@ def encode_field(element, message, prefix): return f"proto_obj.{element.name} = {value}" -def render_encoder(message: MessageAdapter, prefix="") -> str: +def render_encoder(message: MessageAdapter) -> str: - def encode_element(element, prefix) -> str: + def encode_element(element) -> str: match type(element): case ast.Field: - return encode_field(element, message, prefix) + return encode_field(element, message) case ast.OneOf: return "\n".join( f"if isinstance({message.name.lower()}.{element.name}, {PRIMITIVE_TYPE_MAP.get(e.type, e.type)}):\n proto_obj.{e.name} = {message.name.lower()}.{element.name}" @@ -126,18 +126,20 @@ def encode_element(element, prefix) -> str: return f"{iter_items}\n proto_obj.{element.name}[key] = value" elif element.value_type in message.file.enum_names: return f"{iter_items}\n proto_obj.{element.name}[key] = {element.value_type}(value)" + elif element.value_type in message.enum_names: + return f"{iter_items}\n proto_obj.{element.name}[key] = {message.name}.{element.value_type}(value)" else: return f"{iter_items}\n {message.qualified_type(element.value_type)}.encode(proto_obj.{element.name}[key], value)" case _: raise TypeError(f"Unexpected message type: {element}") elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) - inner = "\n".join(encode_element(e, prefix) for e in elements) + inner = "\n".join(map(encode_element, elements)) indented_inner = textwrap.indent(inner, " ") return f"@staticmethod\ndef encode(proto_obj, {message.name.lower()}: \"{message.name}\") -> None:\n{indented_inner}" -def decode_field(field: ast.Field, message: MessageAdapter, prefix="") -> str: +def decode_field(field: ast.Field, message: MessageAdapter) -> str: instance_field = f"proto_obj.{field.name}" if field.type in PRIMITIVE_TYPE_MAP: value = instance_field @@ -163,12 +165,12 @@ def decode_field(field: ast.Field, message: MessageAdapter, prefix="") -> str: raise TypeError(f"Unexpected cardinality: {field.cardinality}") -def render_decoder(message: MessageAdapter, prefix="") -> str: +def render_decoder(message: MessageAdapter) -> str: - def decode_element(element, prefix) -> str: + def decode_element(element) -> str: match type(element): case ast.Field: - return decode_field(element, message, prefix) + return decode_field(element, message) case ast.OneOf: return "\n".join( f"if proto_obj.HasField(\"{e.name}\"):\n {element.name} = proto_obj.{e.name}" @@ -180,6 +182,8 @@ def decode_element(element, prefix) -> str: return f"{element.name} = dict(proto_obj.{element.name})" elif element.value_type in message.file.enum_names: return f"{iter_items}\n {element.name}[key] = {element.value_type}(value)" + elif element.value_type in message.enum_names: + return f"{iter_items}\n {element.name}[key] = {message.name}.{element.value_type}(value)" else: return (f"{element.name} = {{ key: {message.qualified_type(element.value_type)}.decode(item) " f"for key, item in proto_obj.{element.name}.items() }}") @@ -192,6 +196,6 @@ def constructor_kwargs(elements) -> str: constructor = f"return cls(\n {constructor_kwargs(message.elements)}\n)" elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) - inner = "\n".join(decode_element(e, prefix) for e in elements) + "\n\n" + constructor + inner = "\n".join(map(decode_element, elements)) + f"\n\n{constructor}" indented_inner = textwrap.indent(inner, " ") return (f"@classmethod\ndef decode(cls, proto_obj) -> \"{message.name}\":\n{indented_inner}") From 71d44e0bc17f5632653b6d827519f4a53fde062f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 16:39:01 +0200 Subject: [PATCH 086/189] feat: MessageAdapter.parent --- auto_dev/protocols/adapters.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index f60e4cf0..3b41ffeb 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -35,6 +35,7 @@ def camel_to_snake(name: str) -> str: @dataclass class MessageAdapter: file: FileAdapter | None = field(repr=False) + parent: FileAdapter | MessageAdapter | None = field(repr=False) wrapped: Message = field(repr=False) fully_qualified_name: str elements: list[MessageElement | MessageAdapter] = field(default_factory=list, repr=False) @@ -73,7 +74,7 @@ def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: elements = [] grouped_elements = {camel_to_snake(t.__name__): [] for t in MessageElement.__args__} - for i, element in enumerate(message.elements): + for element in message.elements: key = camel_to_snake(element.__class__.__name__) if isinstance(element, Message): element = cls.from_message(element, parent_prefix=f"{parent_prefix}{message.name}.") @@ -82,6 +83,7 @@ def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: return cls( file=None, + parent=None, wrapped=message, fully_qualified_name=f"{parent_prefix}{message.name}", elements=elements, @@ -131,7 +133,7 @@ def from_file(cls, file: File) -> FileAdapter: file_elements = [] grouped_elements = {camel_to_snake(t.__name__): [] for t in FileElement.__args__} - for i, element in enumerate(file.file_elements): + for element in file.file_elements: key = camel_to_snake(element.__class__.__name__) if isinstance(element, Message): element = MessageAdapter.from_message(element) @@ -152,12 +154,13 @@ def from_file(cls, file: File) -> FileAdapter: comments=grouped_elements["comment"] ) - def set_file_adapter(message: MessageAdapter): + def set_parent(message: MessageAdapter, parent: FileAdapter | MessageAdapter): message.file = file_adapter + message.parent = parent for nested_message in message.messages: - set_file_adapter(nested_message) + set_parent(nested_message, message) for message in file_adapter.messages: - set_file_adapter(message) + set_parent(message, parent=file_adapter) return file_adapter From a5933fdf5092ae9327df4c64b3cf5ddacb366179 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 16:41:36 +0200 Subject: [PATCH 087/189] refactor: move MessageAdapter.qualified_type() -> formatter.qualified_type() --- auto_dev/protocols/adapters.py | 5 ---- auto_dev/protocols/formatter.py | 46 +++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 3b41ffeb..650ff871 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -63,11 +63,6 @@ def enum_names(self) -> set[str]: def message_names(self) -> set[str]: return {m.name for m in self.messages} - def qualified_type(self, type_name: str) -> str: - if type_name in self.enum_names or type_name in self.message_names: - return f"{self.fully_qualified_name}.{type_name}" - return type_name - @classmethod def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: """Convert a `Message` into `MessageAdapter`, handling recursion.""" diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index b0c8173e..a13d3940 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -29,8 +29,21 @@ from auto_dev.protocols.primitives import PRIMITIVE_TYPE_MAP -def render_field(field: Field) -> str: - field_type = PRIMITIVE_TYPE_MAP.get(field.type, field.type) +def qualified_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> str: + + def find_definition(scope): + if scope is None or isinstance(scope, FileAdapter): + return None + if type_name in scope.enum_names or type_name in scope.message_names: + return f"{scope.fully_qualified_name}.{type_name}" + return find_definition(scope.parent) + + qualified_name = find_definition(adapter) + return qualified_name if qualified_name is not None else PRIMITIVE_TYPE_MAP.get(type_name, type_name) + + +def render_field(field: Field, message: MessageAdapter) -> str: + field_type = qualified_type(message, field.type) match field.cardinality: case FieldCardinality.REQUIRED | None: return f"{field_type}" @@ -42,20 +55,20 @@ def render_field(field: Field) -> str: raise TypeError(f"Unexpected cardinality: {field.cardinality}") -def render_attribute(element: MessageElement | MessageAdapter) -> str: +def render_attribute(element: MessageElement | MessageAdapter, message: MessageAdapter) -> str: match type(element): case ast.Comment: return f"# {element.text}" case ast.Field: - return f"{element.name}: {render_field(element)}" + return f"{element.name}: {render_field(element, message)}" case ast.OneOf: if not all(isinstance(e, Field) for e in element.elements): raise NotImplementedError("Only implemented OneOf for Field") - inner = " | ".join(render_field(e) for e in element.elements) + inner = " | ".join(render_field(e, message) for e in element.elements) return f"{element.name}: {inner}" case adapters.MessageAdapter: elements = sorted(element.elements, key=lambda e: not isinstance(e, (MessageAdapter, ast.Enum))) - body = inner = "\n".join(map(render_attribute, elements)) + body = inner = "\n".join(render_attribute(e, element) for e in elements) encoder = render_encoder(element) decoder = render_decoder(element) body = f"{inner}\n\n{encoder}\n\n{decoder}" @@ -67,7 +80,7 @@ def render_attribute(element: MessageElement | MessageAdapter) -> str: return f"class {element.name}(IntEnum):\n{indented_members}\n" case ast.MapField: key_type = PRIMITIVE_TYPE_MAP.get(element.key_type, element.key_type) - value_type = PRIMITIVE_TYPE_MAP.get(element.value_type, element.value_type) + value_type = qualified_type(message, element.value_type) return f"{element.name}: dict[{key_type}, {value_type}]" case ast.Group | ast.Option | ast.ExtensionRange | ast.Reserved | ast.Extension: raise NotImplementedError(f"{element}") @@ -77,8 +90,8 @@ def render_attribute(element: MessageElement | MessageAdapter) -> str: def render(file: FileAdapter): - enums = "\n".join(render_attribute(e) for e in file.enums) - messages = "\n".join(render_attribute(e) for e in file.messages) + enums = "\n".join(render_attribute(e, file) for e in file.enums) + messages = "\n".join(render_attribute(e, file) for e in file.messages) return f"{enums}\n{messages}" @@ -91,14 +104,9 @@ def encode_field(element, message): value = f"{message.name.lower()}.{element.name}" elif element.type in message.file.enum_names: value = f"{message.name.lower()}.{element.name}" - elif element.type in message.message_names: - value = f"{message.qualified_type(element.type)}.encode(proto_obj.{element.name}, {instance_attr})" - return value - elif element.type in message.file.message_names: - value = f"{element.type}.encode(proto_obj.{element.name}, {instance_attr})" - return value else: - raise ValueError(f"Unexpected element: {element}") + value = f"{qualified_type(message, element.type)}.encode(proto_obj.{element.name}, {instance_attr})" + return value match element.cardinality: case FieldCardinality.REPEATED: @@ -129,7 +137,7 @@ def encode_element(element) -> str: elif element.value_type in message.enum_names: return f"{iter_items}\n proto_obj.{element.name}[key] = {message.name}.{element.value_type}(value)" else: - return f"{iter_items}\n {message.qualified_type(element.value_type)}.encode(proto_obj.{element.name}[key], value)" + return f"{iter_items}\n {qualified_type(message, element.value_type)}.encode(proto_obj.{element.name}[key], value)" case _: raise TypeError(f"Unexpected message type: {element}") @@ -146,7 +154,7 @@ def decode_field(field: ast.Field, message: MessageAdapter) -> str: elif field.type in message.enum_names: value = instance_field elif field.type in message.message_names: - value = f"{field.name} = {message.qualified_type(field.type)}.decode({instance_field})" + value = f"{field.name} = {qualified_type(message, field.type)}.decode({instance_field})" elif field.type in message.file.message_names: value = f"{field.name} = {field.type}.decode({instance_field})" else: @@ -185,7 +193,7 @@ def decode_element(element) -> str: elif element.value_type in message.enum_names: return f"{iter_items}\n {element.name}[key] = {message.name}.{element.value_type}(value)" else: - return (f"{element.name} = {{ key: {message.qualified_type(element.value_type)}.decode(item) " + return (f"{element.name} = {{ key: {qualified_type(message, element.value_type)}.decode(item) " f"for key, item in proto_obj.{element.name}.items() }}") case _: raise TypeError(f"Unexpected message element type: {element}") From 798b8264cdabf0f3cbfb98c977484546a66d3334 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 16:55:33 +0200 Subject: [PATCH 088/189] refactor: simplify encode_field and decode_field --- auto_dev/protocols/formatter.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index a13d3940..9c18ee22 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -101,9 +101,9 @@ def encode_field(element, message): if element.type in PRIMITIVE_TYPE_MAP: value = instance_attr elif element.type in message.enum_names: - value = f"{message.name.lower()}.{element.name}" + value = instance_attr elif element.type in message.file.enum_names: - value = f"{message.name.lower()}.{element.name}" + value = instance_attr else: value = f"{qualified_type(message, element.type)}.encode(proto_obj.{element.name}, {instance_attr})" return value @@ -153,12 +153,10 @@ def decode_field(field: ast.Field, message: MessageAdapter) -> str: value = instance_field elif field.type in message.enum_names: value = instance_field - elif field.type in message.message_names: - value = f"{field.name} = {qualified_type(message, field.type)}.decode({instance_field})" - elif field.type in message.file.message_names: - value = f"{field.name} = {field.type}.decode({instance_field})" - else: + elif field.type in message.file.enum_names: value = instance_field + else: + value = f"{qualified_type(message, field.type)}.decode({instance_field})" match field.cardinality: case FieldCardinality.REPEATED: From fca1b797975f38bcfe0b8dc48604efe9d91f50ba Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 17:10:26 +0200 Subject: [PATCH 089/189] refactor: primitives.jinja -> primitives.py and simplify protodantic.py --- .../primitives.py} | 0 auto_dev/protocols/protodantic.py | 25 ++++++------------- 2 files changed, 8 insertions(+), 17 deletions(-) rename auto_dev/{data/templates/protocols/primitives.jinja => protocols/primitives.py} (100%) diff --git a/auto_dev/data/templates/protocols/primitives.jinja b/auto_dev/protocols/primitives.py similarity index 100% rename from auto_dev/data/templates/protocols/primitives.jinja rename to auto_dev/protocols/primitives.py diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 1e584257..388daf98 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -3,7 +3,6 @@ import sys import inspect import subprocess # nosec: B404 -import importlib.util from pathlib import Path from types import ModuleType @@ -12,7 +11,7 @@ from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER from auto_dev.protocols.adapters import FileAdapter -from auto_dev.protocols import formatter +from auto_dev.protocols import formatter, primitives as primitives_module def get_repo_root() -> Path: @@ -34,15 +33,6 @@ def _remove_runtime_version_code(pb2_content: str) -> str: return pb2_content -def _dynamic_import(module_outpath: Path) -> ModuleType: - module_name = module_outpath.stem - spec = importlib.util.spec_from_file_location(module_name, module_outpath) - module = importlib.util.module_from_spec(spec) - sys.modules[module_name] = module - spec.loader.exec_module(module) - return module - - def _get_locally_defined_classes(module: ModuleType) -> list[type]: def locally_defined(obj): @@ -62,14 +52,14 @@ def create( content = proto_inpath.read_text() - primitives_template = env.get_template('protocols/primitives.jinja') + primitives_py = repo_root / "auto_dev" / "protocols" / "primitives.py" protodantic_template = env.get_template('protocols/protodantic.jinja') hypothesis_template = env.get_template('protocols/hypothesis.jinja') - primitives = primitives_template.render() - primitives_outpath = code_outpath.parent / "primitives.py" - primitives_outpath.write_text(primitives) - primitives_module = _dynamic_import(primitives_outpath) + primitives_outpath = code_outpath.parent / primitives_py.name + primitives_outpath.write_text(primitives_py.read_text()) + + models_import_path = _compute_import_path(code_outpath, repo_root) primitives_import_path = _compute_import_path(primitives_outpath, repo_root) subprocess.run( @@ -89,6 +79,7 @@ def create( integer_primitives = [p for p in primitives if issubclass(p, int)] file = FileAdapter.from_file(Parser().parse(content)) + code = generated_code = protodantic_template.render( file=file, formatter=formatter, @@ -98,7 +89,6 @@ def create( ) code_outpath.write_text(generated_code) - models_import_path = _compute_import_path(code_outpath, repo_root) message_path = str(Path(models_import_path).parent) pb2_path = code_outpath.parent / f"{proto_inpath.stem}_pb2.py" @@ -118,3 +108,4 @@ def create( messages_pb2=messages_pb2, ) test_outpath.write_text(generated_tests) + breakpoint() From c7161c4fb4d9cb325a1f701e3a37233fbe351339 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 17:23:28 +0200 Subject: [PATCH 090/189] fix: add `from __future__ import annotations` to jinja template --- auto_dev/data/templates/protocols/protodantic.jinja | 2 ++ auto_dev/protocols/formatter.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 9986eb74..ccc90ab2 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -1,3 +1,5 @@ +from __future__ import annotations + from enum import IntEnum from pydantic import BaseModel diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 9c18ee22..7faf4e29 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -144,7 +144,7 @@ def encode_element(element) -> str: elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) inner = "\n".join(map(encode_element, elements)) indented_inner = textwrap.indent(inner, " ") - return f"@staticmethod\ndef encode(proto_obj, {message.name.lower()}: \"{message.name}\") -> None:\n{indented_inner}" + return f"@staticmethod\ndef encode(proto_obj, {message.name.lower()}: {message.name}) -> None:\n{indented_inner}" def decode_field(field: ast.Field, message: MessageAdapter) -> str: @@ -204,4 +204,4 @@ def constructor_kwargs(elements) -> str: elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) inner = "\n".join(map(decode_element, elements)) + f"\n\n{constructor}" indented_inner = textwrap.indent(inner, " ") - return (f"@classmethod\ndef decode(cls, proto_obj) -> \"{message.name}\":\n{indented_inner}") + return (f"@classmethod\ndef decode(cls, proto_obj) -> {message.name}:\n{indented_inner}") From 2b754c5ed5968e4b3714e00ab4496daf3f00d98e Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 17:23:42 +0200 Subject: [PATCH 091/189] fix: add FLOAT_PRIMITIVES, INTEGER_PRIMITIVES and PRIMITIVE_TYPE_MAP to primitives.py --- auto_dev/protocols/primitives.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/auto_dev/protocols/primitives.py b/auto_dev/protocols/primitives.py index 858e4cd2..841f0779 100644 --- a/auto_dev/protocols/primitives.py +++ b/auto_dev/protocols/primitives.py @@ -159,3 +159,30 @@ class SFixed64(BaseConstrainedInt): def min(cls): return min_int64 @classmethod def max(cls): return max_int64 + + +FLOAT_PRIMITIVES = { + "double": "Double", + "float": "Float", +} + +INTEGER_PRIMITIVES = { + "int32": "Int32", + "int64": "Int64", + "uint32": "UInt32", + "uint64": "UInt64", + "sint32": "SInt32", + "sint64": "SInt64", + "fixed32": "Fixed32", + "fixed64": "Fixed64", + "sfixed32": "SFixed32", + "sfixed64": "SFixed64", +} + +PRIMITIVE_TYPE_MAP = { + "bool": "bool", + "string": "str", + "bytes": "bytes", + **FLOAT_PRIMITIVES, + **INTEGER_PRIMITIVES, +} From 19d8bd6cd6d67947daf593a89dcdb71527e0cf0a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 22:05:07 +0200 Subject: [PATCH 092/189] fix: encode and decode ast.Comment --- auto_dev/protocols/formatter.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 7faf4e29..c015f9e4 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -121,6 +121,8 @@ def render_encoder(message: MessageAdapter) -> str: def encode_element(element) -> str: match type(element): + case ast.Comment: + return f"# {element.text}" case ast.Field: return encode_field(element, message) case ast.OneOf: @@ -175,6 +177,8 @@ def render_decoder(message: MessageAdapter) -> str: def decode_element(element) -> str: match type(element): + case ast.Comment: + return f"# {element.text}" case ast.Field: return decode_field(element, message) case ast.OneOf: From 44c339099a2d919334295d0f8630259519493117 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Wed, 2 Apr 2025 22:18:23 +0200 Subject: [PATCH 093/189] feat: make update_protocol_tests --- Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Makefile b/Makefile index 52ee166a..650ef13d 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ clean: install: poetry run bash auto_dev/data/repo/templates/autonomy/install.sh + make update_protocol_tests lint: poetry run adev -v -n 0 lint -p . -co @@ -19,6 +20,7 @@ fmt: poetry run adev -n 0 fmt -p . -co test: + make update_protocol_tests poetry run adev -v test -p tests .PHONY: docs @@ -41,3 +43,18 @@ new_env: git pull poetry env remove --all make install + + +PROTOCOLS_URL = https://github.com/StationsStation/capitalisation_station/archive/main.zip +PROTOCOLS_DIR = ${ROOT_DIR}tests/data/protocols/capitalisation_station +TEMP_ZIP = .capitalisation_station.zip + +update_protocol_tests: + @echo "Downloading protocol specification for testing..." + @curl -L $(PROTOCOLS_URL) -o $(TEMP_ZIP) + @echo "Extracting protocol specification..." + @mkdir -p $(PROTOCOLS_DIR) + @unzip -q $(TEMP_ZIP) "capitalisation_station-main/specs/protocols/*" -d .tmp_protocols + @mv .tmp_protocols/capitalisation_station-main/specs/protocols/* $(PROTOCOLS_DIR)/ + @rm -rf .tmp_protocols $(TEMP_ZIP) + @echo "Protocols updated in $(PROTOCOLS_DIR)" From 121ae565d26a6ce20ef459edb7f48aac14fdbc22 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 3 Apr 2025 16:10:15 +0200 Subject: [PATCH 094/189] chore: tests/data/protocols/.capitalisation_station as hidden dir for .gitignore --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 650ef13d..084d3af5 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ new_env: PROTOCOLS_URL = https://github.com/StationsStation/capitalisation_station/archive/main.zip -PROTOCOLS_DIR = ${ROOT_DIR}tests/data/protocols/capitalisation_station +PROTOCOLS_DIR = ${ROOT_DIR}tests/data/protocols/.capitalisation_station TEMP_ZIP = .capitalisation_station.zip update_protocol_tests: From 181e9c20f5b83b0ad30acc01c88879dd2017d938 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 3 Apr 2025 16:11:06 +0200 Subject: [PATCH 095/189] fix: remove breakpoint --- auto_dev/protocols/protodantic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 388daf98..c2e7c61c 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -108,4 +108,3 @@ def create( messages_pb2=messages_pb2, ) test_outpath.write_text(generated_tests) - breakpoint() From 0f4a02e1cfff1c17116f3d22fa1d81710b04c625 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 3 Apr 2025 16:13:25 +0200 Subject: [PATCH 096/189] feat: utils.file_swapper --- auto_dev/utils.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/auto_dev/utils.py b/auto_dev/utils.py index a4181989..ee954824 100644 --- a/auto_dev/utils.py +++ b/auto_dev/utils.py @@ -232,6 +232,23 @@ def restore_directory(): os.chdir(original_dir) +@contextmanager +def file_swapper(file_a: str | Path, file_b: str | Path): + """Temporarily swap the location of two files.""" + + def swap(swap_file: str): + shutil.move(file_a, swap_file) + shutil.move(file_b, file_a) + shutil.move(swap_file, file_b) + + with tempfile.NamedTemporaryFile() as tmp_file: + try: + swap(tmp_file.name) + yield + finally: + swap(tmp_file.name) + + @contextmanager def folder_swapper(dir_a: str | Path, dir_b: str | Path): """A custom context manager that swaps the contents of two folders, allows the execution of logic From 746c7bb797b550049b8efca60ceb18151037357a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Thu, 3 Apr 2025 16:14:00 +0200 Subject: [PATCH 097/189] tests: utils.file_swapper --- tests/test_utils.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 194d5e15..e23af27b 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -19,6 +19,7 @@ remove_prefix, remove_suffix, write_to_file, + file_swapper, folder_swapper, has_package_code_changed, ) @@ -155,6 +156,27 @@ def test_remove_suffix(): assert remove_suffix("", "xyz") == "" +def test_file_swapper(): + """Test file_swapper""" + + content_a = "AAA" + content_b = "BBB" + + with tempfile.TemporaryDirectory() as tmp_dir: + tmp_path = Path(tmp_dir) + file_a = tmp_path / "file_a.txt" + file_b = tmp_path / "file_b.txt" + file_a.write_text(content_a) + file_b.write_text(content_b) + + with file_swapper(file_a, file_b): + assert file_a.read_text() == content_b + assert file_b.read_text() == content_a + + assert file_a.read_text() == content_a + assert file_b.read_text() == content_b + + class TestFolderSwapper: """TestFolderSwapper.""" From 5c2746494bb48393493b1a4fd334a7c805852a1e Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 4 Apr 2025 15:53:54 +0200 Subject: [PATCH 098/189] fix: message_import_path --- auto_dev/data/templates/protocols/hypothesis.jinja | 2 +- auto_dev/protocols/protodantic.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 389533a7..3ba91cf0 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -1,7 +1,7 @@ from hypothesis import given from hypothesis import strategies as st -from {{ message_path }} import {{ messages_pb2 }} +from {{ message_import_path }} import {{ messages_pb2 }} from {{ primitives_import_path }} import ( {%- for primitive in float_primitives %} diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index c2e7c61c..a3c7b542 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -89,13 +89,12 @@ def create( ) code_outpath.write_text(generated_code) - message_path = str(Path(models_import_path).parent) - pb2_path = code_outpath.parent / f"{proto_inpath.stem}_pb2.py" pb2_content = pb2_path.read_text() pb2_content = _remove_runtime_version_code(pb2_content) pb2_path.write_text(pb2_content) + message_import_path = ".".join(models_import_path.split(".")[:-1]) or "." messages_pb2 = pb2_path.with_suffix("").name tests = generated_tests = hypothesis_template.render( @@ -104,7 +103,7 @@ def create( integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, models_import_path=models_import_path, - message_path=message_path, + message_import_path=message_import_path, messages_pb2=messages_pb2, ) test_outpath.write_text(generated_tests) From e6fea2b83146426c8584d44eeddeb56c52f73ef8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 4 Apr 2025 15:54:33 +0200 Subject: [PATCH 099/189] fix: dialogues.jinja --- auto_dev/data/templates/protocols/dialogues.jinja | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/auto_dev/data/templates/protocols/dialogues.jinja b/auto_dev/data/templates/protocols/dialogues.jinja index 4909603d..76027df3 100644 --- a/auto_dev/data/templates/protocols/dialogues.jinja +++ b/auto_dev/data/templates/protocols/dialogues.jinja @@ -27,21 +27,21 @@ class {{ camel_name }}Dialogue(Dialogue): INITIAL_PERFORMATIVES: FrozenSet[Message.Performative] = frozenset({ {%- for performative in initial_performatives %} - {{ camel_name }}Message.Performative.{{ performative }}, + {{ camel_name }}Message.Performative.{{ performative|upper }}, {%- endfor %} }) TERMINAL_PERFORMATIVES: FrozenSet[Message.Performative] = frozenset({ {%- for performative in terminal_performatives %} - {{ camel_name }}Message.Performative.{{ performative }}, + {{ camel_name }}Message.Performative.{{ performative|upper }}, {%- endfor %} }) VALID_REPLIES: Dict[Message.Performative, FrozenSet[Message.Performative]] = { {%- for performative, replies in valid_replies.items() %} - {{ camel_name }}Message.Performative.{{ performative }}: {% if replies|length > 0 %}frozenset({ + {{ camel_name }}Message.Performative.{{ performative|upper }}: {% if replies|length > 0 %}frozenset({ {%- for reply in replies %} - {{ camel_name }}Message.Performative.{{ reply }}, + {{ camel_name }}Message.Performative.{{ reply|upper }}, {%- endfor %} - }){% else %}frozenset({}){% endif %}, + }){% else %}frozenset(){% endif %}, {%- endfor %} } @@ -86,7 +86,7 @@ class Base{{ camel_name }}Dialogues(Dialogues, ABC): END_STATES = frozenset({ {%- for state in end_states %} - {{ camel_name }}Message.EndState.{{ state.name }}{{ "," if not loop.last }} + {{ camel_name }}Dialogue.EndState.{{ state.name }}, {%- endfor %} }) _keep_terminal_state_dialogues = {{ keep_terminal_state_dialogues }} @@ -107,7 +107,7 @@ class Base{{ camel_name }}Dialogues(Dialogues, ABC): Dialogues.__init__( self, self_address=self_address, - end_states=cast(FrozenSet[Dialogue.EndState], self.END_STATES), + end_states=cast(frozenset[Dialogue.EndState], self.END_STATES), message_class={{ camel_name }}Message, dialogue_class=dialogue_class, role_from_first_message=role_from_first_message, From 66900e8b5aa5a20f506cb3306731ca90bd59e335 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 4 Apr 2025 21:34:39 +0200 Subject: [PATCH 100/189] tests: add empty_message.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 7b07be9f..c577e9c0 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -28,6 +28,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["optional_enum.proto"], PROTO_FILES["repeated_enum.proto"], PROTO_FILES["nested_enum.proto"], + PROTO_FILES["empty_message.proto"], PROTO_FILES["simple_message.proto"], PROTO_FILES["message_reference.proto"], PROTO_FILES["nested_message.proto"], From df5db5114ffd8930d52cd8484d9651f37e74aaa2 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 4 Apr 2025 21:47:44 +0200 Subject: [PATCH 101/189] feat: add docstrings to generated pydantic model code --- auto_dev/protocols/formatter.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index c015f9e4..27414cbe 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -73,11 +73,19 @@ def render_attribute(element: MessageElement | MessageAdapter, message: MessageA decoder = render_decoder(element) body = f"{inner}\n\n{encoder}\n\n{decoder}" indented_body = textwrap.indent(body, " ") - return f"\nclass {element.name}(BaseModel):\n{indented_body}\n" + return ( + f"\nclass {element.name}(BaseModel):\n" + f" \"\"\"{element.name}\"\"\"\n\n" + f"{indented_body}\n" + ) case ast.Enum: members = "\n".join(f"{val.name} = {val.number}" for val in element.elements) indented_members = textwrap.indent(members, " ") - return f"class {element.name}(IntEnum):\n{indented_members}\n" + return ( + f"class {element.name}(IntEnum):\n" + f" \"\"\"{element.name}\"\"\"\n\n" + f"{indented_members}\n" + ) case ast.MapField: key_type = PRIMITIVE_TYPE_MAP.get(element.key_type, element.key_type) value_type = qualified_type(message, element.value_type) @@ -146,8 +154,12 @@ def encode_element(element) -> str: elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) inner = "\n".join(map(encode_element, elements)) indented_inner = textwrap.indent(inner, " ") - return f"@staticmethod\ndef encode(proto_obj, {message.name.lower()}: {message.name}) -> None:\n{indented_inner}" - + return ( + "@staticmethod\n" + f"def encode(proto_obj, {message.name.lower()}: {message.name}) -> None:\n" + f" \"\"\"Encode {message.name} to protobuf.\"\"\"\n\n" + f"{indented_inner}\n" + ) def decode_field(field: ast.Field, message: MessageAdapter) -> str: instance_field = f"proto_obj.{field.name}" @@ -208,4 +220,9 @@ def constructor_kwargs(elements) -> str: elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) inner = "\n".join(map(decode_element, elements)) + f"\n\n{constructor}" indented_inner = textwrap.indent(inner, " ") - return (f"@classmethod\ndef decode(cls, proto_obj) -> {message.name}:\n{indented_inner}") + return ( + "@classmethod\n" + f"def decode(cls, proto_obj) -> {message.name}:\n" + f" \"\"\"Decode proto_obj to {message.name}.\"\"\"\n\n" + f"{indented_inner}\n" + ) \ No newline at end of file From 15c9d2cdab9a348bbd9be001cecc39adf1cd0005 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 11:12:33 +0200 Subject: [PATCH 102/189] feat: field.cardinality handling for message encoding / decoding --- auto_dev/protocols/formatter.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 27414cbe..5eb0d432 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -112,13 +112,25 @@ def encode_field(element, message): value = instance_attr elif element.type in message.file.enum_names: value = instance_attr - else: - value = f"{qualified_type(message, element.type)}.encode(proto_obj.{element.name}, {instance_attr})" - return value + else: # Message + qualified = qualified_type(message, element.type) + if element.cardinality == FieldCardinality.REPEATED: + return ( + f"for item in {instance_attr}:\n" + f" {qualified}.encode(proto_obj.{element.name}.add(), item)" + ) + elif element.cardinality == FieldCardinality.OPTIONAL: + return ( + f"if {instance_attr} is not None:\n" + f" {qualified}.encode(proto_obj.{element.name}, {instance_attr})" + ) + else: + return f"{qualified}.encode(proto_obj.{element.name}, {instance_attr})" match element.cardinality: case FieldCardinality.REPEATED: - return f"proto_obj.{element.name}.extend({value})" + iter_items = f"for item in {value}:\n" + return f"{iter_items} proto_obj.{element.name}.append(item)" case FieldCardinality.OPTIONAL: return f"if {instance_attr} is not None:\n proto_obj.{element.name} = {instance_attr}" case _: @@ -170,7 +182,15 @@ def decode_field(field: ast.Field, message: MessageAdapter) -> str: elif field.type in message.file.enum_names: value = instance_field else: - value = f"{qualified_type(message, field.type)}.decode({instance_field})" + qualified = qualified_type(message, field.type) + if field.cardinality == FieldCardinality.REPEATED: + return f"{field.name} = [{qualified}.decode(item) for item in {instance_field}]" + elif field.cardinality == FieldCardinality.OPTIONAL: + return (f"{field.name} = {qualified}.decode({instance_field}) " + f"if {instance_field} is not None and proto_obj.HasField(\"{field.name}\") " + f"else None") + else: + return f"{field.name} = {qualified}.decode({instance_field})" match field.cardinality: case FieldCardinality.REPEATED: From fe5a84be0a5636b83578da453f958d6f362723a7 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 11:18:01 +0200 Subject: [PATCH 103/189] tests: add repeated_message.proto --- tests/data/protocols/protobuf/repeated_message.proto | 12 ++++++++++++ tests/test_protocol.py | 1 + 2 files changed, 13 insertions(+) create mode 100644 tests/data/protocols/protobuf/repeated_message.proto diff --git a/tests/data/protocols/protobuf/repeated_message.proto b/tests/data/protocols/protobuf/repeated_message.proto new file mode 100644 index 00000000..5fdef615 --- /dev/null +++ b/tests/data/protocols/protobuf/repeated_message.proto @@ -0,0 +1,12 @@ +// repeated_message.proto + +syntax = "proto3"; + +message OuterMessage {} + +message RepeatedMessage { + message InnerMessage {} + + repeated OuterMessage outer_message = 1; + repeated InnerMessage inner_message = 2; +} diff --git a/tests/test_protocol.py b/tests/test_protocol.py index c577e9c0..81821b1e 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -30,6 +30,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["nested_enum.proto"], PROTO_FILES["empty_message.proto"], PROTO_FILES["simple_message.proto"], + PROTO_FILES["repeated_message.proto"], PROTO_FILES["message_reference.proto"], PROTO_FILES["nested_message.proto"], PROTO_FILES["deeply_nested_message.proto"], From c94813dba5f2c071baef388b48be272a946091b0 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 13:03:03 +0200 Subject: [PATCH 104/189] refactor: repeated_message.proto --- tests/data/protocols/protobuf/repeated_message.proto | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/data/protocols/protobuf/repeated_message.proto b/tests/data/protocols/protobuf/repeated_message.proto index 5fdef615..a40aa614 100644 --- a/tests/data/protocols/protobuf/repeated_message.proto +++ b/tests/data/protocols/protobuf/repeated_message.proto @@ -2,11 +2,11 @@ syntax = "proto3"; -message OuterMessage {} +message RepeatedOuterMessage {} message RepeatedMessage { - message InnerMessage {} + message RepeatedInnerMessage {} - repeated OuterMessage outer_message = 1; - repeated InnerMessage inner_message = 2; + repeated RepeatedOuterMessage repeated_outer_message = 1; + repeated RepeatedInnerMessage repeated_inner_message = 2; } From 0a3003bf6ac091598e0741457c3216bea30322dc Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 13:04:02 +0200 Subject: [PATCH 105/189] tests: add optional_message.proto --- tests/data/protocols/protobuf/optional_message.proto | 12 ++++++++++++ tests/test_protocol.py | 1 + 2 files changed, 13 insertions(+) create mode 100644 tests/data/protocols/protobuf/optional_message.proto diff --git a/tests/data/protocols/protobuf/optional_message.proto b/tests/data/protocols/protobuf/optional_message.proto new file mode 100644 index 00000000..f03156e0 --- /dev/null +++ b/tests/data/protocols/protobuf/optional_message.proto @@ -0,0 +1,12 @@ +// optional_message.proto + +syntax = "proto3"; + +message OptionalOuterMessage {} + +message OptionalMessage { + message OptionalInnerMessage {} + + optional OptionalOuterMessage optional_outer_message = 1; + optional OptionalInnerMessage optional_inner_message = 2; +} diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 81821b1e..f6e3d2d2 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -31,6 +31,7 @@ def _get_proto_files() -> dict[str, Path]: PROTO_FILES["empty_message.proto"], PROTO_FILES["simple_message.proto"], PROTO_FILES["repeated_message.proto"], + PROTO_FILES["optional_message.proto"], PROTO_FILES["message_reference.proto"], PROTO_FILES["nested_message.proto"], PROTO_FILES["deeply_nested_message.proto"], From d20b40b2870482cf8c6fce05b7c20cebc3af77d6 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 13:04:37 +0200 Subject: [PATCH 106/189] fix: encoding optional message --- auto_dev/protocols/formatter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 5eb0d432..359da5f5 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -122,7 +122,9 @@ def encode_field(element, message): elif element.cardinality == FieldCardinality.OPTIONAL: return ( f"if {instance_attr} is not None:\n" - f" {qualified}.encode(proto_obj.{element.name}, {instance_attr})" + f" temp = proto_obj.{element.name}.__class__()\n" + f" {qualified}.encode(temp, {instance_attr})\n" + f" proto_obj.{element.name}.CopyFrom(temp)" ) else: return f"{qualified}.encode(proto_obj.{element.name}, {instance_attr})" From 5ec18309fa0c55cfef430e3e1f0a65f75e5d8c75 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 13:33:14 +0200 Subject: [PATCH 107/189] chore: improve readability hypothesis.jinja rendered output --- .../data/templates/protocols/hypothesis.jinja | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 3ba91cf0..2b28ca59 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -41,7 +41,7 @@ st.register_type_strategy( {%- set scalar_map = scalar_map.update({primitive.__name__.lower(): primitive.__name__}) %} {%- endfor %} -{# Define a list of enum names #} +{#- Define a list of enum names #} {%- set enum_names = [] %} {%- for enum in file.enums %} {%- set enum_names = enum_names.append( enum.name ) %} @@ -85,20 +85,20 @@ st.register_type_strategy( {{ message.name|lower }}_strategy = st.builds( {{ prefix }}{{ message.name }}, {%- for element in message.fields %} - {%- if element.type in nested_names %} - {{ element.name }}={{ element.type|lower }}_strategy, - {%- elif element.cardinality == "OPTIONAL" %} - {{ element.name }}={{ optional_strategy(element) }}, - {%- elif element.cardinality == "REPEATED" %} - {{ element.name }}={{ repeated_strategy(element) }}, - {%- else %} - {{ element.name }}={{ scalar_strategy(element) }}, - {%- endif %} + {%- if element.type in nested_names %} + {{ element.name }}={{ element.type|lower }}_strategy, + {%- elif element.cardinality == "OPTIONAL" %} + {{ element.name }}={{ optional_strategy(element) }}, + {%- elif element.cardinality == "REPEATED" %} + {{ element.name }}={{ repeated_strategy(element) }}, + {%- else %} + {{ element.name }}={{ scalar_strategy(element) }}, + {%- endif %} {%- endfor %} {%- for element in message.map_fields %} - {%- if element.value_type in message.file.enum_names %} - {{ element.name }}=st.dictionaries(keys=st.text(), values=st.sampled_from({{ element.value_type }})), - {%- endif %} + {%- if element.value_type in message.file.enum_names %} + {{ element.name }}=st.dictionaries(keys=st.text(), values=st.sampled_from({{ element.value_type }})), + {%- endif %} {%- endfor %} ) {%- endmacro %} @@ -123,4 +123,4 @@ def test_{{ message.name|lower }}({{ message.name|lower }}: {{ message.name }}): result = {{ message.name }}.decode(proto_obj) assert id({{ message.name|lower }}) != id(result) assert {{ message.name|lower }} == result -{%- endfor %} +{% endfor %} From 5b700d95005d4355520bf447a10718849a208e88 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 19:19:18 +0200 Subject: [PATCH 108/189] feat: auto-update forward refs in protodantic.jinja --- auto_dev/data/templates/protocols/protodantic.jinja | 3 +++ 1 file changed, 3 insertions(+) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index ccc90ab2..0ce4dbe1 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -16,3 +16,6 @@ from {{ primitives_import_path }} import ( MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {{ formatter.render(file) }} + +for cls in BaseModel.__subclasses__(): + cls.update_forward_refs() From 304dd7c4247dd7190e75c47bf6cac8433cb62e44 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 19:21:19 +0200 Subject: [PATCH 109/189] fix: simplify and correct message strategies using st.from_type --- .../data/templates/protocols/hypothesis.jinja | 75 +------------------ 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 2b28ca59..a460de12 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -35,82 +35,9 @@ st.register_type_strategy( ) {%- endfor %} -{#- Define a map of scalars -#} -{%- set scalar_map = {"bool": "bool", "string": "str", "bytes": "bytes"} %} -{%- for primitive in integer_primitives + float_primitives %} - {%- set scalar_map = scalar_map.update({primitive.__name__.lower(): primitive.__name__}) %} -{%- endfor %} - -{#- Define a list of enum names #} -{%- set enum_names = [] %} -{%- for enum in file.enums %} -{%- set enum_names = enum_names.append( enum.name ) %} -{%- endfor %} - -{%- macro scalar_strategy(field) -%} - {%- if field.type in enum_names -%} - {{ field.type|lower }}_strategy - {%- else -%} - st.builds({{ scalar_map.get(field.type, field.type) }}) - {%- endif -%} -{%- endmacro -%} - -{%- macro optional_strategy(field) -%} - st.one_of(st.none(), {{ scalar_strategy(field) }}) -{%- endmacro -%} - -{%- macro repeated_strategy(field) -%} - st.lists({{ scalar_strategy(field) }}) -{%- endmacro -%} - -{%- macro enum_strategy(enum, prefix="") -%} -{{ enum.name|lower }}_strategy = st.sampled_from({{ prefix + enum.name }}) -{%- endmacro -%} - -{%- macro message_strategy(message, prefix="") -%} -{#- Build a list of nested enum and message names -#} -{%- set nested_names = [] -%} -{%- for m in message.enums + message.messages %} -{%- set nested_names = nested_names.append(m.name) %} -{%- endfor %} - -{%- for nested in message.enums %} -{{ enum_strategy(nested, prefix + message.name + ".") }} -{%- endfor %} - -{%- for nested in message.messages %} -{{ message_strategy(nested, prefix + message.name + ".") }} -{%- endfor %} - -{{ message.name|lower }}_strategy = st.builds( - {{ prefix }}{{ message.name }}, - {%- for element in message.fields %} - {%- if element.type in nested_names %} - {{ element.name }}={{ element.type|lower }}_strategy, - {%- elif element.cardinality == "OPTIONAL" %} - {{ element.name }}={{ optional_strategy(element) }}, - {%- elif element.cardinality == "REPEATED" %} - {{ element.name }}={{ repeated_strategy(element) }}, - {%- else %} - {{ element.name }}={{ scalar_strategy(element) }}, - {%- endif %} - {%- endfor %} - {%- for element in message.map_fields %} - {%- if element.value_type in message.file.enum_names %} - {{ element.name }}=st.dictionaries(keys=st.text(), values=st.sampled_from({{ element.value_type }})), - {%- endif %} - {%- endfor %} -) -{%- endmacro %} - -{# Define strategies for Enums at the top level #} -{%- for enum in file.enums %} -{{ enum_strategy(enum) }} -{%- endfor %} - {# Define strategies for each message #} {%- for message in file.messages %} -{{ message_strategy(message) }} +{{ message.name|lower }}_strategy = st.from_type({{ message.name }}) {%- endfor %} {# Define tests for each message #} From 4158efbea5c3194a3d9ea5b22e5c6e0a03aa5ee8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 20:32:40 +0200 Subject: [PATCH 110/189] feat: performatives.parse_annotation --- auto_dev/protocols/performatives.py | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 auto_dev/protocols/performatives.py diff --git a/auto_dev/protocols/performatives.py b/auto_dev/protocols/performatives.py new file mode 100644 index 00000000..662ec023 --- /dev/null +++ b/auto_dev/protocols/performatives.py @@ -0,0 +1,37 @@ + + +SCALAR_MAP = { + "int": "Int64", + "float": "Double", + "bool": "bool", + "str": "str", + "bytes": "bytes", +} + + +def parse_annotation(annotation: str) -> str: + """Parse Performative annotation""" + + if annotation.startswith("pt:"): + core = annotation[3:] + elif annotation.startswith("ct:"): + return annotation[3:] + else: + raise ValueError(f"Unknown annotation prefix in: {annotation}") + + if core.startswith("optional[") and core.endswith("]"): + inner = core[len("optional["):-1] + return f"{parse_annotation(inner)} | None" + elif core.startswith("list[") and core.endswith("]"): + inner = core[len("list["):-1] + return f"list[{parse_annotation(inner)}]" + elif core.startswith("dict[") and core.endswith("]"): + inner = core[len("dict["):-1] + key_str, value_str = (part.strip() for part in inner.split(",", 1)) + return f"dict[{parse_annotation(key_str)}, {parse_annotation(value_str)}]" + elif core.startswith("union[") and core.endswith("]"): + inner = core[len("union["):-1] + parts = (parse_annotation(p.strip()) for p in inner.split(",")) + return " | ".join(parts) + else: + return SCALAR_MAP[core] From f80f122196f67c8dfbd14147e3aa20513b3f0fa0 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 20:33:02 +0200 Subject: [PATCH 111/189] test: performatives.parse_annotation --- tests/test_protocol.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index f6e3d2d2..b5cdbac6 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -6,6 +6,7 @@ from jinja2 import Template, Environment, FileSystemLoader from auto_dev.protocols import protodantic +from auto_dev.protocols import performatives @functools.lru_cache() @@ -52,3 +53,17 @@ def test_protodantic(proto_path: Path): protodantic.create(proto_path, code_out, test_out) exit_code = pytest.main([tmp_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) assert exit_code == 0 + + +@pytest.mark.parametrize("annotation, expected", + [ + ("pt:int", "Int64"), + ("pt:float", "Double"), + ("pt:list[pt:int]", "list[Int64]"), + ("pt:optional[pt:int]", "Int64 | None"), + ("pt:dict[pt:str, pt:int]", "dict[str, Int64]"), + ] +) +def test_parse_performative_annotation(annotation: str, expected: str): + """Test parse_performative_annotation""" + assert performatives.parse_annotation(annotation) == expected From 433a309b43004f99d45b550c8e581eee7101d887 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 20:34:14 +0200 Subject: [PATCH 112/189] tests: complex performative annotation parsing --- tests/test_protocol.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index b5cdbac6..3a186f61 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -62,6 +62,8 @@ def test_protodantic(proto_path: Path): ("pt:list[pt:int]", "list[Int64]"), ("pt:optional[pt:int]", "Int64 | None"), ("pt:dict[pt:str, pt:int]", "dict[str, Int64]"), + ("pt:list[pt:union[pt:dict[pt:str, pt:int], pt:list[pt:bytes]]]", "list[dict[str, Int64] | list[bytes]]"), + ("pt:optional[pt:dict[pt:union[pt:str, pt:int], pt:list[pt:union[pt:float, pt:bool]]]]", "dict[str | Int64, list[Double | bool]] | None") ] ) def test_parse_performative_annotation(annotation: str, expected: str): From db8296a5b99e142f3edf89fde92e4ba68731da5e Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 5 Apr 2025 20:36:50 +0200 Subject: [PATCH 113/189] fix: performatives.parse_annotation with _split_top_level --- auto_dev/protocols/performatives.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/auto_dev/protocols/performatives.py b/auto_dev/protocols/performatives.py index 662ec023..003372d4 100644 --- a/auto_dev/protocols/performatives.py +++ b/auto_dev/protocols/performatives.py @@ -9,6 +9,25 @@ } +def _split_top_level(s: str, sep: str = ",") -> list[str]: + parts = [] + current = [] + depth = 0 + for c in s: + if c == "[": + depth += 1 + elif c == "]": + depth -= 1 + if c == sep and depth == 0: + parts.append("".join(current).strip()) + current = [] + else: + current.append(c) + if current: + parts.append("".join(current).strip()) + return parts + + def parse_annotation(annotation: str) -> str: """Parse Performative annotation""" @@ -27,11 +46,11 @@ def parse_annotation(annotation: str) -> str: return f"list[{parse_annotation(inner)}]" elif core.startswith("dict[") and core.endswith("]"): inner = core[len("dict["):-1] - key_str, value_str = (part.strip() for part in inner.split(",", 1)) + key_str, value_str = _split_top_level(inner) return f"dict[{parse_annotation(key_str)}, {parse_annotation(value_str)}]" elif core.startswith("union[") and core.endswith("]"): inner = core[len("union["):-1] - parts = (parse_annotation(p.strip()) for p in inner.split(",")) - return " | ".join(parts) + parts = _split_top_level(inner) + return " | ".join(parse_annotation(p) for p in parts) else: return SCALAR_MAP[core] From ee1c9ce24e4e0612b70b978558137d5e70d3f51d Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 11:52:58 +0200 Subject: [PATCH 114/189] feat: test_dialogues.jinja --- .../templates/protocols/test_dialogues.jinja | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 auto_dev/data/templates/protocols/test_dialogues.jinja diff --git a/auto_dev/data/templates/protocols/test_dialogues.jinja b/auto_dev/data/templates/protocols/test_dialogues.jinja new file mode 100644 index 00000000..801de8bf --- /dev/null +++ b/auto_dev/data/templates/protocols/test_dialogues.jinja @@ -0,0 +1,66 @@ +{{ header }} + +"""Test dialogues module for the {{ snake_name }} protocol.""" + +from unittest.mock import MagicMock + +from pydantic import BaseModel +from hypothesis import strategies as st +from hypothesis import given + +from packages.{{ author }}.protocols.{{ snake_name }}.dialogues import ( + {{ camel_name }}Dialogue, + {{ camel_name }}Dialogues, +) +from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message +from packages.{{ author }}.protocols.{{ snake_name }}.primitives import ( + Int64, + Double, +) +from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( + {%- for custom_type in custom_types %} + {{ custom_type }}, + {%- endfor %} +) + + +def shallow_dump(model: BaseModel) -> dict: + """Shallow dump pydantic model.""" + + return {name: getattr(model, name) for name in model.__fields__} + + +def validate_dialogue(performative, model): + """Validate successful dialogue instantiation.""" + + dialogues = {{ camel_name }}Dialogues( + name="test_{{ snake_name }}_dialogues", + skill_context=MagicMock(), + ) + + dialogue = dialogues.create( + counterparty="dummy_counterparty", + performative=performative, + **shallow_dump(model), + ) + + assert dialogue is not None + +{# Define strategies for each performative #} +{%- for initial_performative, fields in initial_performative_types.items() %} +class {{ snake_to_camel(initial_performative) }}(BaseModel): + """Model for the `{{ initial_performative|upper }}` initial speech act performative.""" + {%- for field_name, field_type in fields.items() %} + {{ field_name }}: {{ field_type }} + {%- endfor %} + +{% endfor %} + + +{%- for initial_performative in initial_performative_types %} +@given(st.from_type({{ snake_to_camel(initial_performative) }})) +def test_{{ initial_performative }}_dialogues(model): + """Test for the '{{ initial_performative|upper }}' protocol.""" + validate_dialogue({{ camel_name }}Message.Performative.{{ initial_performative|upper }}, model) + +{% endfor %} From aad889b21488ab3fca9289308bbff1d622c04d86 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 12:44:41 +0200 Subject: [PATCH 115/189] feat: primitive_strategies.jinja --- .../protocols/primitive_strategies.jinja | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 auto_dev/data/templates/protocols/primitive_strategies.jinja diff --git a/auto_dev/data/templates/protocols/primitive_strategies.jinja b/auto_dev/data/templates/protocols/primitive_strategies.jinja new file mode 100644 index 00000000..b4efabc4 --- /dev/null +++ b/auto_dev/data/templates/protocols/primitive_strategies.jinja @@ -0,0 +1,26 @@ +from hypothesis import given +from hypothesis import strategies as st + +from {{ primitives_import_path }} import ( + {%- for primitive in float_primitives %} + {{ primitive.__name__ }}, + {%- endfor %} + {%- for primitive in integer_primitives %} + {{ primitive.__name__ }}, + {%- endfor %} +) + +{# Register strategies for floating-point types #} +{%- for primitive in float_primitives %} +st.register_type_strategy( + {{ primitive.__name__ }}, + st.floats(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max(), allow_nan=False, allow_infinity=False).map({{ primitive.__name__ }}) +) +{%- endfor %} +{# Register strategies for integer types #} +{%- for primitive in integer_primitives %} +st.register_type_strategy( + {{ primitive.__name__ }}, + st.integers(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max()).map({{ primitive.__name__ }}) +) +{%- endfor %} From 8be53b587b1b0eb38891383e2a770902a4e89760 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 12:46:38 +0200 Subject: [PATCH 116/189] refactor: render primitive_strategies.jinja and import types from there in tests --- .../data/templates/protocols/hypothesis.jinja | 17 +---------------- .../protocols/primitive_strategies.jinja | 2 +- .../templates/protocols/test_dialogues.jinja | 2 +- auto_dev/protocols/protodantic.py | 12 +++++++++++- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index a460de12..cb637a1f 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -3,7 +3,7 @@ from hypothesis import strategies as st from {{ message_import_path }} import {{ messages_pb2 }} -from {{ primitives_import_path }} import ( +from {{ strategies_import_path }} import ( {%- for primitive in float_primitives %} {{ primitive.__name__ }}, {%- endfor %} @@ -20,21 +20,6 @@ from {{ models_import_path }} import ( {%- endfor %} ) -{# Register strategies for floating-point types #} -{%- for primitive in float_primitives %} -st.register_type_strategy( - {{ primitive.__name__ }}, - st.floats(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max(), allow_nan=False, allow_infinity=False).map({{ primitive.__name__ }}) -) -{%- endfor %} -{# Register strategies for integer types #} -{%- for primitive in integer_primitives %} -st.register_type_strategy( - {{ primitive.__name__ }}, - st.integers(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max()).map({{ primitive.__name__ }}) -) -{%- endfor %} - {# Define strategies for each message #} {%- for message in file.messages %} {{ message.name|lower }}_strategy = st.from_type({{ message.name }}) diff --git a/auto_dev/data/templates/protocols/primitive_strategies.jinja b/auto_dev/data/templates/protocols/primitive_strategies.jinja index b4efabc4..730a206d 100644 --- a/auto_dev/data/templates/protocols/primitive_strategies.jinja +++ b/auto_dev/data/templates/protocols/primitive_strategies.jinja @@ -23,4 +23,4 @@ st.register_type_strategy( {{ primitive.__name__ }}, st.integers(min_value={{ primitive.__name__ }}.min(), max_value={{ primitive.__name__ }}.max()).map({{ primitive.__name__ }}) ) -{%- endfor %} +{% endfor %} diff --git a/auto_dev/data/templates/protocols/test_dialogues.jinja b/auto_dev/data/templates/protocols/test_dialogues.jinja index 801de8bf..9a88c98a 100644 --- a/auto_dev/data/templates/protocols/test_dialogues.jinja +++ b/auto_dev/data/templates/protocols/test_dialogues.jinja @@ -13,7 +13,7 @@ from packages.{{ author }}.protocols.{{ snake_name }}.dialogues import ( {{ camel_name }}Dialogues, ) from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message -from packages.{{ author }}.protocols.{{ snake_name }}.primitives import ( +from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies import ( Int64, Double, ) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index a3c7b542..45788779 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -53,6 +53,7 @@ def create( content = proto_inpath.read_text() primitives_py = repo_root / "auto_dev" / "protocols" / "primitives.py" + strategies_template = env.get_template('protocols/primitive_strategies.jinja') protodantic_template = env.get_template('protocols/protodantic.jinja') hypothesis_template = env.get_template('protocols/hypothesis.jinja') @@ -97,11 +98,20 @@ def create( message_import_path = ".".join(models_import_path.split(".")[:-1]) or "." messages_pb2 = pb2_path.with_suffix("").name + generated_strategies = strategies_template.render( + float_primitives=float_primitives, + integer_primitives=integer_primitives, + primitives_import_path=primitives_import_path, + ) + strategies_outpath = test_outpath.parent / "primitive_strategies.py" + strategies_outpath.write_text(generated_strategies) + + strategies_import_path = _compute_import_path(strategies_outpath, repo_root) tests = generated_tests = hypothesis_template.render( file=file, float_primitives=float_primitives, integer_primitives=integer_primitives, - primitives_import_path=primitives_import_path, + strategies_import_path=strategies_import_path, models_import_path=models_import_path, message_import_path=message_import_path, messages_pb2=messages_pb2, From faddb751adc2e0ddff0d15f6015c5d87090120aa Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:19:20 +0200 Subject: [PATCH 117/189] refactor: cls.update_forward_refs() -> cls.model_rebuild() --- auto_dev/data/templates/protocols/protodantic.jinja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 0ce4dbe1..dbe393b2 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -18,4 +18,4 @@ MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {{ formatter.render(file) }} for cls in BaseModel.__subclasses__(): - cls.update_forward_refs() + cls.model_rebuild() From e6d8d871aa856f7f52f5d7c1ae12d5b56f5e8216 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:21:18 +0200 Subject: [PATCH 118/189] fix: test_dialogues.jinja mock skill_context and imports --- .../data/templates/protocols/test_dialogues.jinja | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/auto_dev/data/templates/protocols/test_dialogues.jinja b/auto_dev/data/templates/protocols/test_dialogues.jinja index 9a88c98a..7bd5dea2 100644 --- a/auto_dev/data/templates/protocols/test_dialogues.jinja +++ b/auto_dev/data/templates/protocols/test_dialogues.jinja @@ -4,9 +4,10 @@ from unittest.mock import MagicMock -from pydantic import BaseModel -from hypothesis import strategies as st +from pydantic import BaseModel, conint, confloat from hypothesis import given +from hypothesis import strategies as st +from aea.configurations.data_types import PublicId from packages.{{ author }}.protocols.{{ snake_name }}.dialogues import ( {{ camel_name }}Dialogue, @@ -33,9 +34,15 @@ def shallow_dump(model: BaseModel) -> dict: def validate_dialogue(performative, model): """Validate successful dialogue instantiation.""" + skill_context = MagicMock() + skill_context.skill_id = PublicId( + name="mock_name", + author="mock_author", + ) + dialogues = {{ camel_name }}Dialogues( name="test_{{ snake_name }}_dialogues", - skill_context=MagicMock(), + skill_context=skill_context, ) dialogue = dialogues.create( From 23a33aeb4f4d9afcb83ceb26d5b55c4f325c85f1 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:23:41 +0200 Subject: [PATCH 119/189] feat: test_message.jinja --- .../templates/protocols/test_messages.jinja | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 auto_dev/data/templates/protocols/test_messages.jinja diff --git a/auto_dev/data/templates/protocols/test_messages.jinja b/auto_dev/data/templates/protocols/test_messages.jinja new file mode 100644 index 00000000..ecb69b20 --- /dev/null +++ b/auto_dev/data/templates/protocols/test_messages.jinja @@ -0,0 +1,82 @@ +{{ header }} + +"""Test messages module for the {{ snake_name }} protocol.""" + +import pytest +from pydantic import BaseModel, conint, confloat +from hypothesis import strategies as st +from hypothesis import given + +from aea.common import Address +from aea.mail.base import Envelope +from aea.protocols.base import Message +from aea.protocols.dialogue.base import Dialogue, Dialogues + + +from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message +from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies import ( + Int64, + Double, +) +from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( + {%- for custom_type in custom_types %} + {{ custom_type }}, + {%- endfor %} +) + + +def shallow_dump(model: BaseModel) -> dict: + """Shallow dump pydantic model.""" + + return {name: getattr(model, name) for name in model.__fields__} + + +def perform_message_test(performative, model) -> None: + """Test message encode/decode.""" + + msg = {{ camel_name }}Message( + performative=performative, + **shallow_dump(model), + ) + + msg.to = "receiver" + assert msg._is_consistent() # pylint: disable=protected-access + envelope = Envelope(to=msg.to, sender="sender", message=msg) + envelope_bytes = envelope.encode() + + actual_envelope = Envelope.decode(envelope_bytes) + expected_envelope = envelope + + assert expected_envelope.to == actual_envelope.to + assert expected_envelope.sender == actual_envelope.sender + assert ( + expected_envelope.protocol_specification_id + == actual_envelope.protocol_specification_id + ) + assert expected_envelope.message != actual_envelope.message + + actual_msg = {{ camel_name }}Message.serializer.decode(actual_envelope.message_bytes) + actual_msg.to = actual_envelope.to + actual_msg.sender = actual_envelope.sender + expected_msg = msg + assert expected_msg == actual_msg + +{# Define models for the performatives #} +{%- for performative, fields in performative_types.items() %} +class {{ snake_to_camel(performative) }}(BaseModel): + """Model for the `{{ performative|upper }}` initial speech act performative.""" + {%- for field_name, field_type in fields.items() %} + {{ field_name }}: {{ field_type }} + {%- endfor %} + +{% endfor %} + + +{%- for performative in performative_types %} + +@given(st.from_type({{ snake_to_camel(performative) }})) +def test_{{ performative }}_messages(model): + """Test for the '{{ performative|upper }}' protocol message encode and decode.""" + + perform_message_test({{ camel_name }}Message.Performative.{{ performative|upper }}, model) +{% endfor %} From 358bb2ae13ae0da5f48e15838ac0e09843c00f88 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:25:12 +0200 Subject: [PATCH 120/189] fix: type casting of performatives annotation to python --- auto_dev/data/templates/protocols/test_dialogues.jinja | 2 +- auto_dev/data/templates/protocols/test_messages.jinja | 2 +- auto_dev/protocols/performatives.py | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/auto_dev/data/templates/protocols/test_dialogues.jinja b/auto_dev/data/templates/protocols/test_dialogues.jinja index 7bd5dea2..dba7fe1a 100644 --- a/auto_dev/data/templates/protocols/test_dialogues.jinja +++ b/auto_dev/data/templates/protocols/test_dialogues.jinja @@ -15,7 +15,7 @@ from packages.{{ author }}.protocols.{{ snake_name }}.dialogues import ( ) from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies import ( - Int64, + Int32, Double, ) from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( diff --git a/auto_dev/data/templates/protocols/test_messages.jinja b/auto_dev/data/templates/protocols/test_messages.jinja index ecb69b20..212c9d5d 100644 --- a/auto_dev/data/templates/protocols/test_messages.jinja +++ b/auto_dev/data/templates/protocols/test_messages.jinja @@ -15,7 +15,7 @@ from aea.protocols.dialogue.base import Dialogue, Dialogues from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies import ( - Int64, + Int32, Double, ) from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( diff --git a/auto_dev/protocols/performatives.py b/auto_dev/protocols/performatives.py index 003372d4..0bcd79ad 100644 --- a/auto_dev/protocols/performatives.py +++ b/auto_dev/protocols/performatives.py @@ -1,8 +1,6 @@ - - SCALAR_MAP = { - "int": "Int64", - "float": "Double", + "int": "conint(ge=Int32.min(), le=Int32.max())", + "float": "confloat(ge=Double.min(), le=Double.max())", "bool": "bool", "str": "str", "bytes": "bytes", @@ -43,7 +41,7 @@ def parse_annotation(annotation: str) -> str: return f"{parse_annotation(inner)} | None" elif core.startswith("list[") and core.endswith("]"): inner = core[len("list["):-1] - return f"list[{parse_annotation(inner)}]" + return f"tuple[{parse_annotation(inner)}]" # quirk of the framework! elif core.startswith("dict[") and core.endswith("]"): inner = core[len("dict["):-1] key_str, value_str = _split_top_level(inner) From 9622486b5f15beee9be8cac248284f85d9da09aa Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:37:57 +0200 Subject: [PATCH 121/189] test: updated expected result in test_parse_performative_annotation --- tests/test_protocol.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 3a186f61..bd86755b 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -6,7 +6,7 @@ from jinja2 import Template, Environment, FileSystemLoader from auto_dev.protocols import protodantic -from auto_dev.protocols import performatives +from auto_dev.protocols import performatives @functools.lru_cache() @@ -57,13 +57,13 @@ def test_protodantic(proto_path: Path): @pytest.mark.parametrize("annotation, expected", [ - ("pt:int", "Int64"), - ("pt:float", "Double"), - ("pt:list[pt:int]", "list[Int64]"), - ("pt:optional[pt:int]", "Int64 | None"), - ("pt:dict[pt:str, pt:int]", "dict[str, Int64]"), - ("pt:list[pt:union[pt:dict[pt:str, pt:int], pt:list[pt:bytes]]]", "list[dict[str, Int64] | list[bytes]]"), - ("pt:optional[pt:dict[pt:union[pt:str, pt:int], pt:list[pt:union[pt:float, pt:bool]]]]", "dict[str | Int64, list[Double | bool]] | None") + ("pt:int", "conint(ge=Int32.min(), le=Int32.max())"), + ("pt:float", "confloat(ge=Double.min(), le=Double.max())"), + ("pt:list[pt:int]", "tuple[conint(ge=Int32.min(), le=Int32.max())]"), + ("pt:optional[pt:int]", "conint(ge=Int32.min(), le=Int32.max()) | None"), + ("pt:dict[pt:str, pt:int]", "dict[str, conint(ge=Int32.min(), le=Int32.max())]"), + ("pt:list[pt:union[pt:dict[pt:str, pt:int], pt:list[pt:bytes]]]", "tuple[dict[str, conint(ge=Int32.min(), le=Int32.max())] | tuple[bytes]]"), + ("pt:optional[pt:dict[pt:union[pt:str, pt:int], pt:list[pt:union[pt:float, pt:bool]]]]", "dict[str | conint(ge=Int32.min(), le=Int32.max()), tuple[confloat(ge=Double.min(), le=Double.max()) | bool]] | None"), ] ) def test_parse_performative_annotation(annotation: str, expected: str): From 617e747a4a34d5e7a7bb4825257f8cec1c838395 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:42:10 +0200 Subject: [PATCH 122/189] refactor: move protocol/scaffold.py -> behaviours/protocol_scaffolder.py --- .../scaffolder.py => behaviours/protocol_scaffolder.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename auto_dev/{protocols/scaffolder.py => behaviours/protocol_scaffolder.py} (100%) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/behaviours/protocol_scaffolder.py similarity index 100% rename from auto_dev/protocols/scaffolder.py rename to auto_dev/behaviours/protocol_scaffolder.py From ef764bd11e20f7ef21acb093d5038f5ef6d52d3b Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:43:01 +0200 Subject: [PATCH 123/189] fix: import path ProtocolScaffolder in behaviour/scaffold.py --- auto_dev/behaviours/scaffolder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_dev/behaviours/scaffolder.py b/auto_dev/behaviours/scaffolder.py index 4ba6b8a9..3e2f8c6c 100644 --- a/auto_dev/behaviours/scaffolder.py +++ b/auto_dev/behaviours/scaffolder.py @@ -13,7 +13,7 @@ from auto_dev.fsm.fsm import FsmSpec from auto_dev.constants import JINJA_TEMPLATE_FOLDER from auto_dev.exceptions import UserInputError -from auto_dev.protocols.scaffolder import ProtocolScaffolder +from auto_dev.behaviours.protocol_scaffolder import ProtocolScaffolder ProtocolSpecification = namedtuple("ProtocolSpecification", ["metadata", "custom_types", "speech_acts"]) From 146f8584140fa6b9206cdf18cc8cb7618f7bf90f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 16:51:18 +0200 Subject: [PATCH 124/189] feat: protocols/README.jinja --- auto_dev/data/templates/protocols/README.jinja | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 auto_dev/data/templates/protocols/README.jinja diff --git a/auto_dev/data/templates/protocols/README.jinja b/auto_dev/data/templates/protocols/README.jinja new file mode 100644 index 00000000..c138edfb --- /dev/null +++ b/auto_dev/data/templates/protocols/README.jinja @@ -0,0 +1,10 @@ +# {{ name }} Protocol + +## Description +{{ description }} + +## Specification + +```yaml +{{ protocol_definition}} +``` From 1218cc7ea9b768a32b9108423476bcb2d9bff692 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 6 Apr 2025 19:12:25 +0200 Subject: [PATCH 125/189] fix: update templates to pass adev lint --- auto_dev/data/templates/protocols/dialogues.jinja | 2 +- auto_dev/data/templates/protocols/hypothesis.jinja | 3 +++ .../templates/protocols/primitive_strategies.jinja | 2 ++ auto_dev/data/templates/protocols/protodantic.jinja | 10 ++++++++++ auto_dev/data/templates/protocols/test_messages.jinja | 2 +- auto_dev/protocols/primitives.py | 4 ++++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/auto_dev/data/templates/protocols/dialogues.jinja b/auto_dev/data/templates/protocols/dialogues.jinja index 76027df3..b402fc7d 100644 --- a/auto_dev/data/templates/protocols/dialogues.jinja +++ b/auto_dev/data/templates/protocols/dialogues.jinja @@ -17,7 +17,7 @@ from aea.protocols.dialogue.base import Dialogue, Dialogues, DialogueLabel from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message -def _role_from_first_message(message: Message, sender: Address) -> Dialogue.Role: +def _role_from_first_message(message: Message, sender: Address) -> Dialogue.Role: # noqa: ARG001 """Infer the role of the agent from an incoming/outgoing first message""" return {{ camel_name }}Dialogue.Role.{{ role }} diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index cb637a1f..112a8ac2 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -1,3 +1,5 @@ +"""Module containing tests for the pydantic models generated from the .proto file.""" + from hypothesis import given from hypothesis import strategies as st @@ -29,6 +31,7 @@ from {{ models_import_path }} import ( {%- for message in file.messages %} @given({{ message.name|lower }}_strategy) def test_{{ message.name|lower }}({{ message.name|lower }}: {{ message.name }}): + """Test {{ message.name }}""" assert isinstance({{ message.name|lower }}, {{ message.name }}) proto_obj = {{ messages_pb2 }}.{{ message.name }}() {{ message.name|lower }}.encode(proto_obj, {{ message.name|lower }}) diff --git a/auto_dev/data/templates/protocols/primitive_strategies.jinja b/auto_dev/data/templates/protocols/primitive_strategies.jinja index 730a206d..f5e5bcf0 100644 --- a/auto_dev/data/templates/protocols/primitive_strategies.jinja +++ b/auto_dev/data/templates/protocols/primitive_strategies.jinja @@ -1,3 +1,5 @@ +"""Module containing hypothesis strategies for the custom primitives.""" + from hypothesis import given from hypothesis import strategies as st diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index dbe393b2..3551fe44 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -1,3 +1,5 @@ +"""Module containing the pydantic models generated from the .proto file.""" + from __future__ import annotations from enum import IntEnum @@ -13,6 +15,14 @@ from {{ primitives_import_path }} import ( {%- endfor %} ) +# ruff: noqa: N806, C901, PLR0912, PLR0914, PLR0915, A001 +# N806 - variable should be lowercase +# C901 - function is too complex +# PLR0912 - too many branches +# PLR0914 - too many local variables +# PLR0915 - too many statements +# A001 - shadowing builtin names like `id` and `type` + MAX_PROTO_SIZE = 2 * 1024 * 1024 * 1024 # 2 GiB in bytes {{ formatter.render(file) }} diff --git a/auto_dev/data/templates/protocols/test_messages.jinja b/auto_dev/data/templates/protocols/test_messages.jinja index 212c9d5d..9c06b006 100644 --- a/auto_dev/data/templates/protocols/test_messages.jinja +++ b/auto_dev/data/templates/protocols/test_messages.jinja @@ -40,7 +40,7 @@ def perform_message_test(performative, model) -> None: ) msg.to = "receiver" - assert msg._is_consistent() # pylint: disable=protected-access + assert msg._is_consistent() # noqa: SLF001 envelope = Envelope(to=msg.to, sender="sender", message=msg) envelope_bytes = envelope.encode() diff --git a/auto_dev/protocols/primitives.py b/auto_dev/protocols/primitives.py index 841f0779..3abd20d7 100644 --- a/auto_dev/protocols/primitives.py +++ b/auto_dev/protocols/primitives.py @@ -1,3 +1,7 @@ +"""Module containing custom primitives.""" + +# ruff: noqa: D101, D102, D105, ARG003, PLW3201 + import struct from abc import ABC, abstractmethod from pydantic_core import SchemaValidator, core_schema From c02f2de4d653efdaea63f7fbf6b5e984168e006b Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:14:27 +0200 Subject: [PATCH 126/189] test: adev scaffold protocol --- tests/test_protocol.py | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index bd86755b..ab4a240f 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1,11 +1,15 @@ +import os +import shutil import tempfile import functools +import subprocess from pathlib import Path import pytest from jinja2 import Template, Environment, FileSystemLoader from auto_dev.protocols import protodantic +from auto_dev.protocols.scaffolder import read_protocol from auto_dev.protocols import performatives @@ -18,7 +22,17 @@ def _get_proto_files() -> dict[str, Path]: return proto_files +@functools.lru_cache() +def _get_capitalization_station_protocols() -> dict[str, Path]: + repo_root = protodantic.get_repo_root() + path = repo_root / "tests" / "data" / "protocols" / ".capitalisation_station" + assert path.exists() + yaml_files = {file.name: file for file in path.glob("*.yaml")} + return yaml_files + + PROTO_FILES = _get_proto_files() +PROTOCOL_FILES = _get_capitalization_station_protocols() @pytest.mark.parametrize("proto_path", [ @@ -69,3 +83,47 @@ def test_protodantic(proto_path: Path): def test_parse_performative_annotation(annotation: str, expected: str): """Test parse_performative_annotation""" assert performatives.parse_annotation(annotation) == expected + + +@pytest.mark.parametrize("protocol_spec", [ + PROTOCOL_FILES["balances.yaml"], + PROTOCOL_FILES["bridge.yaml"], + PROTOCOL_FILES["cross_chain_arbtrage.yaml"], + PROTOCOL_FILES["default.yaml"], + PROTOCOL_FILES["liquidity_provision.yaml"], + PROTOCOL_FILES["markets.yaml"], + PROTOCOL_FILES["ohlcv.yaml"], + PROTOCOL_FILES["order_book.yaml"], + PROTOCOL_FILES["orders.yaml"], + PROTOCOL_FILES["positions.yaml"], + PROTOCOL_FILES["spot_asset.yaml"], + PROTOCOL_FILES["tickers.yaml"], +]) +def test_scaffold_protocol(protocol_spec: Path): + """Test `adev scaffold protocol` command""" + + protocol = read_protocol(protocol_spec) + + repo_root = protodantic.get_repo_root() + packages_dir = repo_root / "packages" + if packages_dir.exists(): + raise Exception("Test assumes no packages directory exists in this repo") + + packages_dir.mkdir(exist_ok=False) + tmp_test_agent = repo_root / "tmp_test_agent" + original_cwd = os.getcwd() + try: + subprocess.run(["aea", "create", tmp_test_agent.name], check=True, cwd=repo_root) + os.chdir(tmp_test_agent) + + result = subprocess.run(["adev", "-v", "scaffold", "protocol", str(protocol_spec)], check=False, text=True, capture_output=True) + if result.returncode != 0: + raise ValueError(f"Protocol scaffolding failed: {result.stderr}") + + test_dir = packages_dir / protocol.metadata.author / "protocols" / protocol.metadata.name / "tests" + exit_code = pytest.main([test_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) + assert exit_code == 0 + finally: + shutil.rmtree(tmp_test_agent) + shutil.rmtree(packages_dir) + os.chdir(original_cwd) From 8ea9ba27b69c7c80a1e1f9bf8b688a2c858919af Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:23:46 +0200 Subject: [PATCH 127/189] feat: protocol scaffolder read_protocol_spec --- auto_dev/protocols/scaffolder.py | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 auto_dev/protocols/scaffolder.py diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py new file mode 100644 index 00000000..b399dee0 --- /dev/null +++ b/auto_dev/protocols/scaffolder.py @@ -0,0 +1,69 @@ +import tempfile +from pathlib import Path +from collections import namedtuple + +import yaml +from jinja2 import Environment, FileSystemLoader +from aea.protocols.generator.base import ProtocolGenerator + +from auto_dev.utils import remove_prefix +from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER +from auto_dev.protocols import protodantic + + +ProtocolSpecification = namedtuple("ProtocolSpecification", ["metadata", "custom_types", "speech_acts"]) + + +def read_protocol_spec(filepath: str) -> ProtocolSpecification: + """Read protocol specification.""" + + content = Path(filepath).read_text(encoding=DEFAULT_ENCODING) + + # parse from README.md, otherwise we assume protocol.yaml + if "```" in content: + if content.count("```") != 2: + msg = "Expecting a single code block" + raise ValueError(msg) + content = remove_prefix(content.split("```")[1], "yaml") + + # use ProtocolGenerator to validate the specification + with tempfile.NamedTemporaryFile(mode="w", encoding=DEFAULT_ENCODING) as temp_file: + Path(temp_file.name).write_text(content, encoding=DEFAULT_ENCODING) + ProtocolGenerator(temp_file.name) + + content = list(yaml.safe_load_all(content)) + if len(content) == 3: + metadata, custom_definitions, interaction_model = content + elif len(content) == 2: + metadata, interaction_model = content + custom_definitions = None + else: + msg = f"Expected 2 or 3 YAML documents in {filepath}." + raise ValueError(msg) + + return ProtocolSpecification( + path=filepath, + metadata=metadata, + custom_definitions=custom_definitions, + interaction_model=interaction_model, + ) + + +def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): + """Scaffolding protocol components. + + Args: + ---- + protocol_specification_path: Path to the protocol specification file. + language: Target language for the protocol. + logger: Logger instance for output and debugging. + verbose: Whether to enable verbose logging. + + """ + + Path.cwd() + protodantic.get_repo_root() + env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa + + # 0. Read spec data + read_protocol_spec(protocol_specification_path) From c6f581d0e0ca3b2e2729d4fb085e16a4b6ac2955 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:48:49 +0200 Subject: [PATCH 128/189] feat: ProtocolSpecification model --- auto_dev/protocols/performatives.py | 3 +++ auto_dev/protocols/scaffolder.py | 34 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/auto_dev/protocols/performatives.py b/auto_dev/protocols/performatives.py index 0bcd79ad..6d02766c 100644 --- a/auto_dev/protocols/performatives.py +++ b/auto_dev/protocols/performatives.py @@ -1,3 +1,6 @@ +"""Module for parsing protocol performatives.""" + + SCALAR_MAP = { "int": "conint(ge=Int32.min(), le=Int32.max())", "float": "confloat(ge=Double.min(), le=Double.max())", diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index b399dee0..56d5788b 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -1,9 +1,9 @@ import tempfile from pathlib import Path -from collections import namedtuple import yaml from jinja2 import Environment, FileSystemLoader +from pydantic import BaseModel from aea.protocols.generator.base import ProtocolGenerator from auto_dev.utils import remove_prefix @@ -11,7 +11,37 @@ from auto_dev.protocols import protodantic -ProtocolSpecification = namedtuple("ProtocolSpecification", ["metadata", "custom_types", "speech_acts"]) +class Metadata(BaseModel): + """Metadata.""" + + name: str + author: str + version: str + description: str + license: str + aea_version: str + protocol_specification_id: str + speech_acts: dict[str, dict[str, str]] | None = None + + +class InteractionModel(BaseModel): + """InteractionModel.""" + + initiation: list[str] + reply: dict[str, list[str]] + termination: list[str] + roles: dict[str, None] + end_states: list[str] + keep_terminal_state_dialogues: bool + + +class ProtocolSpecification(BaseModel): + """ProtocolSpecification.""" + + path: Path + metadata: Metadata + custom_definitions: dict[str, str] | None = None + interaction_model: InteractionModel def read_protocol_spec(filepath: str) -> ProtocolSpecification: From 40419df88162e70bcc655ad6f81be822aba9933a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:51:13 +0200 Subject: [PATCH 129/189] feat add computed properties to ProtocolSpecification --- auto_dev/protocols/scaffolder.py | 46 ++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 56d5788b..35acd1bb 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -6,9 +6,9 @@ from pydantic import BaseModel from aea.protocols.generator.base import ProtocolGenerator -from auto_dev.utils import remove_prefix +from auto_dev.utils import remove_prefix, snake_to_camel from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER -from auto_dev.protocols import protodantic +from auto_dev.protocols import protodantic, performatives class Metadata(BaseModel): @@ -43,6 +43,48 @@ class ProtocolSpecification(BaseModel): custom_definitions: dict[str, str] | None = None interaction_model: InteractionModel + @property + def name(self) -> str: + return self.metadata.name + + @property + def author(self) -> str: + return self.metadata.author + + @property + def camel_name(self) -> str: + return snake_to_camel(self.metadata.name) + + @property + def custom_types(self) -> list[str]: + return [custom_type.removeprefix("ct:") for custom_type in self.custom_definitions] + + @property + def performative_types(self) -> dict[str, dict[str, str]]: + performative_types = {} + for performative, message_fields in self.metadata.speech_acts.items(): + field_types = {} + for field_name, value_type in message_fields.items(): + field_types[field_name] = performatives.parse_annotation(value_type) + performative_types[performative] = field_types + return performative_types + + @property + def initial_performative_types(self) -> dict[str, dict[str, str]]: + return {k: v for k, v in self.performative_types.items() if k in self.interaction_model.initiation} + + @property + def outpath(self) -> Path: + return protodantic.get_repo_root() / "packages" / self.author / "protocols" / self.name + + @property + def code_outpath(self) -> Path: + return self.outpath / "custom_types.py" + + @property + def test_outpath(self) -> Path: + return self.outpath / "tests" / "test_custom_types.py" + def read_protocol_spec(filepath: str) -> ProtocolSpecification: """Read protocol specification.""" From d4c253ff7c1d3980ceece0156a6c603363169faf Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:54:43 +0200 Subject: [PATCH 130/189] feat initialize packages, aea generated protocol & aea publish --- auto_dev/protocols/scaffolder.py | 47 ++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 35acd1bb..ebaf99ca 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -1,4 +1,5 @@ import tempfile +import subprocess from pathlib import Path import yaml @@ -121,6 +122,36 @@ def read_protocol_spec(filepath: str) -> ProtocolSpecification: ) +def run_cli_cmd(command: list[str], cwd: Path | None = None): + result = subprocess.run( + command, + shell=False, + capture_output=True, + text=True, + check=False, + cwd=cwd or Path.cwd(), + ) + if result.returncode != 0: + msg = f"Failed: {command}:\n{result.stderr}" + raise ValueError(msg) + + +def initialize_packages(repo_root: Path) -> None: + packages_dir = repo_root / "packages" + if not packages_dir.exists(): + run_cli_cmd(["aea", "packages", "init"], cwd=repo_root) + + +def run_aea_generate_protocol(protocol_path: Path, language: str, agent_dir: Path) -> None: + command = ["aea", "-s", "generate", "protocol", str(protocol_path), "--l", language] + run_cli_cmd(command, cwd=agent_dir) + + +def run_aea_publish(agent_dir: Path) -> None: + command = ["aea", "publish", "--local", "--push-missing"] + run_cli_cmd(command, cwd=agent_dir) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -133,9 +164,19 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb """ - Path.cwd() - protodantic.get_repo_root() + agent_dir = Path.cwd() + repo_root = protodantic.get_repo_root() env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa # 0. Read spec data - read_protocol_spec(protocol_specification_path) + protocol = read_protocol_spec(protocol_specification_path) + + # 1. initialize packages folder if non-existent + initialize_packages(repo_root) + + # 2. AEA generate protocol + run_aea_generate_protocol(protocol.path, language=language, agent_dir=agent_dir) + + # Ensures `protocol.outpath` exists, required for correct import path generation + # TODO: on error during any part of this process, clean up (remove) `protocol.outpath` + run_aea_publish(agent_dir) From 19dba5cfb09357e83ee8c01a38affb4278116c9c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:56:14 +0200 Subject: [PATCH 131/189] feat: generate_readme() using Jinja template --- auto_dev/protocols/scaffolder.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index ebaf99ca..00b8a73f 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -152,6 +152,17 @@ def run_aea_publish(agent_dir: Path) -> None: run_cli_cmd(command, cwd=agent_dir) +def generate_readme(protocol, template): + readme = protocol.outpath / "README.md" + protocol_definition = Path(protocol.path).read_text(encoding="utf-8") + content = template.render( + name=" ".join(map(str.capitalize, protocol.name.split("_"))), + description=protocol.metadata.description, + protocol_definition=protocol_definition, + ) + readme.write_text(content.strip()) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -180,3 +191,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # Ensures `protocol.outpath` exists, required for correct import path generation # TODO: on error during any part of this process, clean up (remove) `protocol.outpath` run_aea_publish(agent_dir) + + # 3. create README.md + template = env.get_template("protocols/README.jinja") + generate_readme(protocol, template) From b7b8c7977ab1fb495e4b064058dd7d00e88537d8 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:57:49 +0200 Subject: [PATCH 132/189] feat: generate_custom_types() using protodantic --- auto_dev/protocols/scaffolder.py | 42 +++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 00b8a73f..155ec012 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -1,3 +1,4 @@ +import shutil import tempfile import subprocess from pathlib import Path @@ -5,9 +6,12 @@ import yaml from jinja2 import Environment, FileSystemLoader from pydantic import BaseModel +from proto_schema_parser import ast +from proto_schema_parser.parser import Parser from aea.protocols.generator.base import ProtocolGenerator +from proto_schema_parser.generator import Generator -from auto_dev.utils import remove_prefix, snake_to_camel +from auto_dev.utils import file_swapper, remove_prefix, snake_to_camel from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER from auto_dev.protocols import protodantic, performatives @@ -163,6 +167,39 @@ def generate_readme(protocol, template): readme.write_text(content.strip()) +def generate_custom_types(protocol: ProtocolSpecification): + """Generate custom_types.py and tests/test_custom_types.py.""" + + proto_inpath = protocol.outpath / f"{protocol.name}.proto" + file = Parser().parse(proto_inpath.read_text()) + + # extract custom type messages from AEA framework "wrapper" message + main_message = file.file_elements.pop(1) + custom_type_names = {name.removeprefix("ct:") for name in protocol.custom_definitions} + for element in main_message.elements: + if isinstance(element, ast.Message) and element.name in custom_type_names: + file.file_elements.append(element) + + proto = Generator().generate(file) + tmp_proto_path = protocol.outpath / f"tmp_{proto_inpath.name}" + tmp_proto_path.write_text(proto) + + proto_pb2 = protocol.outpath / f"{protocol.name}_pb2.py" + backup_pb2 = proto_pb2.with_suffix(".bak") + shutil.move(str(proto_pb2), str(backup_pb2)) + with file_swapper(proto_inpath, tmp_proto_path): + protodantic.create( + proto_inpath=proto_inpath, + code_outpath=protocol.code_outpath, + test_outpath=protocol.test_outpath, + ) + shutil.move(str(backup_pb2), str(proto_pb2)) + pb2_content = proto_pb2.read_text() + pb2_content = protodantic._remove_runtime_version_code(pb2_content) + proto_pb2.write_text(pb2_content) + tmp_proto_path.unlink() + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -195,3 +232,6 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 3. create README.md template = env.get_template("protocols/README.jinja") generate_readme(protocol, template) + + # 4. Generate custom_types.py and test_custom_types.py + generate_custom_types(protocol) From 04e58c78cd59a1bf9ae0234621f5e759697ef3c6 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 02:59:49 +0200 Subject: [PATCH 133/189] fix: test_custom_types import patching --- auto_dev/protocols/scaffolder.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 155ec012..ba8162a2 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -200,6 +200,13 @@ def generate_custom_types(protocol: ProtocolSpecification): tmp_proto_path.unlink() +def rewrite_test_custom_types(protocol: ProtocolSpecification) -> None: + content = protocol.test_outpath.read_text() + a = f"packages.{protocol.author}.protocols.{protocol.name} import {protocol.name}_pb2" + b = f"packages.{protocol.author}.protocols.{protocol.name}.{protocol.name}_pb2 import {protocol.camel_name}Message as {protocol.name}_pb2 # noqa: N813" + protocol.test_outpath.write_text(content.replace(a, b)) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -235,3 +242,6 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 4. Generate custom_types.py and test_custom_types.py generate_custom_types(protocol) + + # 5. rewrite test_custom_types to patch the import + rewrite_test_custom_types(protocol) From a73d7a07bbe498e9108fdcac82f3288c59876f90 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:01:06 +0200 Subject: [PATCH 134/189] feat: generate_dialogues() using ProtocolSpecification --- auto_dev/protocols/scaffolder.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index ba8162a2..0989fb03 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -207,6 +207,31 @@ def rewrite_test_custom_types(protocol: ProtocolSpecification) -> None: protocol.test_outpath.write_text(content.replace(a, b)) +def generate_dialogues(protocol: ProtocolSpecification, template): + """Generate dialogues.py.""" + + valid_replies = protocol.interaction_model.reply + roles = [{"name": r.upper(), "value": r} for r in protocol.interaction_model.roles] + end_states = [{"name": s.upper(), "value": idx} for idx, s in enumerate(protocol.interaction_model.end_states)] + keep_terminal = protocol.interaction_model.keep_terminal_state_dialogues + + output = template.render( + header="# Auto-generated by tool", + author=protocol.author, + snake_name=protocol.name, + camel_name=protocol.camel_name, + initial_performatives=protocol.interaction_model.initiation, + terminal_performatives=protocol.interaction_model.termination, + valid_replies=valid_replies, + roles=roles, + role=roles[0]["name"], + end_states=end_states, + keep_terminal_state_dialogues=keep_terminal, + ) + dialogues = protocol.outpath / "dialogues.py" + dialogues.write_text(output) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -245,3 +270,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 5. rewrite test_custom_types to patch the import rewrite_test_custom_types(protocol) + + # 6. Dialogues + template = env.get_template("protocols/dialogues.jinja") + generate_dialogues(protocol, template) From d3510a1c8d954ab7b807d01bcfdf6f5b825f91fe Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:02:10 +0200 Subject: [PATCH 135/189] feat: generate_test_dialogues() using ProtocolSpecification --- auto_dev/protocols/scaffolder.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 0989fb03..d94a66a7 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -232,6 +232,25 @@ def generate_dialogues(protocol: ProtocolSpecification, template): dialogues.write_text(output) +def generate_tests_init(protocol: ProtocolSpecification) -> None: + test_init_file = protocol.outpath / "tests" / "__init__.py" + test_init_file.write_text(f'"""Test module for the {protocol.name}"""') + + +def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: + output = template.render( + header="# Auto-generated by tool", + author=protocol.author, + snake_name=protocol.name, + camel_name=protocol.camel_name, + initial_performative_types=protocol.initial_performative_types, + custom_types=protocol.custom_types, + snake_to_camel=snake_to_camel, + ) + test_dialogues = protocol.outpath / "tests" / f"test_{protocol.name}_dialogues.py" + test_dialogues.write_text(output) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -274,3 +293,10 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 6. Dialogues template = env.get_template("protocols/dialogues.jinja") generate_dialogues(protocol, template) + + # 7. generate __init__.py in tests folder + generate_tests_init(protocol) + + # 8. Test dialogues + template = env.get_template("protocols/test_dialogues.jinja") + generate_test_dialogues(protocol, template) From f67e74927338e5b73565e896726cd4617c70e85a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:05:07 +0200 Subject: [PATCH 136/189] feat: generate_test_messages() using ProtocolSpecification --- auto_dev/protocols/scaffolder.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index d94a66a7..de37955d 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -251,6 +251,20 @@ def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: test_dialogues.write_text(output) +def generate_test_messages(protocol: ProtocolSpecification, template) -> None: + output = template.render( + header="# Auto-generated by tool", + author=protocol.author, + snake_name=protocol.name, + camel_name=protocol.camel_name, + performative_types=protocol.performative_types, + custom_types=protocol.custom_types, + snake_to_camel=snake_to_camel, + ) + test_messages = protocol.outpath / "tests" / f"test_{protocol.name}_messages.py" + test_messages.write_text(output) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -300,3 +314,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 8. Test dialogues template = env.get_template("protocols/test_dialogues.jinja") generate_test_dialogues(protocol, template) + + # 9. Test messages + template = env.get_template("protocols/test_messages.jinja") + generate_test_messages(protocol, template) From 26ca126eea3d1bd14615ebbbf4a86b524fff48f5 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:14:04 +0200 Subject: [PATCH 137/189] feat: update protocol.yaml with pydantic and hypothesis dependencies --- auto_dev/protocols/scaffolder.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index de37955d..4c91765c 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -265,6 +265,15 @@ def generate_test_messages(protocol: ProtocolSpecification, template) -> None: test_messages.write_text(output) +def update_yaml(protocol, dependencies: dict[str, dict[str, str]]) -> None: + protocol_yaml = protocol.outpath / "protocol.yaml" + content = yaml.safe_load(protocol_yaml.read_text()) + for package_name, package_info in dependencies.items(): + content["dependencies"][package_name] = package_info + content["dependencies"][package_name] = package_info + protocol_yaml.write_text(yaml.dump(content, sort_keys=False)) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -318,3 +327,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 9. Test messages template = env.get_template("protocols/test_messages.jinja") generate_test_messages(protocol, template) + + # 10. Update YAML + dependencies = {"pydantic": {}, "hypothesis": {}} + update_yaml(protocol, dependencies) From 4c79bb84a4c16fc7a10e6ab51c5ac1d22394c975 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:15:44 +0200 Subject: [PATCH 138/189] feat: adev fmt & lint, aea fingerprint on newly generated protocol code --- auto_dev/protocols/scaffolder.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 4c91765c..e4202e68 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -274,6 +274,21 @@ def update_yaml(protocol, dependencies: dict[str, dict[str, str]]) -> None: protocol_yaml.write_text(yaml.dump(content, sort_keys=False)) +def run_adev_fmt(protocol) -> None: + command = ["adev", "-v", "fmt", "-p", str(protocol.outpath)] + run_cli_cmd(command) + + +def run_adev_lint(protocol) -> None: + command = ["adev", "-v", "lint", "-p", str(protocol.outpath)] + run_cli_cmd(command) + + +def run_aea_fingerprint(protocol) -> None: + command = ["aea", "fingerprint", "protocol", protocol.metadata.protocol_specification_id] + run_cli_cmd(command) + + def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): """Scaffolding protocol components. @@ -331,3 +346,15 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 10. Update YAML dependencies = {"pydantic": {}, "hypothesis": {}} update_yaml(protocol, dependencies) + + # 11. fmt + run_adev_fmt(protocol) + + # 12. lint + run_adev_lint(protocol) + + # 13. Fingerprint + run_aea_fingerprint(protocol) + + # Hurray's are in order + logger.info(f"New protocol scaffolded at {protocol.outpath}") From af1f0a44c3b1896ec175974b58e0738ba115ab97 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:16:43 +0200 Subject: [PATCH 139/189] refactor: use new protocol_scaffolder in adev command --- auto_dev/commands/scaffold.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/auto_dev/commands/scaffold.py b/auto_dev/commands/scaffold.py index 48d64d0b..9702f331 100644 --- a/auto_dev/commands/scaffold.py +++ b/auto_dev/commands/scaffold.py @@ -29,7 +29,7 @@ from auto_dev.contracts.contract import DEFAULT_NULL_ADDRESS from auto_dev.handler.scaffolder import HandlerScaffoldBuilder from auto_dev.dialogues.scaffolder import DialogueTypes, DialogueScaffolder -from auto_dev.protocols.scaffolder import ProtocolScaffolder +from auto_dev.protocols.scaffolder import protocol_scaffolder from auto_dev.behaviours.scaffolder import BehaviourScaffolder from auto_dev.connections.scaffolder import ConnectionScaffolder from auto_dev.contracts.block_explorer import BlockExplorer @@ -329,8 +329,7 @@ def protocol(ctx, protocol_specification_path: str, language: str) -> None: """ logger = ctx.obj["LOGGER"] verbose = ctx.obj["VERBOSE"] - scaffolder = ProtocolScaffolder(protocol_specification_path, language, logger=logger, verbose=verbose) - scaffolder.generate() + protocol_scaffolder(protocol_specification_path, language, logger=logger, verbose=verbose) @scaffold.command() From acd6b336025eaef58516e792f37951e7da502ca1 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:18:29 +0200 Subject: [PATCH 140/189] test: fix import and remove flawed capitalisation station protocol specs from tests --- tests/test_protocol.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index ab4a240f..3f19199f 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -9,7 +9,7 @@ from jinja2 import Template, Environment, FileSystemLoader from auto_dev.protocols import protodantic -from auto_dev.protocols.scaffolder import read_protocol +from auto_dev.protocols.scaffolder import read_protocol_spec from auto_dev.protocols import performatives @@ -87,13 +87,13 @@ def test_parse_performative_annotation(annotation: str, expected: str): @pytest.mark.parametrize("protocol_spec", [ PROTOCOL_FILES["balances.yaml"], - PROTOCOL_FILES["bridge.yaml"], - PROTOCOL_FILES["cross_chain_arbtrage.yaml"], + # PROTOCOL_FILES["bridge.yaml"], + # PROTOCOL_FILES["cross_chain_arbtrage.yaml"], PROTOCOL_FILES["default.yaml"], PROTOCOL_FILES["liquidity_provision.yaml"], PROTOCOL_FILES["markets.yaml"], PROTOCOL_FILES["ohlcv.yaml"], - PROTOCOL_FILES["order_book.yaml"], + # PROTOCOL_FILES["order_book.yaml"], PROTOCOL_FILES["orders.yaml"], PROTOCOL_FILES["positions.yaml"], PROTOCOL_FILES["spot_asset.yaml"], @@ -102,7 +102,7 @@ def test_parse_performative_annotation(annotation: str, expected: str): def test_scaffold_protocol(protocol_spec: Path): """Test `adev scaffold protocol` command""" - protocol = read_protocol(protocol_spec) + protocol = read_protocol_spec(protocol_spec) repo_root = protodantic.get_repo_root() packages_dir = repo_root / "packages" From 5527149eaa8d398a22515fc6bd8dd4e46216c871 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:29:40 +0200 Subject: [PATCH 141/189] fix: connection scaffolder to use ProtocolSpecification --- auto_dev/connections/scaffolder.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/auto_dev/connections/scaffolder.py b/auto_dev/connections/scaffolder.py index b0ea683e..e25e515c 100644 --- a/auto_dev/connections/scaffolder.py +++ b/auto_dev/connections/scaffolder.py @@ -16,7 +16,7 @@ from auto_dev.utils import get_logger, write_to_file, folder_swapper from auto_dev.constants import AEA_CONFIG, DEFAULT_ENCODING from auto_dev.cli_executor import CommandExecutor -from auto_dev.protocols.scaffolder import ProtocolSpecification, read_protocol +from auto_dev.protocols.scaffolder import ProtocolSpecification, read_protocol_spec from auto_dev.data.connections.template import HEADER, CONNECTION_TEMPLATE from auto_dev.data.connections.test_template import TEST_CONNECTION_TEMPLATE @@ -137,10 +137,10 @@ def __init__(self, name: str, logger, protocol): @property def kwargs(self) -> dict: """Template formatting kwargs.""" - protocol_name = self.protocol.metadata["name"] - protocol_author = self.protocol.metadata["author"] - speech_acts = list(self.protocol.metadata["speech_acts"]) - roles = list(self.protocol.speech_acts["roles"]) + protocol_name = self.protocol.metadata.name + protocol_author = self.protocol.metadata.author + speech_acts = list(self.protocol.metadata.speech_acts) + roles = list(self.protocol.interaction_model.roles) handlers = get_handlers(self.protocol) handler_mapping = get_handler_mapping(self.protocol) @@ -205,7 +205,7 @@ def __init__(self, ctx: click.Context, name: str, protocol_id: PublicId): self.logger = ctx.obj["LOGGER"] or get_logger() self.verbose = ctx.obj["VERBOSE"] self.protocol_id = protocol_id - self.protocol = read_protocol(protocol_specification_path) + self.protocol = read_protocol_spec(protocol_specification_path) self.logger.info(f"Read protocol specification: {protocol_specification_path}") self.public_id = PublicId.from_str(self.name) @@ -217,7 +217,7 @@ def update_config(self) -> None: connection_config = self.ctx.aea_ctx.connection_loader.load(infile) connection_config.protocols.add(self.protocol_id) connection_config.class_name = f"{to_camel(self.name)}Connection" - connection_config.description = self.protocol.metadata["description"].replace("protocol", "connection") + connection_config.description = self.protocol.metadata.description.replace("protocol", "connection") with open(connection_yaml, "w", encoding=DEFAULT_ENCODING) as outfile: # # pylint: disable=R1732 yaml_dump(connection_config.ordered_json, outfile) self.logger.info(f"Updated {connection_yaml}") From 21f6d529c96f0ef3008ef91e5f36350e4f4f8436 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 03:33:02 +0200 Subject: [PATCH 142/189] fix: test_scaffolder to use ProtocolSpecification --- tests/test_scaffold.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_scaffold.py b/tests/test_scaffold.py index 81372e1e..5c497ee2 100644 --- a/tests/test_scaffold.py +++ b/tests/test_scaffold.py @@ -16,7 +16,7 @@ from auto_dev.constants import DEFAULT_ENCODING from auto_dev.dao.scaffolder import DAOScaffolder from auto_dev.handler.scaffolder import HandlerScaffolder, HandlerScaffoldBuilder -from auto_dev.protocols.scaffolder import read_protocol +from auto_dev.protocols.scaffolder import read_protocol_spec from auto_dev.handler.openapi_models import ( Schema, OpenAPI, @@ -101,9 +101,9 @@ def test_scaffold_protocol(cli_runner, dummy_agent_tim): assert runner.return_code == 0, result.output assert "New protocol scaffolded" in runner.output - protocol = read_protocol(str(path)) + protocol = read_protocol_spec(str(path)) original_content = path.read_text(encoding=DEFAULT_ENCODING) - readme_path = dummy_agent_tim / "protocols" / protocol.metadata["name"] / "README.md" + readme_path = dummy_agent_tim / "protocols" / protocol.metadata.name / "README.md" assert original_content in readme_path.read_text(encoding=DEFAULT_ENCODING) From fd222fca4d2906984c95c19eefe1c5178c539cf2 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 13:10:15 +0200 Subject: [PATCH 143/189] chore: adev fmt lint --- auto_dev/protocols/adapters.py | 51 ++++++---- auto_dev/protocols/formatter.py | 153 ++++++++++++++-------------- auto_dev/protocols/performatives.py | 23 ++--- auto_dev/protocols/primitives.py | 107 +++++++++++++------ auto_dev/protocols/protodantic.py | 44 ++++---- auto_dev/protocols/scaffolder.py | 52 ++++++++-- tests/test_protocol.py | 124 ++++++++++++---------- tests/test_utils.py | 4 +- 8 files changed, 332 insertions(+), 226 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 650ff871..0255ae15 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -1,39 +1,40 @@ +"""Module containing adapter classes for proto_schema_parser.""" + from __future__ import annotations import re -from typing_extensions import TypeAliasType -from dataclasses import dataclass, field +from dataclasses import field, dataclass from proto_schema_parser.ast import ( - FileElement, + Enum, File, - Import, - Package, - Option, - Extension, - Service, - MessageElement, - Comment, Field, Group, OneOf, - ExtensionRange, - Reserved, + Import, + Option, + Comment, Message, - Enum, + Package, + Service, MapField, - MessageValue, - EnumElement, + Reserved, + Extension, + FileElement, + ExtensionRange, + MessageElement, ) def camel_to_snake(name: str) -> str: """Convert CamelCase to snake_case.""" - return re.sub(r'(? set[str]: + """Enum names referenced in this ast.Message.""" + return {m.name for m in self.enums} @property def message_names(self) -> set[str]: + """Message names referenced in this ast.Message.""" + return {m.name for m in self.messages} @classmethod @@ -92,12 +99,14 @@ def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: messages=grouped_elements["message"], enums=grouped_elements["enum"], extensions=grouped_elements["extension"], - map_fields=grouped_elements["map_field"] + map_fields=grouped_elements["map_field"], ) @dataclass class FileAdapter: + """FileAdapter for proto_schema_parser ast.File.""" + wrapped: File = field(repr=False) file_elements: list[FileElement | MessageAdapter] = field(repr=False) @@ -112,14 +121,20 @@ class FileAdapter: comments: list[Comment] = field(default_factory=list) def __getattr__(self, name: str): + """Access wrapped ast.File instance attributes.""" + return getattr(self.wrapped, name) @property def enum_names(self) -> set[str]: + """Top-level Enum names in ast.File.""" + return {m.name for m in self.enums} @property def message_names(self) -> set[str]: + """Top-level Message names in ast.File.""" + return {m.name for m in self.messages} @classmethod @@ -146,7 +161,7 @@ def from_file(cls, file: File) -> FileAdapter: enums=grouped_elements["enum"], extensions=grouped_elements["extension"], services=grouped_elements["service"], - comments=grouped_elements["comment"] + comments=grouped_elements["comment"], ) def set_parent(message: MessageAdapter, parent: FileAdapter | MessageAdapter): diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 359da5f5..c36dc351 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -1,26 +1,11 @@ +"""Module with formatter for rendering pydantic model code from proto_schema_parser ast.File.""" + import textwrap from proto_schema_parser import ast from proto_schema_parser.ast import ( - FileElement, - File, - Import, - Package, - Option, - Extension, - Service, - MessageElement, - Comment, Field, - Group, - OneOf, - ExtensionRange, - Reserved, - Message, - Enum, - MapField, - MessageValue, - EnumElement, + MessageElement, FieldCardinality, ) @@ -29,7 +14,11 @@ from auto_dev.protocols.primitives import PRIMITIVE_TYPE_MAP +# ruff: noqa: E501, PLR0911 + + def qualified_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> str: + """Fully qualified type for a type reference.""" def find_definition(scope): if scope is None or isinstance(scope, FileAdapter): @@ -43,6 +32,8 @@ def find_definition(scope): def render_field(field: Field, message: MessageAdapter) -> str: + """Render Field.""" + field_type = qualified_type(message, field.type) match field.cardinality: case FieldCardinality.REQUIRED | None: @@ -52,10 +43,13 @@ def render_field(field: Field, message: MessageAdapter) -> str: case FieldCardinality.REPEATED: return f"list[{field_type}]" case _: - raise TypeError(f"Unexpected cardinality: {field.cardinality}") + msg = f"Unexpected cardinality: {field.cardinality}" + raise TypeError(msg) def render_attribute(element: MessageElement | MessageAdapter, message: MessageAdapter) -> str: + """Render message elements.""" + match type(element): case ast.Comment: return f"# {element.text}" @@ -63,40 +57,36 @@ def render_attribute(element: MessageElement | MessageAdapter, message: MessageA return f"{element.name}: {render_field(element, message)}" case ast.OneOf: if not all(isinstance(e, Field) for e in element.elements): - raise NotImplementedError("Only implemented OneOf for Field") + msg = "Only implemented OneOf for Field" + raise NotImplementedError(msg) inner = " | ".join(render_field(e, message) for e in element.elements) return f"{element.name}: {inner}" case adapters.MessageAdapter: - elements = sorted(element.elements, key=lambda e: not isinstance(e, (MessageAdapter, ast.Enum))) + elements = sorted(element.elements, key=lambda e: not isinstance(e, MessageAdapter | ast.Enum)) body = inner = "\n".join(render_attribute(e, element) for e in elements) encoder = render_encoder(element) decoder = render_decoder(element) body = f"{inner}\n\n{encoder}\n\n{decoder}" indented_body = textwrap.indent(body, " ") - return ( - f"\nclass {element.name}(BaseModel):\n" - f" \"\"\"{element.name}\"\"\"\n\n" - f"{indented_body}\n" - ) + return f"\nclass {element.name}(BaseModel):\n" f' """{element.name}"""\n\n' f"{indented_body}\n" case ast.Enum: members = "\n".join(f"{val.name} = {val.number}" for val in element.elements) indented_members = textwrap.indent(members, " ") - return ( - f"class {element.name}(IntEnum):\n" - f" \"\"\"{element.name}\"\"\"\n\n" - f"{indented_members}\n" - ) + return f"class {element.name}(IntEnum):\n" f' """{element.name}"""\n\n' f"{indented_members}\n" case ast.MapField: key_type = PRIMITIVE_TYPE_MAP.get(element.key_type, element.key_type) value_type = qualified_type(message, element.value_type) return f"{element.name}: dict[{key_type}, {value_type}]" case ast.Group | ast.Option | ast.ExtensionRange | ast.Reserved | ast.Extension: - raise NotImplementedError(f"{element}") + msg = f"{element}" + raise NotImplementedError(msg) case _: - raise TypeError(f"Unexpected message type: {element}") + msg = f"Unexpected message type: {element}" + raise TypeError(msg) def render(file: FileAdapter): + """Main function to render a .proto file.""" enums = "\n".join(render_attribute(e, file) for e in file.enums) messages = "\n".join(render_attribute(e, file) for e in file.messages) @@ -105,29 +95,27 @@ def render(file: FileAdapter): def encode_field(element, message): + """Render pydantic model field encoding.""" + instance_attr = f"{message.name.lower()}.{element.name}" - if element.type in PRIMITIVE_TYPE_MAP: - value = instance_attr - elif element.type in message.enum_names: - value = instance_attr - elif element.type in message.file.enum_names: + if ( + element.type in PRIMITIVE_TYPE_MAP + or element.type in message.enum_names + or element.type in message.file.enum_names + ): value = instance_attr else: # Message qualified = qualified_type(message, element.type) if element.cardinality == FieldCardinality.REPEATED: - return ( - f"for item in {instance_attr}:\n" - f" {qualified}.encode(proto_obj.{element.name}.add(), item)" - ) - elif element.cardinality == FieldCardinality.OPTIONAL: + return f"for item in {instance_attr}:\n" f" {qualified}.encode(proto_obj.{element.name}.add(), item)" + if element.cardinality == FieldCardinality.OPTIONAL: return ( f"if {instance_attr} is not None:\n" f" temp = proto_obj.{element.name}.__class__()\n" f" {qualified}.encode(temp, {instance_attr})\n" f" proto_obj.{element.name}.CopyFrom(temp)" ) - else: - return f"{qualified}.encode(proto_obj.{element.name}, {instance_attr})" + return f"{qualified}.encode(proto_obj.{element.name}, {instance_attr})" match element.cardinality: case FieldCardinality.REPEATED: @@ -140,6 +128,7 @@ def encode_field(element, message): def render_encoder(message: MessageAdapter) -> str: + """Render pydantic model .encode() method.""" def encode_element(element) -> str: match type(element): @@ -156,58 +145,64 @@ def encode_element(element) -> str: iter_items = f"for key, value in {message.name.lower()}.{element.name}.items():" if element.value_type in PRIMITIVE_TYPE_MAP: return f"{iter_items}\n proto_obj.{element.name}[key] = value" - elif element.value_type in message.file.enum_names: + if element.value_type in message.file.enum_names: return f"{iter_items}\n proto_obj.{element.name}[key] = {element.value_type}(value)" - elif element.value_type in message.enum_names: - return f"{iter_items}\n proto_obj.{element.name}[key] = {message.name}.{element.value_type}(value)" - else: - return f"{iter_items}\n {qualified_type(message, element.value_type)}.encode(proto_obj.{element.name}[key], value)" + if element.value_type in message.enum_names: + return ( + f"{iter_items}\n proto_obj.{element.name}[key] = {message.name}.{element.value_type}(value)" + ) + return f"{iter_items}\n {qualified_type(message, element.value_type)}.encode(proto_obj.{element.name}[key], value)" case _: - raise TypeError(f"Unexpected message type: {element}") + msg = f"Unexpected message type: {element}" + raise TypeError(msg) - elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) + elements = filter(lambda e: not isinstance(e, MessageAdapter | ast.Enum), message.elements) inner = "\n".join(map(encode_element, elements)) indented_inner = textwrap.indent(inner, " ") return ( "@staticmethod\n" f"def encode(proto_obj, {message.name.lower()}: {message.name}) -> None:\n" - f" \"\"\"Encode {message.name} to protobuf.\"\"\"\n\n" + f' """Encode {message.name} to protobuf."""\n\n' f"{indented_inner}\n" ) + def decode_field(field: ast.Field, message: MessageAdapter) -> str: + """Render pydantic model field decoding.""" + instance_field = f"proto_obj.{field.name}" - if field.type in PRIMITIVE_TYPE_MAP: - value = instance_field - elif field.type in message.enum_names: - value = instance_field - elif field.type in message.file.enum_names: + if field.type in PRIMITIVE_TYPE_MAP or field.type in message.enum_names or field.type in message.file.enum_names: value = instance_field else: qualified = qualified_type(message, field.type) if field.cardinality == FieldCardinality.REPEATED: return f"{field.name} = [{qualified}.decode(item) for item in {instance_field}]" - elif field.cardinality == FieldCardinality.OPTIONAL: - return (f"{field.name} = {qualified}.decode({instance_field}) " - f"if {instance_field} is not None and proto_obj.HasField(\"{field.name}\") " - f"else None") - else: - return f"{field.name} = {qualified}.decode({instance_field})" + if field.cardinality == FieldCardinality.OPTIONAL: + return ( + f"{field.name} = {qualified}.decode({instance_field}) " + f'if {instance_field} is not None and proto_obj.HasField("{field.name}") ' + f"else None" + ) + return f"{field.name} = {qualified}.decode({instance_field})" match field.cardinality: case FieldCardinality.REPEATED: return f"{field.name} = list({value})" case FieldCardinality.OPTIONAL: - return (f"{field.name} = {value} " - f"if {instance_field} is not None and proto_obj.HasField(\"{field.name}\") " - f"else None") + return ( + f"{field.name} = {value} " + f'if {instance_field} is not None and proto_obj.HasField("{field.name}") ' + f"else None" + ) case FieldCardinality.REQUIRED | None: return f"{field.name} = {value}" case _: - raise TypeError(f"Unexpected cardinality: {field.cardinality}") + msg = f"Unexpected cardinality: {field.cardinality}" + raise TypeError(msg) def render_decoder(message: MessageAdapter) -> str: + """Render pydantic model .decode() method.""" def decode_element(element) -> str: match type(element): @@ -217,34 +212,36 @@ def decode_element(element) -> str: return decode_field(element, message) case ast.OneOf: return "\n".join( - f"if proto_obj.HasField(\"{e.name}\"):\n {element.name} = proto_obj.{e.name}" + f'if proto_obj.HasField("{e.name}"):\n {element.name} = proto_obj.{e.name}' for e in element.elements ) case ast.MapField: iter_items = f"{element.name} = {{}}\nfor key, value in proto_obj.{element.name}.items():" if element.value_type in PRIMITIVE_TYPE_MAP: return f"{element.name} = dict(proto_obj.{element.name})" - elif element.value_type in message.file.enum_names: + if element.value_type in message.file.enum_names: return f"{iter_items}\n {element.name}[key] = {element.value_type}(value)" - elif element.value_type in message.enum_names: + if element.value_type in message.enum_names: return f"{iter_items}\n {element.name}[key] = {message.name}.{element.value_type}(value)" - else: - return (f"{element.name} = {{ key: {qualified_type(message, element.value_type)}.decode(item) " - f"for key, item in proto_obj.{element.name}.items() }}") + return ( + f"{element.name} = {{ key: {qualified_type(message, element.value_type)}.decode(item) " + f"for key, item in proto_obj.{element.name}.items() }}" + ) case _: - raise TypeError(f"Unexpected message element type: {element}") + msg = f"Unexpected message element type: {element}" + raise TypeError(msg) def constructor_kwargs(elements) -> str: types = (ast.Field, ast.MapField, ast.OneOf) return ",\n ".join(f"{e.name}={e.name}" for e in elements if isinstance(e, types)) constructor = f"return cls(\n {constructor_kwargs(message.elements)}\n)" - elements = filter(lambda e: not isinstance(e, (MessageAdapter, ast.Enum)), message.elements) + elements = filter(lambda e: not isinstance(e, MessageAdapter | ast.Enum), message.elements) inner = "\n".join(map(decode_element, elements)) + f"\n\n{constructor}" indented_inner = textwrap.indent(inner, " ") return ( "@classmethod\n" f"def decode(cls, proto_obj) -> {message.name}:\n" - f" \"\"\"Decode proto_obj to {message.name}.\"\"\"\n\n" + f' """Decode proto_obj to {message.name}."""\n\n' f"{indented_inner}\n" - ) \ No newline at end of file + ) diff --git a/auto_dev/protocols/performatives.py b/auto_dev/protocols/performatives.py index 6d02766c..fd1546be 100644 --- a/auto_dev/protocols/performatives.py +++ b/auto_dev/protocols/performatives.py @@ -1,6 +1,5 @@ """Module for parsing protocol performatives.""" - SCALAR_MAP = { "int": "conint(ge=Int32.min(), le=Int32.max())", "float": "confloat(ge=Double.min(), le=Double.max())", @@ -30,28 +29,28 @@ def _split_top_level(s: str, sep: str = ",") -> list[str]: def parse_annotation(annotation: str) -> str: - """Parse Performative annotation""" + """Parse Performative annotation.""" if annotation.startswith("pt:"): core = annotation[3:] elif annotation.startswith("ct:"): return annotation[3:] else: - raise ValueError(f"Unknown annotation prefix in: {annotation}") + msg = f"Unknown annotation prefix in: {annotation}" + raise ValueError(msg) if core.startswith("optional[") and core.endswith("]"): - inner = core[len("optional["):-1] + inner = core[len("optional[") : -1] return f"{parse_annotation(inner)} | None" - elif core.startswith("list[") and core.endswith("]"): - inner = core[len("list["):-1] + if core.startswith("list[") and core.endswith("]"): + inner = core[len("list[") : -1] return f"tuple[{parse_annotation(inner)}]" # quirk of the framework! - elif core.startswith("dict[") and core.endswith("]"): - inner = core[len("dict["):-1] + if core.startswith("dict[") and core.endswith("]"): + inner = core[len("dict[") : -1] key_str, value_str = _split_top_level(inner) return f"dict[{parse_annotation(key_str)}, {parse_annotation(value_str)}]" - elif core.startswith("union[") and core.endswith("]"): - inner = core[len("union["):-1] + if core.startswith("union[") and core.endswith("]"): + inner = core[len("union[") : -1] parts = _split_top_level(inner) return " | ".join(parse_annotation(p) for p in parts) - else: - return SCALAR_MAP[core] + return SCALAR_MAP[core] diff --git a/auto_dev/protocols/primitives.py b/auto_dev/protocols/primitives.py index 3abd20d7..4f7b4da7 100644 --- a/auto_dev/protocols/primitives.py +++ b/auto_dev/protocols/primitives.py @@ -4,6 +4,7 @@ import struct from abc import ABC, abstractmethod + from pydantic_core import SchemaValidator, core_schema @@ -17,10 +18,10 @@ min_uint64 = 0 max_uint64 = (1 << 64) - 1 -min_float32 = struct.unpack('f', struct.pack('I', 0xFF7FFFFF))[0] -max_float32 = struct.unpack('f', struct.pack('I', 0x7F7FFFFF))[0] -min_float64 = struct.unpack('d', struct.pack('Q', 0xFFEFFFFFFFFFFFFF))[0] -max_float64 = struct.unpack('d', struct.pack('Q', 0x7FEFFFFFFFFFFFFF))[0] +min_float32 = struct.unpack("f", struct.pack("I", 0xFF7FFFFF))[0] +max_float32 = struct.unpack("f", struct.pack("I", 0x7F7FFFFF))[0] +min_float64 = struct.unpack("d", struct.pack("Q", 0xFFEFFFFFFFFFFFFF))[0] +max_float64 = struct.unpack("d", struct.pack("Q", 0x7FEFFFFFFFFFFFFF))[0] def to_float32(value: float) -> float: @@ -34,12 +35,14 @@ class BaseConstrainedFloat(float, ABC): @classmethod @abstractmethod def min(cls) -> float: - raise NotImplementedError(f"{cls.__name__}.min() is not implemented.") + msg = f"{cls.__name__}.min() is not implemented." + raise NotImplementedError(msg) @classmethod @abstractmethod def max(cls) -> float: - raise NotImplementedError(f"{cls.__name__}.max() is not implemented.") + msg = f"{cls.__name__}.max() is not implemented." + raise NotImplementedError(msg) def __new__(cls, value: float = 0.0, *args, **kwargs) -> "BaseConstrainedInt": schema = core_schema.float_schema(strict=True, ge=cls.min(), le=cls.max()) @@ -59,12 +62,14 @@ class BaseConstrainedInt(int, ABC): @classmethod @abstractmethod def min(cls) -> int: - raise NotImplementedError(f"{cls.__name__}.min() is not implemented.") + msg = f"{cls.__name__}.min() is not implemented." + raise NotImplementedError(msg) @classmethod @abstractmethod def max(cls) -> int: - raise NotImplementedError(f"{cls.__name__}.max() is not implemented.") + msg = f"{cls.__name__}.max() is not implemented." + raise NotImplementedError(msg) def __new__(cls, value: int = 0, *args, **kwargs) -> "BaseConstrainedInt": schema = core_schema.int_schema(strict=True, ge=cls.min(), le=cls.max()) @@ -76,20 +81,26 @@ def __new__(cls, value: int = 0, *args, **kwargs) -> "BaseConstrainedInt": def __get_pydantic_core_schema__(cls, source, handler): schema = core_schema.int_schema(strict=True, ge=cls.min(), le=cls.max()) return core_schema.no_info_wrap_validator_function(cls, schema) - + class Double(BaseConstrainedFloat): @classmethod - def min(cls): return min_float64 + def min(cls): + return min_float64 + @classmethod - def max(cls): return max_float64 + def max(cls): + return max_float64 class Float(BaseConstrainedFloat): @classmethod - def min(cls): return min_float32 + def min(cls): + return min_float32 + @classmethod - def max(cls): return max_float32 + def max(cls): + return max_float32 def __new__(cls, value: float = 0.0, *args, **kwargs) -> "Float": return super().__new__(cls, to_float32(float(value))) @@ -97,72 +108,102 @@ def __new__(cls, value: float = 0.0, *args, **kwargs) -> "Float": class Int32(BaseConstrainedInt): @classmethod - def min(cls): return min_int32 + def min(cls): + return min_int32 + @classmethod - def max(cls): return max_int32 + def max(cls): + return max_int32 class Int64(BaseConstrainedInt): @classmethod - def min(cls): return min_int64 + def min(cls): + return min_int64 + @classmethod - def max(cls): return max_int64 + def max(cls): + return max_int64 class UInt32(BaseConstrainedInt): @classmethod - def min(cls): return min_uint32 + def min(cls): + return min_uint32 + @classmethod - def max(cls): return max_uint32 + def max(cls): + return max_uint32 class UInt64(BaseConstrainedInt): @classmethod - def min(cls): return min_uint64 + def min(cls): + return min_uint64 + @classmethod - def max(cls): return max_uint64 + def max(cls): + return max_uint64 class SInt32(BaseConstrainedInt): @classmethod - def min(cls): return min_int32 + def min(cls): + return min_int32 + @classmethod - def max(cls): return max_int32 + def max(cls): + return max_int32 class SInt64(BaseConstrainedInt): @classmethod - def min(cls): return min_int64 + def min(cls): + return min_int64 + @classmethod - def max(cls): return max_int64 + def max(cls): + return max_int64 class Fixed32(BaseConstrainedInt): @classmethod - def min(cls): return min_uint32 + def min(cls): + return min_uint32 + @classmethod - def max(cls): return max_uint32 + def max(cls): + return max_uint32 class Fixed64(BaseConstrainedInt): @classmethod - def min(cls): return min_uint64 + def min(cls): + return min_uint64 + @classmethod - def max(cls): return max_uint64 + def max(cls): + return max_uint64 class SFixed32(BaseConstrainedInt): @classmethod - def min(cls): return min_int32 + def min(cls): + return min_int32 + @classmethod - def max(cls): return max_int32 + def max(cls): + return max_int32 class SFixed64(BaseConstrainedInt): @classmethod - def min(cls): return min_int64 + def min(cls): + return min_int64 + @classmethod - def max(cls): return max_int64 + def max(cls): + return max_int64 FLOAT_PRIMITIVES = { diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 45788779..a23835e4 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -1,20 +1,22 @@ +"""Module for generating pydantic models and associated hypothesis tests.""" + import re -import os -import sys import inspect import subprocess # nosec: B404 -from pathlib import Path from types import ModuleType +from pathlib import Path +from jinja2 import Environment, FileSystemLoader from proto_schema_parser.parser import Parser -from jinja2 import Template, Environment, FileSystemLoader -from auto_dev.constants import DEFAULT_ENCODING, JINJA_TEMPLATE_FOLDER -from auto_dev.protocols.adapters import FileAdapter +from auto_dev.constants import JINJA_TEMPLATE_FOLDER from auto_dev.protocols import formatter, primitives as primitives_module +from auto_dev.protocols.adapters import FileAdapter def get_repo_root() -> Path: + """Get repository root directory path.""" + command = ["git", "rev-parse", "--show-toplevel"] repo_root = subprocess.check_output(command, stderr=subprocess.STDOUT).strip() # nosec: B603 return Path(repo_root.decode("utf-8")) @@ -23,29 +25,35 @@ def get_repo_root() -> Path: def _compute_import_path(file_path: Path, repo_root: Path) -> str: if file_path.is_relative_to(repo_root): relative_path = file_path.relative_to(repo_root) - return ".".join(relative_path.with_suffix('').parts) + return ".".join(relative_path.with_suffix("").parts) return f".{file_path.stem}" def _remove_runtime_version_code(pb2_content: str) -> str: - pb2_content = re.sub(r'^from\s+google\.protobuf\s+import\s+runtime_version\s+as\s+_runtime_version\s*\n', '', pb2_content, flags=re.MULTILINE) - pb2_content = re.sub(r'_runtime_version\.ValidateProtobufRuntimeVersion\s*\(\s*[^)]*\)\s*\n?', '', pb2_content, flags=re.DOTALL) - return pb2_content + pb2_content = re.sub( + r"^from\s+google\.protobuf\s+import\s+runtime_version\s+as\s+_runtime_version\s*\n", + "", + pb2_content, + flags=re.MULTILINE, + ) + return re.sub( + r"_runtime_version\.ValidateProtobufRuntimeVersion\s*\(\s*[^)]*\)\s*\n?", "", pb2_content, flags=re.DOTALL + ) def _get_locally_defined_classes(module: ModuleType) -> list[type]: - def locally_defined(obj): return isinstance(obj, type) and obj.__module__ == module.__name__ return list(filter(locally_defined, vars(module).values())) -def create( +def create( # noqa: PLR0914 proto_inpath: Path, code_outpath: Path, test_outpath: Path, ) -> None: + """Main function to create pydantic models from a .proto file.""" repo_root = get_repo_root() env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa @@ -53,9 +61,9 @@ def create( content = proto_inpath.read_text() primitives_py = repo_root / "auto_dev" / "protocols" / "primitives.py" - strategies_template = env.get_template('protocols/primitive_strategies.jinja') - protodantic_template = env.get_template('protocols/protodantic.jinja') - hypothesis_template = env.get_template('protocols/hypothesis.jinja') + strategies_template = env.get_template("protocols/primitive_strategies.jinja") + protodantic_template = env.get_template("protocols/protodantic.jinja") + hypothesis_template = env.get_template("protocols/hypothesis.jinja") primitives_outpath = code_outpath.parent / primitives_py.name primitives_outpath.write_text(primitives_py.read_text()) @@ -71,7 +79,7 @@ def create( proto_inpath.name, ], cwd=proto_inpath.parent, - check=True + check=True, ) custom_primitives = _get_locally_defined_classes(primitives_module) @@ -81,7 +89,7 @@ def create( file = FileAdapter.from_file(Parser().parse(content)) - code = generated_code = protodantic_template.render( + generated_code = protodantic_template.render( file=file, formatter=formatter, float_primitives=float_primitives, @@ -107,7 +115,7 @@ def create( strategies_outpath.write_text(generated_strategies) strategies_import_path = _compute_import_path(strategies_outpath, repo_root) - tests = generated_tests = hypothesis_template.render( + generated_tests = hypothesis_template.render( file=file, float_primitives=float_primitives, integer_primitives=integer_primitives, diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index e4202e68..a81f3c78 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -1,3 +1,5 @@ +"""Module for generating protocols from a protocol.yaml specification.""" + import shutil import tempfile import subprocess @@ -50,22 +52,28 @@ class ProtocolSpecification(BaseModel): @property def name(self) -> str: + """Protocol name.""" return self.metadata.name @property def author(self) -> str: + """Protocol author.""" return self.metadata.author @property def camel_name(self) -> str: + """Protocol name in camel case.""" return snake_to_camel(self.metadata.name) @property def custom_types(self) -> list[str]: + """Top-level custom type names in protocol specification.""" return [custom_type.removeprefix("ct:") for custom_type in self.custom_definitions] @property def performative_types(self) -> dict[str, dict[str, str]]: + """Python type annotation for performatives.""" + performative_types = {} for performative, message_fields in self.metadata.speech_acts.items(): field_types = {} @@ -76,18 +84,22 @@ def performative_types(self) -> dict[str, dict[str, str]]: @property def initial_performative_types(self) -> dict[str, dict[str, str]]: + """Python type annotation for initial performatives.""" return {k: v for k, v in self.performative_types.items() if k in self.interaction_model.initiation} @property def outpath(self) -> Path: + """Protocol expected outpath after `aea create` and `aea publish --local`.""" return protodantic.get_repo_root() / "packages" / self.author / "protocols" / self.name @property def code_outpath(self) -> Path: + """Outpath for custom_types.py.""" return self.outpath / "custom_types.py" @property def test_outpath(self) -> Path: + """Outpath for tests/test_custom_types.py.""" return self.outpath / "tests" / "test_custom_types.py" @@ -127,36 +139,43 @@ def read_protocol_spec(filepath: str) -> ProtocolSpecification: def run_cli_cmd(command: list[str], cwd: Path | None = None): + """Run CLI command helper function.""" + result = subprocess.run( - command, - shell=False, - capture_output=True, - text=True, - check=False, - cwd=cwd or Path.cwd(), - ) + command, + shell=False, + capture_output=True, + text=True, + check=False, + cwd=cwd or Path.cwd(), + ) if result.returncode != 0: msg = f"Failed: {command}:\n{result.stderr}" raise ValueError(msg) def initialize_packages(repo_root: Path) -> None: + """Initialize packages directory with packages.json file.""" packages_dir = repo_root / "packages" if not packages_dir.exists(): run_cli_cmd(["aea", "packages", "init"], cwd=repo_root) def run_aea_generate_protocol(protocol_path: Path, language: str, agent_dir: Path) -> None: + """Run `aea generate protocol`.""" command = ["aea", "-s", "generate", "protocol", str(protocol_path), "--l", language] run_cli_cmd(command, cwd=agent_dir) def run_aea_publish(agent_dir: Path) -> None: + """Run `aea publish --local --push-missing`.""" command = ["aea", "publish", "--local", "--push-missing"] run_cli_cmd(command, cwd=agent_dir) def generate_readme(protocol, template): + """Generate protocol README.md file.""" + readme = protocol.outpath / "README.md" protocol_definition = Path(protocol.path).read_text(encoding="utf-8") content = template.render( @@ -195,15 +214,17 @@ def generate_custom_types(protocol: ProtocolSpecification): ) shutil.move(str(backup_pb2), str(proto_pb2)) pb2_content = proto_pb2.read_text() - pb2_content = protodantic._remove_runtime_version_code(pb2_content) + pb2_content = protodantic._remove_runtime_version_code(pb2_content) # noqa: SLF001 proto_pb2.write_text(pb2_content) tmp_proto_path.unlink() def rewrite_test_custom_types(protocol: ProtocolSpecification) -> None: + """Rewrite custom_types.py import to accomodate aea message wrapping during .proto generation.""" + content = protocol.test_outpath.read_text() a = f"packages.{protocol.author}.protocols.{protocol.name} import {protocol.name}_pb2" - b = f"packages.{protocol.author}.protocols.{protocol.name}.{protocol.name}_pb2 import {protocol.camel_name}Message as {protocol.name}_pb2 # noqa: N813" + b = f"packages.{protocol.author}.protocols.{protocol.name}.{protocol.name}_pb2 import {protocol.camel_name}Message as {protocol.name}_pb2 # noqa: N813" # noqa: E501 protocol.test_outpath.write_text(content.replace(a, b)) @@ -233,11 +254,14 @@ def generate_dialogues(protocol: ProtocolSpecification, template): def generate_tests_init(protocol: ProtocolSpecification) -> None: + """Generate tests/__init__.py.""" test_init_file = protocol.outpath / "tests" / "__init__.py" test_init_file.write_text(f'"""Test module for the {protocol.name}"""') def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: + """Generate tests/test_dialogue.py.""" + output = template.render( header="# Auto-generated by tool", author=protocol.author, @@ -252,6 +276,8 @@ def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: def generate_test_messages(protocol: ProtocolSpecification, template) -> None: + """Generate tests/test_messages.py.""" + output = template.render( header="# Auto-generated by tool", author=protocol.author, @@ -266,6 +292,7 @@ def generate_test_messages(protocol: ProtocolSpecification, template) -> None: def update_yaml(protocol, dependencies: dict[str, dict[str, str]]) -> None: + """Update protocol.yaml dependencies.""" protocol_yaml = protocol.outpath / "protocol.yaml" content = yaml.safe_load(protocol_yaml.read_text()) for package_name, package_info in dependencies.items(): @@ -275,21 +302,24 @@ def update_yaml(protocol, dependencies: dict[str, dict[str, str]]) -> None: def run_adev_fmt(protocol) -> None: + """Run `adev -v fmt`.""" command = ["adev", "-v", "fmt", "-p", str(protocol.outpath)] run_cli_cmd(command) def run_adev_lint(protocol) -> None: + """Run `adev -v lint`.""" command = ["adev", "-v", "lint", "-p", str(protocol.outpath)] run_cli_cmd(command) def run_aea_fingerprint(protocol) -> None: + """Run `aea fingerprint protocol`.""" command = ["aea", "fingerprint", "protocol", protocol.metadata.protocol_specification_id] run_cli_cmd(command) -def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): +def protocol_scaffolder(protocol_specification_path: str, language, logger, verbose: bool = True): # noqa: ARG001 """Scaffolding protocol components. Args: @@ -315,7 +345,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb run_aea_generate_protocol(protocol.path, language=language, agent_dir=agent_dir) # Ensures `protocol.outpath` exists, required for correct import path generation - # TODO: on error during any part of this process, clean up (remove) `protocol.outpath` + # TODO: on error during any part of this process, clean up (remove) `protocol.outpath` # noqa: FIX002, TD002, TD003 run_aea_publish(agent_dir) # 3. create README.md diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 3f19199f..e74a3072 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1,3 +1,5 @@ +"""Module for testing protocol generation.""" + import os import shutil import tempfile @@ -6,58 +8,58 @@ from pathlib import Path import pytest -from jinja2 import Template, Environment, FileSystemLoader -from auto_dev.protocols import protodantic +from auto_dev.protocols import protodantic, performatives from auto_dev.protocols.scaffolder import read_protocol_spec -from auto_dev.protocols import performatives -@functools.lru_cache() +@functools.lru_cache def _get_proto_files() -> dict[str, Path]: repo_root = protodantic.get_repo_root() path = repo_root / "tests" / "data" / "protocols" / "protobuf" assert path.exists() - proto_files = {file.name: file for file in path.glob("*.proto")} - return proto_files + return {file.name: file for file in path.glob("*.proto")} -@functools.lru_cache() +@functools.lru_cache def _get_capitalization_station_protocols() -> dict[str, Path]: repo_root = protodantic.get_repo_root() path = repo_root / "tests" / "data" / "protocols" / ".capitalisation_station" assert path.exists() - yaml_files = {file.name: file for file in path.glob("*.yaml")} - return yaml_files + return {file.name: file for file in path.glob("*.yaml")} PROTO_FILES = _get_proto_files() PROTOCOL_FILES = _get_capitalization_station_protocols() -@pytest.mark.parametrize("proto_path", [ - PROTO_FILES["primitives.proto"], - PROTO_FILES["optional_primitives.proto"], - PROTO_FILES["repeated_primitives.proto"], - PROTO_FILES["basic_enum.proto"], - PROTO_FILES["optional_enum.proto"], - PROTO_FILES["repeated_enum.proto"], - PROTO_FILES["nested_enum.proto"], - PROTO_FILES["empty_message.proto"], - PROTO_FILES["simple_message.proto"], - PROTO_FILES["repeated_message.proto"], - PROTO_FILES["optional_message.proto"], - PROTO_FILES["message_reference.proto"], - PROTO_FILES["nested_message.proto"], - PROTO_FILES["deeply_nested_message.proto"], - PROTO_FILES["oneof_value.proto"], - PROTO_FILES["map_primitive_values.proto"], - PROTO_FILES["map_enum.proto"], - PROTO_FILES["map_message.proto"], - PROTO_FILES["map_optional_primitive_values.proto"], - PROTO_FILES["map_repeated_primitive_values.proto"], -]) +@pytest.mark.parametrize( + "proto_path", + [ + PROTO_FILES["primitives.proto"], + PROTO_FILES["optional_primitives.proto"], + PROTO_FILES["repeated_primitives.proto"], + PROTO_FILES["basic_enum.proto"], + PROTO_FILES["optional_enum.proto"], + PROTO_FILES["repeated_enum.proto"], + PROTO_FILES["nested_enum.proto"], + PROTO_FILES["empty_message.proto"], + PROTO_FILES["simple_message.proto"], + PROTO_FILES["repeated_message.proto"], + PROTO_FILES["optional_message.proto"], + PROTO_FILES["message_reference.proto"], + PROTO_FILES["nested_message.proto"], + PROTO_FILES["deeply_nested_message.proto"], + PROTO_FILES["oneof_value.proto"], + PROTO_FILES["map_primitive_values.proto"], + PROTO_FILES["map_enum.proto"], + PROTO_FILES["map_message.proto"], + PROTO_FILES["map_optional_primitive_values.proto"], + PROTO_FILES["map_repeated_primitive_values.proto"], + ], +) def test_protodantic(proto_path: Path): + """Test protodantic.create.""" with tempfile.TemporaryDirectory() as tmp_dir: tmp_path = Path(tmp_dir) @@ -69,45 +71,56 @@ def test_protodantic(proto_path: Path): assert exit_code == 0 -@pytest.mark.parametrize("annotation, expected", +@pytest.mark.parametrize( + ("annotation", "expected"), [ ("pt:int", "conint(ge=Int32.min(), le=Int32.max())"), ("pt:float", "confloat(ge=Double.min(), le=Double.max())"), ("pt:list[pt:int]", "tuple[conint(ge=Int32.min(), le=Int32.max())]"), ("pt:optional[pt:int]", "conint(ge=Int32.min(), le=Int32.max()) | None"), ("pt:dict[pt:str, pt:int]", "dict[str, conint(ge=Int32.min(), le=Int32.max())]"), - ("pt:list[pt:union[pt:dict[pt:str, pt:int], pt:list[pt:bytes]]]", "tuple[dict[str, conint(ge=Int32.min(), le=Int32.max())] | tuple[bytes]]"), - ("pt:optional[pt:dict[pt:union[pt:str, pt:int], pt:list[pt:union[pt:float, pt:bool]]]]", "dict[str | conint(ge=Int32.min(), le=Int32.max()), tuple[confloat(ge=Double.min(), le=Double.max()) | bool]] | None"), - ] + ( + "pt:list[pt:union[pt:dict[pt:str, pt:int], pt:list[pt:bytes]]]", + "tuple[dict[str, conint(ge=Int32.min(), le=Int32.max())] | tuple[bytes]]", + ), + ( + "pt:optional[pt:dict[pt:union[pt:str, pt:int], pt:list[pt:union[pt:float, pt:bool]]]]", + "dict[str | conint(ge=Int32.min(), le=Int32.max()), tuple[confloat(ge=Double.min(), le=Double.max()) | bool]] | None", # noqa: E501 + ), + ], ) def test_parse_performative_annotation(annotation: str, expected: str): - """Test parse_performative_annotation""" + """Test parse_performative_annotation.""" assert performatives.parse_annotation(annotation) == expected -@pytest.mark.parametrize("protocol_spec", [ - PROTOCOL_FILES["balances.yaml"], - # PROTOCOL_FILES["bridge.yaml"], - # PROTOCOL_FILES["cross_chain_arbtrage.yaml"], - PROTOCOL_FILES["default.yaml"], - PROTOCOL_FILES["liquidity_provision.yaml"], - PROTOCOL_FILES["markets.yaml"], - PROTOCOL_FILES["ohlcv.yaml"], - # PROTOCOL_FILES["order_book.yaml"], - PROTOCOL_FILES["orders.yaml"], - PROTOCOL_FILES["positions.yaml"], - PROTOCOL_FILES["spot_asset.yaml"], - PROTOCOL_FILES["tickers.yaml"], -]) +@pytest.mark.parametrize( + "protocol_spec", + [ + PROTOCOL_FILES["balances.yaml"], + # PROTOCOL_FILES["bridge.yaml"], # noqa: ERA001 + # PROTOCOL_FILES["cross_chain_arbtrage.yaml"], # noqa: ERA001 + PROTOCOL_FILES["default.yaml"], + PROTOCOL_FILES["liquidity_provision.yaml"], + PROTOCOL_FILES["markets.yaml"], + PROTOCOL_FILES["ohlcv.yaml"], + # PROTOCOL_FILES["order_book.yaml"], # noqa: ERA001 + PROTOCOL_FILES["orders.yaml"], + PROTOCOL_FILES["positions.yaml"], + PROTOCOL_FILES["spot_asset.yaml"], + PROTOCOL_FILES["tickers.yaml"], + ], +) def test_scaffold_protocol(protocol_spec: Path): - """Test `adev scaffold protocol` command""" + """Test `adev scaffold protocol` command.""" protocol = read_protocol_spec(protocol_spec) repo_root = protodantic.get_repo_root() packages_dir = repo_root / "packages" if packages_dir.exists(): - raise Exception("Test assumes no packages directory exists in this repo") + msg = "Test assumes no packages directory exists in this repo" + raise ValueError(msg) packages_dir.mkdir(exist_ok=False) tmp_test_agent = repo_root / "tmp_test_agent" @@ -116,9 +129,12 @@ def test_scaffold_protocol(protocol_spec: Path): subprocess.run(["aea", "create", tmp_test_agent.name], check=True, cwd=repo_root) os.chdir(tmp_test_agent) - result = subprocess.run(["adev", "-v", "scaffold", "protocol", str(protocol_spec)], check=False, text=True, capture_output=True) + result = subprocess.run( + ["adev", "-v", "scaffold", "protocol", str(protocol_spec)], check=False, text=True, capture_output=True + ) if result.returncode != 0: - raise ValueError(f"Protocol scaffolding failed: {result.stderr}") + msg = f"Protocol scaffolding failed: {result.stderr}" + raise ValueError(msg) test_dir = packages_dir / protocol.metadata.author / "protocols" / protocol.metadata.name / "tests" exit_code = pytest.main([test_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) diff --git a/tests/test_utils.py b/tests/test_utils.py index e23af27b..07cc4de6 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -14,12 +14,12 @@ from auto_dev.utils import ( get_paths, get_logger, + file_swapper, get_packages, load_aea_ctx, remove_prefix, remove_suffix, write_to_file, - file_swapper, folder_swapper, has_package_code_changed, ) @@ -157,7 +157,7 @@ def test_remove_suffix(): def test_file_swapper(): - """Test file_swapper""" + """Test file_swapper.""" content_a = "AAA" content_b = "BBB" From 2c50c479bcce2834569bce2e3c85607b2e85b026 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 13:41:52 +0200 Subject: [PATCH 144/189] fix: use `aea push --local protocol` instead of `aea publish --local --push-missing` in during protocol generation --- auto_dev/protocols/scaffolder.py | 8 ++++---- tests/test_protocol.py | 9 +-------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index a81f3c78..49059be0 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -167,9 +167,9 @@ def run_aea_generate_protocol(protocol_path: Path, language: str, agent_dir: Pat run_cli_cmd(command, cwd=agent_dir) -def run_aea_publish(agent_dir: Path) -> None: - """Run `aea publish --local --push-missing`.""" - command = ["aea", "publish", "--local", "--push-missing"] +def run_push_local_protocol(protocol: ProtocolSpecification, agent_dir: Path) -> None: + """Run `aea push --local protocol`.""" + command = ["aea", "push", "--local", "protocol", protocol.metadata.protocol_specification_id] run_cli_cmd(command, cwd=agent_dir) @@ -346,7 +346,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # Ensures `protocol.outpath` exists, required for correct import path generation # TODO: on error during any part of this process, clean up (remove) `protocol.outpath` # noqa: FIX002, TD002, TD003 - run_aea_publish(agent_dir) + run_push_local_protocol(protocol, agent_dir) # 3. create README.md template = env.get_template("protocols/README.jinja") diff --git a/tests/test_protocol.py b/tests/test_protocol.py index e74a3072..065e1769 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -115,14 +115,7 @@ def test_scaffold_protocol(protocol_spec: Path): """Test `adev scaffold protocol` command.""" protocol = read_protocol_spec(protocol_spec) - repo_root = protodantic.get_repo_root() - packages_dir = repo_root / "packages" - if packages_dir.exists(): - msg = "Test assumes no packages directory exists in this repo" - raise ValueError(msg) - - packages_dir.mkdir(exist_ok=False) tmp_test_agent = repo_root / "tmp_test_agent" original_cwd = os.getcwd() try: @@ -141,5 +134,5 @@ def test_scaffold_protocol(protocol_spec: Path): assert exit_code == 0 finally: shutil.rmtree(tmp_test_agent) - shutil.rmtree(packages_dir) + shutil.rmtree(protocol.outpath) os.chdir(original_cwd) From def919f3163df20de02861209b52a72f4034ddc9 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 14:24:18 +0200 Subject: [PATCH 145/189] fix: test_scaffold_protocol --- tests/test_protocol.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 065e1769..2dbce3a5 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -116,6 +116,7 @@ def test_scaffold_protocol(protocol_spec: Path): protocol = read_protocol_spec(protocol_spec) repo_root = protodantic.get_repo_root() + packages_dir = repo_root / "packages" tmp_test_agent = repo_root / "tmp_test_agent" original_cwd = os.getcwd() try: @@ -133,6 +134,6 @@ def test_scaffold_protocol(protocol_spec: Path): exit_code = pytest.main([test_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) assert exit_code == 0 finally: + os.chdir(original_cwd) shutil.rmtree(tmp_test_agent) shutil.rmtree(protocol.outpath) - os.chdir(original_cwd) From e33ff7bb78af6ed37d462bab55c1262263adeb7f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 16:34:51 +0200 Subject: [PATCH 146/189] fix: test_scaffold_protocol --- auto_dev/protocols/scaffolder.py | 13 +------- tests/test_protocol.py | 55 +++++++++++++++++++------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 49059be0..4eff10a2 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -154,13 +154,6 @@ def run_cli_cmd(command: list[str], cwd: Path | None = None): raise ValueError(msg) -def initialize_packages(repo_root: Path) -> None: - """Initialize packages directory with packages.json file.""" - packages_dir = repo_root / "packages" - if not packages_dir.exists(): - run_cli_cmd(["aea", "packages", "init"], cwd=repo_root) - - def run_aea_generate_protocol(protocol_path: Path, language: str, agent_dir: Path) -> None: """Run `aea generate protocol`.""" command = ["aea", "-s", "generate", "protocol", str(protocol_path), "--l", language] @@ -332,15 +325,11 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb """ agent_dir = Path.cwd() - repo_root = protodantic.get_repo_root() env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa - # 0. Read spec data + # 1. Read spec data protocol = read_protocol_spec(protocol_specification_path) - # 1. initialize packages folder if non-existent - initialize_packages(repo_root) - # 2. AEA generate protocol run_aea_generate_protocol(protocol.path, language=language, agent_dir=agent_dir) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 2dbce3a5..e6e88372 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1,7 +1,6 @@ """Module for testing protocol generation.""" import os -import shutil import tempfile import functools import subprocess @@ -100,7 +99,7 @@ def test_parse_performative_annotation(annotation: str, expected: str): PROTOCOL_FILES["balances.yaml"], # PROTOCOL_FILES["bridge.yaml"], # noqa: ERA001 # PROTOCOL_FILES["cross_chain_arbtrage.yaml"], # noqa: ERA001 - PROTOCOL_FILES["default.yaml"], + # PROTOCOL_FILES["default.yaml"], # noqa: ERA001 PROTOCOL_FILES["liquidity_provision.yaml"], PROTOCOL_FILES["markets.yaml"], PROTOCOL_FILES["ohlcv.yaml"], @@ -111,29 +110,39 @@ def test_parse_performative_annotation(annotation: str, expected: str): PROTOCOL_FILES["tickers.yaml"], ], ) -def test_scaffold_protocol(protocol_spec: Path): +def test_scaffold_protocol(dummy_agent_tim, protocol_spec: Path): """Test `adev scaffold protocol` command.""" + assert dummy_agent_tim, "Dummy agent not created." + protocol = read_protocol_spec(protocol_spec) repo_root = protodantic.get_repo_root() packages_dir = repo_root / "packages" - tmp_test_agent = repo_root / "tmp_test_agent" - original_cwd = os.getcwd() - try: - subprocess.run(["aea", "create", tmp_test_agent.name], check=True, cwd=repo_root) - os.chdir(tmp_test_agent) - - result = subprocess.run( - ["adev", "-v", "scaffold", "protocol", str(protocol_spec)], check=False, text=True, capture_output=True - ) - if result.returncode != 0: - msg = f"Protocol scaffolding failed: {result.stderr}" - raise ValueError(msg) - - test_dir = packages_dir / protocol.metadata.author / "protocols" / protocol.metadata.name / "tests" - exit_code = pytest.main([test_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) - assert exit_code == 0 - finally: - os.chdir(original_cwd) - shutil.rmtree(tmp_test_agent) - shutil.rmtree(protocol.outpath) + protocol_outpath = packages_dir / protocol.metadata.author / "protocols" / protocol.metadata.name + + if protocol_outpath.exists(): + msg = f"Protocol already exists in dummy_agent_tim: {protocol_outpath}" + raise ValueError(msg) + + result = subprocess.run( + ["adev", "-v", "scaffold", "protocol", str(protocol_spec)], check=False, text=True, capture_output=True + ) + if result.returncode != 0: + msg = f"Protocol scaffolding failed: {result.stderr}" + raise ValueError(msg) + + # Point PYTHONPATH to the temporary project root so generated modules are discoverable + env = os.environ.copy() + env["PYTHONPATH"] = str(repo_root) + + test_dir = protocol_outpath / "tests" + command = ["pytest", str(test_dir), "-vv", "-s", "--tb=long", "-p", "no:warnings"] + result = subprocess.run( + command, + env=env, + check=False, + text=True, + capture_output=True, + ) + + assert result.returncode == 0, f"Failed pytest on generated protocol: {result.stderr}" From 6ceb34feec9288797f6bd522008b2216546042be Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 16:35:40 +0200 Subject: [PATCH 147/189] fix: python version in pyproject <3.14 -> <3.13 --- poetry.lock | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index e1b43a34..35f73e94 100644 --- a/poetry.lock +++ b/poetry.lock @@ -5537,5 +5537,5 @@ all = ["isort", "open-aea", "open-aea-ledger-cosmos", "open-aea-ledger-ethereum" [metadata] lock-version = "2.1" -python-versions = ">=3.10,<3.14" -content-hash = "c6cf6124a89ffbb32accbaff93d58f16ed1e41e7dde9cda256d96b797af835cd" +python-versions = ">=3.10,<3.13" +content-hash = "93e7bfb47436b45e1b894cab192eacf821f9b48090f62075e110b52aeef34151" diff --git a/pyproject.toml b/pyproject.toml index 9bd4f39c..41a5e543 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ include = "\\.pyi?$" exclude = "/(\n \\.eggs\n | \\.git\n | \\.hg\n | \\.mypy_cache\n | \\.tox\n | \\.venv\n | _build\n | buck-out\n | build\n | dist\n)/\n" [tool.poetry.dependencies] -python = ">=3.10,<3.14" +python = ">=3.10,<3.13" open-autonomy = "==0.19.7" open-aea = "==1.65.0" open-aea-test-autonomy = "==0.19.7" From 5d942545c942ac991d7654a6c316e3ff161c5a10 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 18:47:42 +0200 Subject: [PATCH 148/189] fix: pyproject.toml.template --- auto_dev/data/repo/templates/autonomy/pyproject.toml.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto_dev/data/repo/templates/autonomy/pyproject.toml.template b/auto_dev/data/repo/templates/autonomy/pyproject.toml.template index c79da680..2077b21b 100644 --- a/auto_dev/data/repo/templates/autonomy/pyproject.toml.template +++ b/auto_dev/data/repo/templates/autonomy/pyproject.toml.template @@ -14,7 +14,7 @@ classifiers = [ package-mode = false [tool.poetry.dependencies] -python = ">=3.10,<3.14" +python = ">=3.10,<3.13" open-aea-ledger-solana = "==1.65.0" open-aea-ledger-cosmos = "==1.65.0" open-aea-ledger-ethereum = "==1.65.0" From c9471c7407f56ab8e10af2c76a87d6e934b6f0ce Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 19:38:03 +0200 Subject: [PATCH 149/189] fix: file_swapper --- auto_dev/utils.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/auto_dev/utils.py b/auto_dev/utils.py index ee954824..e4e77ed8 100644 --- a/auto_dev/utils.py +++ b/auto_dev/utils.py @@ -236,17 +236,18 @@ def restore_directory(): def file_swapper(file_a: str | Path, file_b: str | Path): """Temporarily swap the location of two files.""" - def swap(swap_file: str): + def swap(swap_file: Path): shutil.move(file_a, swap_file) shutil.move(file_b, file_a) shutil.move(swap_file, file_b) - with tempfile.NamedTemporaryFile() as tmp_file: + with tempfile.TemporaryDirectory() as tmpdir: + tmp_path = Path(tmpdir) / "swapfile" + swap(tmp_path) try: - swap(tmp_file.name) yield finally: - swap(tmp_file.name) + swap(tmp_path) @contextmanager From 466f9a219063b44d2793364f8dca9a890f71acaf Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 21:15:07 +0200 Subject: [PATCH 150/189] fix: remove old test_scaffold_protocol --- tests/test_scaffold.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/test_scaffold.py b/tests/test_scaffold.py index 5c497ee2..6799cd70 100644 --- a/tests/test_scaffold.py +++ b/tests/test_scaffold.py @@ -89,24 +89,6 @@ def test_scaffold_fsm_with_aea_run(cli_runner, spec, dummy_agent_tim): assert "An error occurred during instantiation of connection valory" in result.output -def test_scaffold_protocol(cli_runner, dummy_agent_tim): - """Test scaffold protocol.""" - - path = Path.cwd() / ".." / "tests" / "data" / "dummy_protocol.yaml" - command = ["adev", "scaffold", "protocol", str(path)] - runner = cli_runner(command) - result = runner.execute() - assert result, runner.output - - assert runner.return_code == 0, result.output - assert "New protocol scaffolded" in runner.output - - protocol = read_protocol_spec(str(path)) - original_content = path.read_text(encoding=DEFAULT_ENCODING) - readme_path = dummy_agent_tim / "protocols" / protocol.metadata.name / "README.md" - assert original_content in readme_path.read_text(encoding=DEFAULT_ENCODING) - - @pytest.mark.skip(reason="Needs changes to scaffolder to handle directory structure") def test_scaffold_handler(dummy_agent_tim, openapi_test_case): """Test scaffold handler.""" From 39c9536937b2a54e6da9312d8be29ecebb21af86 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 21:15:36 +0200 Subject: [PATCH 151/189] fix: update templates/python/poetry.lock & templates/autonomy/poetry.lock --- .../data/repo/templates/autonomy/poetry.lock | 74 ++++++++-------- .../data/repo/templates/python/poetry.lock | 86 +++++++++---------- 2 files changed, 80 insertions(+), 80 deletions(-) diff --git a/auto_dev/data/repo/templates/autonomy/poetry.lock b/auto_dev/data/repo/templates/autonomy/poetry.lock index caeccf3b..0afd3c17 100644 --- a/auto_dev/data/repo/templates/autonomy/poetry.lock +++ b/auto_dev/data/repo/templates/autonomy/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -114,7 +114,7 @@ propcache = ">=0.2.0" yarl = ">=1.17.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] +speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] [[package]] name = "aiosignal" @@ -221,7 +221,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] trio = ["trio (>=0.26.1)"] [[package]] @@ -276,12 +276,12 @@ files = [ ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "autonomy-dev" @@ -1160,7 +1160,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" @@ -1211,10 +1211,10 @@ files = [ cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] +pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] @@ -1530,7 +1530,7 @@ pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"p dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] pycryptodome = ["pycryptodome (>=3.6.6,<4)"] -pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] +pysha3 = ["pysha3 (>=1.0.0,<2.0.0) ; python_version < \"3.9\"", "safe-pysha3 (>=1.0.0) ; python_version >= \"3.9\""] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] @@ -1574,10 +1574,10 @@ eth-utils = ">=2.0.0,<3.0.0" [package.extras] coincurve = ["coincurve (>=7.0.0,<16.0.0)"] -dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] +dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] eth-keys = ["eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)"] lint = ["flake8 (==3.0.4)", "mypy (==0.782)"] -test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] +test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] [[package]] name = "eth-rlp" @@ -1678,7 +1678,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "flask" @@ -1841,13 +1841,13 @@ graphql-core = ">=3.2,<3.3" yarl = ">=1.6,<2.0" [package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)"] -all = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] +aiohttp = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\""] +all = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] botocore = ["botocore (>=1.21,<2)"] -dev = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] +dev = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] httpx = ["httpx (>=0.23.1,<1)"] requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)"] -test = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] +test = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.4.0)"] websockets = ["websockets (>=10,<12)"] @@ -2002,7 +2002,7 @@ rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" [package.extras] -brotli = ["brotli", "brotlicffi"] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -2025,7 +2025,7 @@ exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} sortedcontainers = ">=2.1.0,<3.0.0" [package.extras] -all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2)"] +all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] codemods = ["libcst (>=0.3.16)"] crosshair = ["crosshair-tool (>=0.0.78)", "hypothesis-crosshair (>=0.0.18)"] @@ -2039,7 +2039,7 @@ pandas = ["pandas (>=1.1)"] pytest = ["pytest (>=4.6)"] pytz = ["pytz (>=2014.1)"] redis = ["redis (>=3.0.0)"] -zoneinfo = ["tzdata (>=2024.2)"] +zoneinfo = ["tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] [[package]] name = "idna" @@ -2772,8 +2772,8 @@ cryptography = ">=3.3" pynacl = ">=1.5" [package.extras] -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] +gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] invoke = ["invoke (>=2.0)"] [[package]] @@ -3150,7 +3150,7 @@ typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" @@ -3950,13 +3950,13 @@ files = [ ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] -core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "six" @@ -4240,7 +4240,7 @@ virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2, [package.extras] docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] -testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] +testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3) ; python_version < \"3.4\"", "psutil (>=5.6.1) ; platform_python_implementation == \"cpython\"", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] [[package]] name = "types-cachetools" @@ -4291,7 +4291,7 @@ files = [ ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -4355,7 +4355,7 @@ platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "watchdog" @@ -4431,10 +4431,10 @@ typing-extensions = ">=4.0.1" websockets = ">=10.0.0,<14.0.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0)", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] +dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0) ; python_version < \"3.8\"", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] docs = ["sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)"] ipfs = ["ipfshttpclient (==0.8.0a2)"] -tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1)", "py-geth (>=3.14.0,<4)"] +tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "py-geth (>=3.14.0,<4)"] [[package]] name = "websocket-client" @@ -4704,5 +4704,5 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.1" -python-versions = ">=3.10,<3.14" -content-hash = "fb5f7a33d2b8bec2fe868a378ea021fd00fd2a1a3b64c99a0afa0edb066a22d2" +python-versions = ">=3.10,<3.13" +content-hash = "4bca5d49773631ae3e70b50cba0bc76179f6cede4519e87005aa2b4eb975b139" diff --git a/auto_dev/data/repo/templates/python/poetry.lock b/auto_dev/data/repo/templates/python/poetry.lock index f4861da1..c2cedde1 100644 --- a/auto_dev/data/repo/templates/python/poetry.lock +++ b/auto_dev/data/repo/templates/python/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -114,7 +114,7 @@ propcache = ">=0.2.0" yarl = ">=1.17.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] +speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] [[package]] name = "aiosignal" @@ -221,7 +221,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] trio = ["trio (>=0.26.1)"] [[package]] @@ -276,12 +276,12 @@ files = [ ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "autonomy-dev" @@ -1178,7 +1178,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "cryptography" @@ -1230,10 +1230,10 @@ markers = {dev = "sys_platform == \"linux\""} cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] +pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] @@ -1561,7 +1561,7 @@ pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"p dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] pycryptodome = ["pycryptodome (>=3.6.6,<4)"] -pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] +pysha3 = ["pysha3 (>=1.0.0,<2.0.0) ; python_version < \"3.9\"", "safe-pysha3 (>=1.0.0) ; python_version >= \"3.9\""] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] @@ -1605,10 +1605,10 @@ eth-utils = ">=2.0.0,<3.0.0" [package.extras] coincurve = ["coincurve (>=7.0.0,<16.0.0)"] -dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] +dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] eth-keys = ["eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)"] lint = ["flake8 (==3.0.4)", "mypy (==0.782)"] -test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome]", "eth-hash[pysha3]", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] +test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] [[package]] name = "eth-rlp" @@ -1709,7 +1709,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "flask" @@ -1872,13 +1872,13 @@ graphql-core = ">=3.2,<3.3" yarl = ">=1.6,<2.0" [package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)"] -all = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] +aiohttp = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\""] +all = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] botocore = ["botocore (>=1.21,<2)"] -dev = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] +dev = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] httpx = ["httpx (>=0.23.1,<1)"] requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)"] -test = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] +test = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.4.0)"] websockets = ["websockets (>=10,<12)"] @@ -2033,7 +2033,7 @@ rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" [package.extras] -brotli = ["brotli", "brotlicffi"] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -2056,7 +2056,7 @@ exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} sortedcontainers = ">=2.1.0,<3.0.0" [package.extras] -all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2)"] +all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] codemods = ["libcst (>=0.3.16)"] crosshair = ["crosshair-tool (>=0.0.78)", "hypothesis-crosshair (>=0.0.18)"] @@ -2070,7 +2070,7 @@ pandas = ["pandas (>=1.1)"] pytest = ["pytest (>=4.6)"] pytz = ["pytz (>=2014.1)"] redis = ["redis (>=3.0.0)"] -zoneinfo = ["tzdata (>=2024.2)"] +zoneinfo = ["tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] [[package]] name = "idna" @@ -2103,12 +2103,12 @@ files = [ zipp = ">=3.20" [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] @@ -2202,7 +2202,7 @@ files = [ [package.extras] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -test = ["portend", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +test = ["portend", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] [[package]] name = "jaraco-functools" @@ -2220,7 +2220,7 @@ files = [ more-itertools = "*" [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] @@ -2241,7 +2241,7 @@ files = [ ] [package.extras] -test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] +test = ["async-timeout ; python_version < \"3.11\"", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] trio = ["trio"] [[package]] @@ -2330,7 +2330,7 @@ pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] completion = ["shtab (>=1.1.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] @@ -2969,8 +2969,8 @@ cryptography = ">=3.3" pynacl = ">=1.5" [package.extras] -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"] +all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] +gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] invoke = ["invoke (>=2.0)"] [[package]] @@ -3363,7 +3363,7 @@ typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" @@ -4213,13 +4213,13 @@ files = [ ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] -core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "six" @@ -4503,7 +4503,7 @@ virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2, [package.extras] docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] -testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] +testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3) ; python_version < \"3.4\"", "psutil (>=5.6.1) ; platform_python_implementation == \"cpython\"", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] [[package]] name = "twine" @@ -4578,7 +4578,7 @@ files = [ ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -4642,7 +4642,7 @@ platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "watchdog" @@ -4718,10 +4718,10 @@ typing-extensions = ">=4.0.1" websockets = ">=10.0.0,<14.0.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1)", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0)", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] +dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0) ; python_version < \"3.8\"", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] docs = ["sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)"] ipfs = ["ipfshttpclient (==0.8.0a2)"] -tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1)", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1)", "py-geth (>=3.14.0,<4)"] +tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "py-geth (>=3.14.0,<4)"] [[package]] name = "websocket-client" @@ -4942,11 +4942,11 @@ files = [ ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [[package]] From e0b67164c65d6f213e798e592131fe8b04f53433 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 7 Apr 2025 21:18:37 +0200 Subject: [PATCH 152/189] chore: remove import --- tests/test_scaffold.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_scaffold.py b/tests/test_scaffold.py index 6799cd70..3ec1a9b7 100644 --- a/tests/test_scaffold.py +++ b/tests/test_scaffold.py @@ -16,7 +16,6 @@ from auto_dev.constants import DEFAULT_ENCODING from auto_dev.dao.scaffolder import DAOScaffolder from auto_dev.handler.scaffolder import HandlerScaffolder, HandlerScaffoldBuilder -from auto_dev.protocols.scaffolder import read_protocol_spec from auto_dev.handler.openapi_models import ( Schema, OpenAPI, From 6009bcb350202eb75437285965200578939ebf85 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 11 Apr 2025 23:14:04 +0200 Subject: [PATCH 153/189] chore: https://rpc.ankr.com/eth -> https://eth.drpc.org --- tests/test_local_fork.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_local_fork.py b/tests/test_local_fork.py index 09d52483..ccdc2b80 100644 --- a/tests/test_local_fork.py +++ b/tests/test_local_fork.py @@ -9,7 +9,7 @@ from auto_dev.local_fork import DockerFork -TESTNET_RPC_URL = "https://rpc.ankr.com/eth" +TESTNET_RPC_URL = f"https://eth.drpc.org" DEFAULT_FORK_BLOCK_NUMBER = 18120809 From f79b85c4a6682b84e8c32ad22f63e10ae0be4aac Mon Sep 17 00:00:00 2001 From: zarathustra Date: Fri, 11 Apr 2025 23:14:52 +0200 Subject: [PATCH 154/189] feat: module_scoped_dummy_agent_tim --- tests/conftest.py | 22 ++++++++++++++++++++++ tests/test_protocol.py | 9 ++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fbde625a..2f3d98f2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ # pylint: disable=W0135 import os +import subprocess from pathlib import Path import pytest @@ -107,9 +108,30 @@ def dummy_agent_tim(test_packages_filesystem) -> Path: return Path.cwd() +@pytest.fixture(scope="module") +def module_scoped_dummy_agent_tim() -> Path: + """Fixture for module scoped dummy agent tim.""" + + with isolated_filesystem(copy_cwd=True) as directory: + command = ["autonomy", "packages", "init"] + result = subprocess.run(command, check=False, text=True, capture_output=True) + if not result.returncode == 0: + raise ValueError(f"Failed to init packages: {result.stderr}") + + agent = DEFAULT_PUBLIC_ID + command = ["adev", "create", f"{agent!s}", "-t", "eightballer/base", "--no-clean-up"] + result = subprocess.run(command, check=False, text=True, capture_output=True, cwd=directory) + if not result.returncode == 0: + raise ValueError(f"Failed to create agent: {result.stderr}") + + os.chdir(agent.name) + yield Path.cwd() + + @pytest.fixture def dummy_agent_default(test_packages_filesystem) -> Path: """Fixture for dummy agent default.""" + assert Path.cwd() == Path(test_packages_filesystem) agent = DEFAULT_PUBLIC_ID command = f"adev create {agent!s} -t eightballer/base --no-clean-up --no-publish" diff --git a/tests/test_protocol.py b/tests/test_protocol.py index e6e88372..be28efce 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -110,10 +110,10 @@ def test_parse_performative_annotation(annotation: str, expected: str): PROTOCOL_FILES["tickers.yaml"], ], ) -def test_scaffold_protocol(dummy_agent_tim, protocol_spec: Path): +def test_scaffold_protocol(module_scoped_dummy_agent_tim, protocol_spec: Path): """Test `adev scaffold protocol` command.""" - assert dummy_agent_tim, "Dummy agent not created." + assert module_scoped_dummy_agent_tim protocol = read_protocol_spec(protocol_spec) repo_root = protodantic.get_repo_root() @@ -124,9 +124,8 @@ def test_scaffold_protocol(dummy_agent_tim, protocol_spec: Path): msg = f"Protocol already exists in dummy_agent_tim: {protocol_outpath}" raise ValueError(msg) - result = subprocess.run( - ["adev", "-v", "scaffold", "protocol", str(protocol_spec)], check=False, text=True, capture_output=True - ) + command = ["adev", "-v", "scaffold", "protocol", str(protocol_spec)] + result = subprocess.run(command, check=False, text=True, capture_output=True) if result.returncode != 0: msg = f"Protocol scaffolding failed: {result.stderr}" raise ValueError(msg) From 860c67067b5319cd54a2f6e1cd30afea4a647598 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 11:22:48 +0200 Subject: [PATCH 155/189] test: add map_nested.proto --- .../data/protocols/protobuf/map_nested.proto | 24 +++++++++++++++++++ tests/test_protocol.py | 1 + 2 files changed, 25 insertions(+) create mode 100644 tests/data/protocols/protobuf/map_nested.proto diff --git a/tests/data/protocols/protobuf/map_nested.proto b/tests/data/protocols/protobuf/map_nested.proto new file mode 100644 index 00000000..5a69a39e --- /dev/null +++ b/tests/data/protocols/protobuf/map_nested.proto @@ -0,0 +1,24 @@ +// map_nested.proto + +syntax = "proto3"; + +message MapNested { + enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; + } + + message Message { + int32 int32_field = 1; + optional Status optional_status_field = 2; + optional Message optional_message_field = 3; + repeated Status repeated_status_field = 4; + repeated Message repeated_message_field = 5; + } + + map int32_map = 1; + map status_map = 2; + map message_map = 3; +} + diff --git a/tests/test_protocol.py b/tests/test_protocol.py index be28efce..5410da85 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -55,6 +55,7 @@ def _get_capitalization_station_protocols() -> dict[str, Path]: PROTO_FILES["map_message.proto"], PROTO_FILES["map_optional_primitive_values.proto"], PROTO_FILES["map_repeated_primitive_values.proto"], + PROTO_FILES["map_nested.proto"], ], ) def test_protodantic(proto_path: Path): From 0fd5c03b39ba2c1566f103e11b30bdb09f3343e5 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 14:37:47 +0200 Subject: [PATCH 156/189] fix: qualified_type via introduction of ResolvedType --- auto_dev/protocols/adapters.py | 16 +++++----- auto_dev/protocols/formatter.py | 54 ++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 0255ae15..4ef659a6 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -59,16 +59,16 @@ def __getattr__(self, name: str): return getattr(self.wrapped, name) @property - def enum_names(self) -> set[str]: + def enum_names(self) -> dict[str, ast.Enum]: """Enum names referenced in this ast.Message.""" - return {m.name for m in self.enums} + return {m.name: m for m in self.enums} @property - def message_names(self) -> set[str]: + def message_names(self) -> dict[str, MessageAdapter]: """Message names referenced in this ast.Message.""" - return {m.name for m in self.messages} + return {m.name: m for m in self.messages} @classmethod def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: @@ -126,16 +126,16 @@ def __getattr__(self, name: str): return getattr(self.wrapped, name) @property - def enum_names(self) -> set[str]: + def enum_names(self) -> dict[str, ast.Enum]: """Top-level Enum names in ast.File.""" - return {m.name for m in self.enums} + return {m.name: m for m in self.enums} @property - def message_names(self) -> set[str]: + def message_names(self) -> dict[str, MessageAdapter]: """Top-level Message names in ast.File.""" - return {m.name for m in self.messages} + return {m.name: m for m in self.messages} @classmethod def from_file(cls, file: File) -> FileAdapter: diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index c36dc351..312a5ff6 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -1,6 +1,7 @@ """Module with formatter for rendering pydantic model code from proto_schema_parser ast.File.""" import textwrap +from typing import NamedTuple from proto_schema_parser import ast from proto_schema_parser.ast import ( @@ -17,18 +18,40 @@ # ruff: noqa: E501, PLR0911 -def qualified_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> str: - """Fully qualified type for a type reference.""" +class ResolvedType(NamedTuple): + fully_qualified_name: str + ast_node: MessageAdapter | ast.Enum | None = None + + @property + def is_enum(self): + return isinstance(self.ast_node, ast.Enum) + + @property + def is_message(self): + return isinstance(self.ast_node, MessageAdapter) + + def __str__(self): + return self.fully_qualified_name - def find_definition(scope): - if scope is None or isinstance(scope, FileAdapter): - return None - if type_name in scope.enum_names or type_name in scope.message_names: - return f"{scope.fully_qualified_name}.{type_name}" - return find_definition(scope.parent) - qualified_name = find_definition(adapter) - return qualified_name if qualified_name is not None else PRIMITIVE_TYPE_MAP.get(type_name, type_name) +def qualified_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> ResolvedType: + """Fully qualified type for a type reference.""" + + if (scalar_type := PRIMITIVE_TYPE_MAP.get(type_name)) is not None: + return ResolvedType(scalar_type) + + node = adapter.enum_names.get(type_name) or adapter.message_names.get(type_name) + match adapter, node: + case FileAdapter(), None: + raise ValueError(f"Could not resolve {type_name}") + case FileAdapter(), _: + return ResolvedType(type_name, node) + case MessageAdapter(), None: + return qualified_type(adapter.parent, type_name) + case MessageAdapter(), _: + return ResolvedType(f"{adapter.fully_qualified_name}.{type_name}", node) + case _: + raise TypeError(f"Unexpected adapter type : {adapter}.") def render_field(field: Field, message: MessageAdapter) -> str: @@ -98,14 +121,10 @@ def encode_field(element, message): """Render pydantic model field encoding.""" instance_attr = f"{message.name.lower()}.{element.name}" - if ( - element.type in PRIMITIVE_TYPE_MAP - or element.type in message.enum_names - or element.type in message.file.enum_names - ): + qualified = qualified_type(message, element.type) + if element.type in PRIMITIVE_TYPE_MAP or qualified.is_enum: value = instance_attr else: # Message - qualified = qualified_type(message, element.type) if element.cardinality == FieldCardinality.REPEATED: return f"for item in {instance_attr}:\n" f" {qualified}.encode(proto_obj.{element.name}.add(), item)" if element.cardinality == FieldCardinality.OPTIONAL: @@ -171,7 +190,8 @@ def decode_field(field: ast.Field, message: MessageAdapter) -> str: """Render pydantic model field decoding.""" instance_field = f"proto_obj.{field.name}" - if field.type in PRIMITIVE_TYPE_MAP or field.type in message.enum_names or field.type in message.file.enum_names: + qualified = qualified_type(message, field.type) + if field.type in PRIMITIVE_TYPE_MAP or qualified.is_enum: value = instance_field else: qualified = qualified_type(message, field.type) From 850150d098048fbe8f396839faccc54b8c83e35c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 14:51:47 +0200 Subject: [PATCH 157/189] refactor: renaming and property -> cachedproperty --- auto_dev/protocols/adapters.py | 17 +++++------ auto_dev/protocols/formatter.py | 50 ++++++++++++++++----------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 4ef659a6..cdebeeeb 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -4,6 +4,7 @@ import re from dataclasses import field, dataclass +from functools import cached_property from proto_schema_parser.ast import ( Enum, @@ -58,14 +59,14 @@ def __getattr__(self, name: str): return getattr(self.wrapped, name) - @property - def enum_names(self) -> dict[str, ast.Enum]: + @cached_property + def enums_by_name(self) -> dict[str, ast.Enum]: """Enum names referenced in this ast.Message.""" return {m.name: m for m in self.enums} - @property - def message_names(self) -> dict[str, MessageAdapter]: + @cached_property + def messages_by_name(self) -> dict[str, MessageAdapter]: """Message names referenced in this ast.Message.""" return {m.name: m for m in self.messages} @@ -125,14 +126,14 @@ def __getattr__(self, name: str): return getattr(self.wrapped, name) - @property - def enum_names(self) -> dict[str, ast.Enum]: + @cached_property + def enums_by_name(self) -> dict[str, ast.Enum]: """Top-level Enum names in ast.File.""" return {m.name: m for m in self.enums} - @property - def message_names(self) -> dict[str, MessageAdapter]: + @cached_property + def messages_by_name(self) -> dict[str, MessageAdapter]: """Top-level Message names in ast.File.""" return {m.name: m for m in self.messages} diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 312a5ff6..8b319c5a 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -34,20 +34,20 @@ def __str__(self): return self.fully_qualified_name -def qualified_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> ResolvedType: +def resolve_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> ResolvedType: """Fully qualified type for a type reference.""" if (scalar_type := PRIMITIVE_TYPE_MAP.get(type_name)) is not None: return ResolvedType(scalar_type) - node = adapter.enum_names.get(type_name) or adapter.message_names.get(type_name) + node = adapter.enums_by_name.get(type_name) or adapter.messages_by_name.get(type_name) match adapter, node: case FileAdapter(), None: raise ValueError(f"Could not resolve {type_name}") case FileAdapter(), _: return ResolvedType(type_name, node) case MessageAdapter(), None: - return qualified_type(adapter.parent, type_name) + return resolve_type(adapter.parent, type_name) case MessageAdapter(), _: return ResolvedType(f"{adapter.fully_qualified_name}.{type_name}", node) case _: @@ -57,14 +57,14 @@ def qualified_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> Res def render_field(field: Field, message: MessageAdapter) -> str: """Render Field.""" - field_type = qualified_type(message, field.type) + resolved_type = resolve_type(message, field.type) match field.cardinality: case FieldCardinality.REQUIRED | None: - return f"{field_type}" + return f"{resolved_type}" case FieldCardinality.OPTIONAL: - return f"{field_type} | None" + return f"{resolved_type} | None" case FieldCardinality.REPEATED: - return f"list[{field_type}]" + return f"list[{resolved_type}]" case _: msg = f"Unexpected cardinality: {field.cardinality}" raise TypeError(msg) @@ -98,7 +98,7 @@ def render_attribute(element: MessageElement | MessageAdapter, message: MessageA return f"class {element.name}(IntEnum):\n" f' """{element.name}"""\n\n' f"{indented_members}\n" case ast.MapField: key_type = PRIMITIVE_TYPE_MAP.get(element.key_type, element.key_type) - value_type = qualified_type(message, element.value_type) + value_type = resolve_type(message, element.value_type) return f"{element.name}: dict[{key_type}, {value_type}]" case ast.Group | ast.Option | ast.ExtensionRange | ast.Reserved | ast.Extension: msg = f"{element}" @@ -121,20 +121,20 @@ def encode_field(element, message): """Render pydantic model field encoding.""" instance_attr = f"{message.name.lower()}.{element.name}" - qualified = qualified_type(message, element.type) - if element.type in PRIMITIVE_TYPE_MAP or qualified.is_enum: + resolved_type = resolve_type(message, element.type) + if element.type in PRIMITIVE_TYPE_MAP or resolved_type.is_enum: value = instance_attr else: # Message if element.cardinality == FieldCardinality.REPEATED: - return f"for item in {instance_attr}:\n" f" {qualified}.encode(proto_obj.{element.name}.add(), item)" + return f"for item in {instance_attr}:\n" f" {resolved_type}.encode(proto_obj.{element.name}.add(), item)" if element.cardinality == FieldCardinality.OPTIONAL: return ( f"if {instance_attr} is not None:\n" f" temp = proto_obj.{element.name}.__class__()\n" - f" {qualified}.encode(temp, {instance_attr})\n" + f" {resolved_type}.encode(temp, {instance_attr})\n" f" proto_obj.{element.name}.CopyFrom(temp)" ) - return f"{qualified}.encode(proto_obj.{element.name}, {instance_attr})" + return f"{resolved_type}.encode(proto_obj.{element.name}, {instance_attr})" match element.cardinality: case FieldCardinality.REPEATED: @@ -164,13 +164,13 @@ def encode_element(element) -> str: iter_items = f"for key, value in {message.name.lower()}.{element.name}.items():" if element.value_type in PRIMITIVE_TYPE_MAP: return f"{iter_items}\n proto_obj.{element.name}[key] = value" - if element.value_type in message.file.enum_names: + if element.value_type in message.file.enums_by_name: return f"{iter_items}\n proto_obj.{element.name}[key] = {element.value_type}(value)" - if element.value_type in message.enum_names: + if element.value_type in message.enums_by_name: return ( f"{iter_items}\n proto_obj.{element.name}[key] = {message.name}.{element.value_type}(value)" ) - return f"{iter_items}\n {qualified_type(message, element.value_type)}.encode(proto_obj.{element.name}[key], value)" + return f"{iter_items}\n {resolve_type(message, element.value_type)}.encode(proto_obj.{element.name}[key], value)" case _: msg = f"Unexpected message type: {element}" raise TypeError(msg) @@ -190,20 +190,20 @@ def decode_field(field: ast.Field, message: MessageAdapter) -> str: """Render pydantic model field decoding.""" instance_field = f"proto_obj.{field.name}" - qualified = qualified_type(message, field.type) - if field.type in PRIMITIVE_TYPE_MAP or qualified.is_enum: + resolved_type = resolve_type(message, field.type) + if field.type in PRIMITIVE_TYPE_MAP or resolved_type.is_enum: value = instance_field else: - qualified = qualified_type(message, field.type) + resolved_type = resolve_type(message, field.type) if field.cardinality == FieldCardinality.REPEATED: - return f"{field.name} = [{qualified}.decode(item) for item in {instance_field}]" + return f"{field.name} = [{resolved_type}.decode(item) for item in {instance_field}]" if field.cardinality == FieldCardinality.OPTIONAL: return ( - f"{field.name} = {qualified}.decode({instance_field}) " + f"{field.name} = {resolved_type}.decode({instance_field}) " f'if {instance_field} is not None and proto_obj.HasField("{field.name}") ' f"else None" ) - return f"{field.name} = {qualified}.decode({instance_field})" + return f"{field.name} = {resolved_type}.decode({instance_field})" match field.cardinality: case FieldCardinality.REPEATED: @@ -239,12 +239,12 @@ def decode_element(element) -> str: iter_items = f"{element.name} = {{}}\nfor key, value in proto_obj.{element.name}.items():" if element.value_type in PRIMITIVE_TYPE_MAP: return f"{element.name} = dict(proto_obj.{element.name})" - if element.value_type in message.file.enum_names: + if element.value_type in message.file.enums_by_name: return f"{iter_items}\n {element.name}[key] = {element.value_type}(value)" - if element.value_type in message.enum_names: + if element.value_type in message.enums_by_name: return f"{iter_items}\n {element.name}[key] = {message.name}.{element.value_type}(value)" return ( - f"{element.name} = {{ key: {qualified_type(message, element.value_type)}.decode(item) " + f"{element.name} = {{ key: {resolve_type(message, element.value_type)}.decode(item) " f"for key, item in proto_obj.{element.name}.items() }}" ) case _: From b15a79bac3665340276691627d452f94fefd6f1f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 15:03:49 +0200 Subject: [PATCH 158/189] tests: add map_of_map.proto --- tests/data/protocols/protobuf/map_of_map.proto | 5 +++++ tests/test_protocol.py | 1 + 2 files changed, 6 insertions(+) diff --git a/tests/data/protocols/protobuf/map_of_map.proto b/tests/data/protocols/protobuf/map_of_map.proto index fe28eb7c..9eb68f57 100644 --- a/tests/data/protocols/protobuf/map_of_map.proto +++ b/tests/data/protocols/protobuf/map_of_map.proto @@ -8,4 +8,9 @@ message MapOfMap { message InnerMap { map inner = 1; } + + message AnotherInnerMap { + map inner = 1; + map inner_map = 2; + } } diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 5410da85..9b5803d6 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -56,6 +56,7 @@ def _get_capitalization_station_protocols() -> dict[str, Path]: PROTO_FILES["map_optional_primitive_values.proto"], PROTO_FILES["map_repeated_primitive_values.proto"], PROTO_FILES["map_nested.proto"], + PROTO_FILES["map_of_map.proto"], ], ) def test_protodantic(proto_path: Path): From 96ef64dc7cd077f39d5685b8bbf0e975ca09b4da Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 20:58:02 +0200 Subject: [PATCH 159/189] refactor: explicit ast. reference in adapters.py --- auto_dev/protocols/adapters.py | 84 +++++++++++++--------------------- 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index cdebeeeb..5172a4c8 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -3,28 +3,10 @@ from __future__ import annotations import re -from dataclasses import field, dataclass from functools import cached_property +from dataclasses import field, dataclass -from proto_schema_parser.ast import ( - Enum, - File, - Field, - Group, - OneOf, - Import, - Option, - Comment, - Message, - Package, - Service, - MapField, - Reserved, - Extension, - FileElement, - ExtensionRange, - MessageElement, -) +from proto_schema_parser import ast def camel_to_snake(name: str) -> str: @@ -38,21 +20,21 @@ class MessageAdapter: file: FileAdapter | None = field(repr=False) parent: FileAdapter | MessageAdapter | None = field(repr=False) - wrapped: Message = field(repr=False) + wrapped: ast.Message = field(repr=False) fully_qualified_name: str - elements: list[MessageElement | MessageAdapter] = field(default_factory=list, repr=False) - - comments: list[Comment] = field(default_factory=list) - fields: list[Field] = field(default_factory=list) - groups: list[Group] = field(default_factory=list) - oneofs: list[OneOf] = field(default_factory=list) - options: list[Option] = field(default_factory=list) - extension_ranges: list[ExtensionRange] = field(default_factory=list) - reserved: list[Reserved] = field(default_factory=list) + elements: list[ast.MessageElement | MessageAdapter] = field(default_factory=list, repr=False) + + comments: list[ast.Comment] = field(default_factory=list) + fields: list[ast.Field] = field(default_factory=list) + groups: list[ast.Group] = field(default_factory=list) + oneofs: list[ast.OneOf] = field(default_factory=list) + options: list[ast.Option] = field(default_factory=list) + extension_ranges: list[ast.ExtensionRange] = field(default_factory=list) + reserved: list[ast.Reserved] = field(default_factory=list) messages: list[MessageAdapter] = field(default_factory=list) - enums: list[Enum] = field(default_factory=list) - extensions: list[Extension] = field(default_factory=list) - map_fields: list[MapField] = field(default_factory=list) + enums: list[ast.Enum] = field(default_factory=list) + extensions: list[ast.Extension] = field(default_factory=list) + map_fields: list[ast.MapField] = field(default_factory=list) def __getattr__(self, name: str): """Access wrapped ast.Message instance attributes.""" @@ -61,25 +43,25 @@ def __getattr__(self, name: str): @cached_property def enums_by_name(self) -> dict[str, ast.Enum]: - """Enum names referenced in this ast.Message.""" + """Enum names referenced in this ast.Enum.""" return {m.name: m for m in self.enums} @cached_property def messages_by_name(self) -> dict[str, MessageAdapter]: - """Message names referenced in this ast.Message.""" + """Message names referenced in this MessageAdapter.""" return {m.name: m for m in self.messages} @classmethod - def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: + def from_message(cls, message: ast.Message, parent_prefix="") -> MessageAdapter: """Convert a `Message` into `MessageAdapter`, handling recursion.""" elements = [] - grouped_elements = {camel_to_snake(t.__name__): [] for t in MessageElement.__args__} + grouped_elements = {camel_to_snake(t.__name__): [] for t in ast.MessageElement.__args__} for element in message.elements: key = camel_to_snake(element.__class__.__name__) - if isinstance(element, Message): + if isinstance(element, ast.Message): element = cls.from_message(element, parent_prefix=f"{parent_prefix}{message.name}.") elements.append(element) grouped_elements[key].append(element) @@ -108,18 +90,18 @@ def from_message(cls, message: Message, parent_prefix="") -> MessageAdapter: class FileAdapter: """FileAdapter for proto_schema_parser ast.File.""" - wrapped: File = field(repr=False) - file_elements: list[FileElement | MessageAdapter] = field(repr=False) + wrapped: ast.File = field(repr=False) + file_elements: list[ast.FileElement | MessageAdapter] = field(repr=False) syntax: str | None - imports: list[Import] = field(default_factory=list) - packages: list[Package] = field(default_factory=list) - options: list[Option] = field(default_factory=list) - messages: list[MessageAdapter] = field(default_factory=list) - enums: list[Enum] = field(default_factory=list) - extensions: list[Extension] = field(default_factory=list) - services: list[Service] = field(default_factory=list) - comments: list[Comment] = field(default_factory=list) + imports: list[ast.Import] = field(default_factory=list) + packages: list[ast.Package] = field(default_factory=list) + options: list[ast.Option] = field(default_factory=list) + messages: list[ast.MessageAdapter] = field(default_factory=list) + enums: list[ast.Enum] = field(default_factory=list) + extensions: list[ast.Extension] = field(default_factory=list) + services: list[ast.Service] = field(default_factory=list) + comments: list[ast.Comment] = field(default_factory=list) def __getattr__(self, name: str): """Access wrapped ast.File instance attributes.""" @@ -139,14 +121,14 @@ def messages_by_name(self) -> dict[str, MessageAdapter]: return {m.name: m for m in self.messages} @classmethod - def from_file(cls, file: File) -> FileAdapter: + def from_file(cls, file: ast.File) -> FileAdapter: """Convert a `File` into `FileAdapter`, handling messages recursively.""" file_elements = [] - grouped_elements = {camel_to_snake(t.__name__): [] for t in FileElement.__args__} + grouped_elements = {camel_to_snake(t.__name__): [] for t in ast.FileElement.__args__} for element in file.file_elements: key = camel_to_snake(element.__class__.__name__) - if isinstance(element, Message): + if isinstance(element, ast.Message): element = MessageAdapter.from_message(element) file_elements.append(element) grouped_elements[key].append(element) From 5e3f23f0ae04f1bca8384fd5603ad61961ea1d5e Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 21:02:27 +0200 Subject: [PATCH 160/189] chore: make fmt lint --- auto_dev/protocols/formatter.py | 16 +++++++++++----- tests/conftest.py | 10 ++++++---- tests/test_local_fork.py | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/auto_dev/protocols/formatter.py b/auto_dev/protocols/formatter.py index 8b319c5a..18c95909 100644 --- a/auto_dev/protocols/formatter.py +++ b/auto_dev/protocols/formatter.py @@ -15,19 +15,23 @@ from auto_dev.protocols.primitives import PRIMITIVE_TYPE_MAP -# ruff: noqa: E501, PLR0911 +# ruff: noqa: D105, E501, PLR0911 class ResolvedType(NamedTuple): + """Represents a fully resolved type reference with optional AST context.""" + fully_qualified_name: str ast_node: MessageAdapter | ast.Enum | None = None @property - def is_enum(self): + def is_enum(self) -> bool: + """Return True if the resolved type is an enum.""" return isinstance(self.ast_node, ast.Enum) @property - def is_message(self): + def is_message(self) -> bool: + """Return True if the resolved type is a message.""" return isinstance(self.ast_node, MessageAdapter) def __str__(self): @@ -43,7 +47,8 @@ def resolve_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> Resol node = adapter.enums_by_name.get(type_name) or adapter.messages_by_name.get(type_name) match adapter, node: case FileAdapter(), None: - raise ValueError(f"Could not resolve {type_name}") + msg = f"Could not resolve {type_name}" + raise ValueError(msg) case FileAdapter(), _: return ResolvedType(type_name, node) case MessageAdapter(), None: @@ -51,7 +56,8 @@ def resolve_type(adapter: FileAdapter | MessageAdapter, type_name: str) -> Resol case MessageAdapter(), _: return ResolvedType(f"{adapter.fully_qualified_name}.{type_name}", node) case _: - raise TypeError(f"Unexpected adapter type : {adapter}.") + msg = f"Unexpected adapter type : {adapter}." + raise TypeError(msg) def render_field(field: Field, message: MessageAdapter) -> str: diff --git a/tests/conftest.py b/tests/conftest.py index 2f3d98f2..088d3ea8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -115,14 +115,16 @@ def module_scoped_dummy_agent_tim() -> Path: with isolated_filesystem(copy_cwd=True) as directory: command = ["autonomy", "packages", "init"] result = subprocess.run(command, check=False, text=True, capture_output=True) - if not result.returncode == 0: - raise ValueError(f"Failed to init packages: {result.stderr}") + if result.returncode != 0: + msg = f"Failed to init packages: {result.stderr}" + raise ValueError(msg) agent = DEFAULT_PUBLIC_ID command = ["adev", "create", f"{agent!s}", "-t", "eightballer/base", "--no-clean-up"] result = subprocess.run(command, check=False, text=True, capture_output=True, cwd=directory) - if not result.returncode == 0: - raise ValueError(f"Failed to create agent: {result.stderr}") + if result.returncode != 0: + msg = f"Failed to create agent: {result.stderr}" + raise ValueError(msg) os.chdir(agent.name) yield Path.cwd() diff --git a/tests/test_local_fork.py b/tests/test_local_fork.py index ccdc2b80..97b4f013 100644 --- a/tests/test_local_fork.py +++ b/tests/test_local_fork.py @@ -9,7 +9,7 @@ from auto_dev.local_fork import DockerFork -TESTNET_RPC_URL = f"https://eth.drpc.org" +TESTNET_RPC_URL = "https://eth.drpc.org" DEFAULT_FORK_BLOCK_NUMBER = 18120809 From 76f48d5d85f060bf3942f85d9ab53eb211b6b5fe Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 21:06:15 +0200 Subject: [PATCH 161/189] tests: add map_scalar_keys.proto --- tests/test_protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 9b5803d6..be0d2f12 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -57,6 +57,7 @@ def _get_capitalization_station_protocols() -> dict[str, Path]: PROTO_FILES["map_repeated_primitive_values.proto"], PROTO_FILES["map_nested.proto"], PROTO_FILES["map_of_map.proto"], + PROTO_FILES["map_scalar_keys.proto"], ], ) def test_protodantic(proto_path: Path): From bff04ddc0c8a893454441666030cb5ac08ca4153 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 23:44:11 +0200 Subject: [PATCH 162/189] fix: point PYTHONPATH to tmp dir before `adev scaffold protocol` in test_scaffold_protocol --- tests/test_protocol.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index be0d2f12..6acb3632 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -127,15 +127,17 @@ def test_scaffold_protocol(module_scoped_dummy_agent_tim, protocol_spec: Path): msg = f"Protocol already exists in dummy_agent_tim: {protocol_outpath}" raise ValueError(msg) + # Point PYTHONPATH to the temporary project root so generated modules are discoverable + env = os.environ.copy() + env["PYTHONPATH"] = str(repo_root) + command = ["adev", "-v", "scaffold", "protocol", str(protocol_spec)] - result = subprocess.run(command, check=False, text=True, capture_output=True) + result = subprocess.run(command, env=env, check=False, text=True, capture_output=True) if result.returncode != 0: msg = f"Protocol scaffolding failed: {result.stderr}" raise ValueError(msg) - # Point PYTHONPATH to the temporary project root so generated modules are discoverable - env = os.environ.copy() - env["PYTHONPATH"] = str(repo_root) + assert protocol_outpath.exists() test_dir = protocol_outpath / "tests" command = ["pytest", str(test_dir), "-vv", "-s", "--tb=long", "-p", "no:warnings"] From fdda705d9bcf4b40003e99dd53c51241cac8383e Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 23:44:29 +0200 Subject: [PATCH 163/189] feat: protocols/performatives.jinja --- .../templates/protocols/performatives.jinja | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 auto_dev/data/templates/protocols/performatives.jinja diff --git a/auto_dev/data/templates/protocols/performatives.jinja b/auto_dev/data/templates/protocols/performatives.jinja new file mode 100644 index 00000000..b8e2868a --- /dev/null +++ b/auto_dev/data/templates/protocols/performatives.jinja @@ -0,0 +1,28 @@ +{{ header }} + +"""Models for the {{ snake_name }} protocol performatives to facilitate hypothesis strategy generation.""" + +from pydantic import BaseModel, conint, confloat + +from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies import ( + Int32, + Double, +) +from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( + {%- for custom_type in custom_types %} + {{ custom_type }}, + {%- endfor %} +) + +{# Define models for the performatives #} +{%- for performative, fields in performative_types.items() %} +class {{ snake_to_camel(performative) }}(BaseModel): + """Model for the `{{ performative|upper }}` initial speech act performative.""" + {%- for field_name, field_type in fields.items() %} + {{ field_name }}: {{ field_type }} + {%- endfor %} + +{% endfor %} + +for cls in BaseModel.__subclasses__(): + cls.model_rebuild() From 9dceeaca1a45a78425abd5daece6262aef791b3a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 23:45:41 +0200 Subject: [PATCH 164/189] refactor: import from tests/performatives.py in other tests --- .../templates/protocols/test_dialogues.jinja | 22 +++----------- .../templates/protocols/test_messages.jinja | 18 +++-------- auto_dev/protocols/scaffolder.py | 30 +++++++++++++++---- 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/auto_dev/data/templates/protocols/test_dialogues.jinja b/auto_dev/data/templates/protocols/test_dialogues.jinja index dba7fe1a..7dd8cc41 100644 --- a/auto_dev/data/templates/protocols/test_dialogues.jinja +++ b/auto_dev/data/templates/protocols/test_dialogues.jinja @@ -4,7 +4,7 @@ from unittest.mock import MagicMock -from pydantic import BaseModel, conint, confloat +from pydantic import BaseModel from hypothesis import given from hypothesis import strategies as st from aea.configurations.data_types import PublicId @@ -14,13 +14,9 @@ from packages.{{ author }}.protocols.{{ snake_name }}.dialogues import ( {{ camel_name }}Dialogues, ) from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message -from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies import ( - Int32, - Double, -) -from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( - {%- for custom_type in custom_types %} - {{ custom_type }}, +from packages.{{ author }}.protocols.{{ snake_name }}.tests.performatives import ( + {%- for performative in initial_performative_types %} + {{ snake_to_camel(performative) }}, {%- endfor %} ) @@ -53,16 +49,6 @@ def validate_dialogue(performative, model): assert dialogue is not None -{# Define strategies for each performative #} -{%- for initial_performative, fields in initial_performative_types.items() %} -class {{ snake_to_camel(initial_performative) }}(BaseModel): - """Model for the `{{ initial_performative|upper }}` initial speech act performative.""" - {%- for field_name, field_type in fields.items() %} - {{ field_name }}: {{ field_type }} - {%- endfor %} - -{% endfor %} - {%- for initial_performative in initial_performative_types %} @given(st.from_type({{ snake_to_camel(initial_performative) }})) diff --git a/auto_dev/data/templates/protocols/test_messages.jinja b/auto_dev/data/templates/protocols/test_messages.jinja index 9c06b006..182dc09b 100644 --- a/auto_dev/data/templates/protocols/test_messages.jinja +++ b/auto_dev/data/templates/protocols/test_messages.jinja @@ -3,7 +3,7 @@ """Test messages module for the {{ snake_name }} protocol.""" import pytest -from pydantic import BaseModel, conint, confloat +from pydantic import BaseModel from hypothesis import strategies as st from hypothesis import given @@ -18,9 +18,9 @@ from packages.{{ author }}.protocols.{{ snake_name }}.tests.primitive_strategies Int32, Double, ) -from packages.{{ author }}.protocols.{{ snake_name }}.custom_types import ( - {%- for custom_type in custom_types %} - {{ custom_type }}, +from packages.{{ author }}.protocols.{{ snake_name }}.tests.performatives import ( + {%- for performative in performative_types %} + {{ snake_to_camel(performative) }}, {%- endfor %} ) @@ -61,16 +61,6 @@ def perform_message_test(performative, model) -> None: expected_msg = msg assert expected_msg == actual_msg -{# Define models for the performatives #} -{%- for performative, fields in performative_types.items() %} -class {{ snake_to_camel(performative) }}(BaseModel): - """Model for the `{{ performative|upper }}` initial speech act performative.""" - {%- for field_name, field_type in fields.items() %} - {{ field_name }}: {{ field_type }} - {%- endfor %} - -{% endfor %} - {%- for performative in performative_types %} diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 4eff10a2..ee7d8dcc 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -252,6 +252,20 @@ def generate_tests_init(protocol: ProtocolSpecification) -> None: test_init_file.write_text(f'"""Test module for the {protocol.name}"""') +def generate_performative_messages(protocol: ProtocolSpecification, template) -> None: + """Generate performatives for hypothesis strategy generation.""" + output = template.render( + header="# Auto-generated by tool", + author=protocol.author, + snake_name=protocol.name, + performative_types=protocol.performative_types, + custom_types=protocol.custom_types, + snake_to_camel=snake_to_camel, + ) + test_dialogues = protocol.outpath / "tests" / f"performatives.py" + test_dialogues.write_text(output) + + def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: """Generate tests/test_dialogue.py.""" @@ -354,25 +368,29 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb # 7. generate __init__.py in tests folder generate_tests_init(protocol) - # 8. Test dialogues + # 8. generate performatives + template = env.get_template("protocols/performatives.jinja") + generate_performative_messages(protocol, template) + + # 9. Test dialogues template = env.get_template("protocols/test_dialogues.jinja") generate_test_dialogues(protocol, template) - # 9. Test messages + # 10. Test messages template = env.get_template("protocols/test_messages.jinja") generate_test_messages(protocol, template) - # 10. Update YAML + # 11. Update YAML dependencies = {"pydantic": {}, "hypothesis": {}} update_yaml(protocol, dependencies) - # 11. fmt + # 12. fmt run_adev_fmt(protocol) - # 12. lint + # 13. lint run_adev_lint(protocol) - # 13. Fingerprint + # 14. Fingerprint run_aea_fingerprint(protocol) # Hurray's are in order From e79c40ba737c68fafcfecda04c0ba5ce6dd5ae45 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 23:47:25 +0200 Subject: [PATCH 165/189] chore: remove empty protocols/tests.jinja --- auto_dev/data/templates/protocols/tests.jinja | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 auto_dev/data/templates/protocols/tests.jinja diff --git a/auto_dev/data/templates/protocols/tests.jinja b/auto_dev/data/templates/protocols/tests.jinja deleted file mode 100644 index e69de29b..00000000 From d5b9281f309185516b9b65c3a19c4181f98d2a44 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sat, 12 Apr 2025 23:49:06 +0200 Subject: [PATCH 166/189] chore: make fmt lint --- auto_dev/protocols/scaffolder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index ee7d8dcc..959e1d05 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -252,7 +252,7 @@ def generate_tests_init(protocol: ProtocolSpecification) -> None: test_init_file.write_text(f'"""Test module for the {protocol.name}"""') -def generate_performative_messages(protocol: ProtocolSpecification, template) -> None: +def generate_performative_messages(protocol: ProtocolSpecification, template) -> None: """Generate performatives for hypothesis strategy generation.""" output = template.render( header="# Auto-generated by tool", @@ -262,7 +262,7 @@ def generate_performative_messages(protocol: ProtocolSpecification, template) -> custom_types=protocol.custom_types, snake_to_camel=snake_to_camel, ) - test_dialogues = protocol.outpath / "tests" / f"performatives.py" + test_dialogues = protocol.outpath / "tests" / "performatives.py" test_dialogues.write_text(output) From 46efb90594b98e668c99428aad513fdb6123f3ad Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 13:00:16 +0200 Subject: [PATCH 167/189] refactor: unify template rendering with `TemplateContext` model and `ProtocolSpec.template_context` cached property --- auto_dev/protocols/scaffolder.py | 123 +++++++++++++++++-------------- 1 file changed, 69 insertions(+), 54 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 959e1d05..ac2156bd 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -4,10 +4,12 @@ import tempfile import subprocess from pathlib import Path +from functools import cached_property +from collections.abc import Callable import yaml from jinja2 import Environment, FileSystemLoader -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from proto_schema_parser import ast from proto_schema_parser.parser import Parser from aea.protocols.generator.base import ProtocolGenerator @@ -42,6 +44,37 @@ class InteractionModel(BaseModel): keep_terminal_state_dialogues: bool +class TemplateContext(BaseModel): + """TemplateContext.""" + + model_config = ConfigDict( + extra="forbid", + str_strip_whitespace=True, + ) + + header: str + description: str + protocol_definition: str + + author: str + name: str + snake_name: str + camel_name: str + + custom_types: list[str] + initial_performatives: list[str] + terminal_performatives: list[str] + valid_replies: dict[str, list[str]] + performative_types: dict[str, dict[str, str]] + initial_performative_types: dict[str, dict[str, str]] + + role: str + roles: list[dict[str, str]] + end_states: list[dict[str, str | int]] + keep_terminal_state_dialogues: bool + snake_to_camel: Callable[[str], str] + + class ProtocolSpecification(BaseModel): """ProtocolSpecification.""" @@ -102,6 +135,35 @@ def test_outpath(self) -> Path: """Outpath for tests/test_custom_types.py.""" return self.outpath / "tests" / "test_custom_types.py" + @cached_property + def template_context(self) -> TemplateContext: + """Get the template context for template rendering.""" + + roles = [{"name": r.upper(), "value": r} for r in self.interaction_model.roles] + end_states = [{"name": s.upper(), "value": idx} for idx, s in enumerate(self.interaction_model.end_states)] + protocol_definition = Path(self.path).read_text(encoding="utf-8") + + return TemplateContext( + header="# Auto-generated by tool", + description=self.metadata.description, + protocol_definition=protocol_definition, + author=self.metadata.author, + name=" ".join(map(str.capitalize, self.name.split("_"))), + snake_name=self.metadata.name, + camel_name=snake_to_camel(self.metadata.name), + custom_types=self.custom_types, + initial_performatives=self.interaction_model.initiation, + terminal_performatives=self.interaction_model.termination, + valid_replies=self.interaction_model.reply, + performative_types=self.performative_types, + initial_performative_types=self.initial_performative_types, + role=roles[0]["name"], + roles=roles, + end_states=end_states, + keep_terminal_state_dialogues=self.interaction_model.keep_terminal_state_dialogues, + snake_to_camel=snake_to_camel, + ) + def read_protocol_spec(filepath: str) -> ProtocolSpecification: """Read protocol specification.""" @@ -168,14 +230,9 @@ def run_push_local_protocol(protocol: ProtocolSpecification, agent_dir: Path) -> def generate_readme(protocol, template): """Generate protocol README.md file.""" - readme = protocol.outpath / "README.md" - protocol_definition = Path(protocol.path).read_text(encoding="utf-8") - content = template.render( - name=" ".join(map(str.capitalize, protocol.name.split("_"))), - description=protocol.metadata.description, - protocol_definition=protocol_definition, - ) + Path(protocol.path).read_text(encoding="utf-8") + content = template.render(**protocol.template_context.model_dump()) readme.write_text(content.strip()) @@ -214,7 +271,6 @@ def generate_custom_types(protocol: ProtocolSpecification): def rewrite_test_custom_types(protocol: ProtocolSpecification) -> None: """Rewrite custom_types.py import to accomodate aea message wrapping during .proto generation.""" - content = protocol.test_outpath.read_text() a = f"packages.{protocol.author}.protocols.{protocol.name} import {protocol.name}_pb2" b = f"packages.{protocol.author}.protocols.{protocol.name}.{protocol.name}_pb2 import {protocol.camel_name}Message as {protocol.name}_pb2 # noqa: N813" # noqa: E501 @@ -223,25 +279,7 @@ def rewrite_test_custom_types(protocol: ProtocolSpecification) -> None: def generate_dialogues(protocol: ProtocolSpecification, template): """Generate dialogues.py.""" - - valid_replies = protocol.interaction_model.reply - roles = [{"name": r.upper(), "value": r} for r in protocol.interaction_model.roles] - end_states = [{"name": s.upper(), "value": idx} for idx, s in enumerate(protocol.interaction_model.end_states)] - keep_terminal = protocol.interaction_model.keep_terminal_state_dialogues - - output = template.render( - header="# Auto-generated by tool", - author=protocol.author, - snake_name=protocol.name, - camel_name=protocol.camel_name, - initial_performatives=protocol.interaction_model.initiation, - terminal_performatives=protocol.interaction_model.termination, - valid_replies=valid_replies, - roles=roles, - role=roles[0]["name"], - end_states=end_states, - keep_terminal_state_dialogues=keep_terminal, - ) + output = template.render(**protocol.template_context.model_dump()) dialogues = protocol.outpath / "dialogues.py" dialogues.write_text(output) @@ -254,14 +292,7 @@ def generate_tests_init(protocol: ProtocolSpecification) -> None: def generate_performative_messages(protocol: ProtocolSpecification, template) -> None: """Generate performatives for hypothesis strategy generation.""" - output = template.render( - header="# Auto-generated by tool", - author=protocol.author, - snake_name=protocol.name, - performative_types=protocol.performative_types, - custom_types=protocol.custom_types, - snake_to_camel=snake_to_camel, - ) + output = template.render(**protocol.template_context.model_dump()) test_dialogues = protocol.outpath / "tests" / "performatives.py" test_dialogues.write_text(output) @@ -269,15 +300,7 @@ def generate_performative_messages(protocol: ProtocolSpecification, template) -> def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: """Generate tests/test_dialogue.py.""" - output = template.render( - header="# Auto-generated by tool", - author=protocol.author, - snake_name=protocol.name, - camel_name=protocol.camel_name, - initial_performative_types=protocol.initial_performative_types, - custom_types=protocol.custom_types, - snake_to_camel=snake_to_camel, - ) + output = template.render(**protocol.template_context.model_dump()) test_dialogues = protocol.outpath / "tests" / f"test_{protocol.name}_dialogues.py" test_dialogues.write_text(output) @@ -285,15 +308,7 @@ def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: def generate_test_messages(protocol: ProtocolSpecification, template) -> None: """Generate tests/test_messages.py.""" - output = template.render( - header="# Auto-generated by tool", - author=protocol.author, - snake_name=protocol.name, - camel_name=protocol.camel_name, - performative_types=protocol.performative_types, - custom_types=protocol.custom_types, - snake_to_camel=snake_to_camel, - ) + output = template.render(**protocol.template_context.model_dump()) test_messages = protocol.outpath / "tests" / f"test_{protocol.name}_messages.py" test_messages.write_text(output) From 830b52d1ef335f29274ca75e81fef357c5b696c5 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 13:12:23 +0200 Subject: [PATCH 168/189] refactor: remove initial_performative_types --- auto_dev/data/templates/protocols/test_dialogues.jinja | 4 ++-- auto_dev/protocols/scaffolder.py | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/auto_dev/data/templates/protocols/test_dialogues.jinja b/auto_dev/data/templates/protocols/test_dialogues.jinja index 7dd8cc41..9ef02dc6 100644 --- a/auto_dev/data/templates/protocols/test_dialogues.jinja +++ b/auto_dev/data/templates/protocols/test_dialogues.jinja @@ -15,7 +15,7 @@ from packages.{{ author }}.protocols.{{ snake_name }}.dialogues import ( ) from packages.{{ author }}.protocols.{{ snake_name }}.message import {{ camel_name }}Message from packages.{{ author }}.protocols.{{ snake_name }}.tests.performatives import ( - {%- for performative in initial_performative_types %} + {%- for performative in initial_performatives %} {{ snake_to_camel(performative) }}, {%- endfor %} ) @@ -50,7 +50,7 @@ def validate_dialogue(performative, model): assert dialogue is not None -{%- for initial_performative in initial_performative_types %} +{%- for initial_performative in initial_performatives %} @given(st.from_type({{ snake_to_camel(initial_performative) }})) def test_{{ initial_performative }}_dialogues(model): """Test for the '{{ initial_performative|upper }}' protocol.""" diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index ac2156bd..31a5e728 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -66,7 +66,6 @@ class TemplateContext(BaseModel): terminal_performatives: list[str] valid_replies: dict[str, list[str]] performative_types: dict[str, dict[str, str]] - initial_performative_types: dict[str, dict[str, str]] role: str roles: list[dict[str, str]] @@ -115,11 +114,6 @@ def performative_types(self) -> dict[str, dict[str, str]]: performative_types[performative] = field_types return performative_types - @property - def initial_performative_types(self) -> dict[str, dict[str, str]]: - """Python type annotation for initial performatives.""" - return {k: v for k, v in self.performative_types.items() if k in self.interaction_model.initiation} - @property def outpath(self) -> Path: """Protocol expected outpath after `aea create` and `aea publish --local`.""" @@ -156,7 +150,6 @@ def template_context(self) -> TemplateContext: terminal_performatives=self.interaction_model.termination, valid_replies=self.interaction_model.reply, performative_types=self.performative_types, - initial_performative_types=self.initial_performative_types, role=roles[0]["name"], roles=roles, end_states=end_states, From e8721877a9f3f48e1b312c7f6af331af591395a6 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 13:28:37 +0200 Subject: [PATCH 169/189] refactor: moved hardcoded template paths into JinjaTemplates model --- auto_dev/protocols/scaffolder.py | 36 ++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index 31a5e728..c3c1282a 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -8,7 +8,7 @@ from collections.abc import Callable import yaml -from jinja2 import Environment, FileSystemLoader +from jinja2 import Template, Environment, FileSystemLoader from pydantic import BaseModel, ConfigDict from proto_schema_parser import ast from proto_schema_parser.parser import Parser @@ -20,6 +20,23 @@ from auto_dev.protocols import protodantic, performatives +class JinjaTemplates(BaseModel, arbitrary_types_allowed=True): + """JinjaTemplates.""" + + README: Template + dialogues: Template + performatives: Template + primitive_strategies: Template + test_dialogues: Template + test_messages: Template + + @classmethod + def load(cls): + """Load from jinja2.Environment.""" + env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa + return cls(**{field: env.get_template(f"protocols/{field}.jinja") for field in cls.model_fields}) + + class Metadata(BaseModel): """Metadata.""" @@ -346,6 +363,8 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb """ + jinja_templates = JinjaTemplates.load() + agent_dir = Path.cwd() env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa @@ -360,8 +379,7 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb run_push_local_protocol(protocol, agent_dir) # 3. create README.md - template = env.get_template("protocols/README.jinja") - generate_readme(protocol, template) + generate_readme(protocol, jinja_templates.README) # 4. Generate custom_types.py and test_custom_types.py generate_custom_types(protocol) @@ -370,23 +388,19 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb rewrite_test_custom_types(protocol) # 6. Dialogues - template = env.get_template("protocols/dialogues.jinja") - generate_dialogues(protocol, template) + generate_dialogues(protocol, jinja_templates.dialogues) # 7. generate __init__.py in tests folder generate_tests_init(protocol) # 8. generate performatives - template = env.get_template("protocols/performatives.jinja") - generate_performative_messages(protocol, template) + generate_performative_messages(protocol, jinja_templates.performatives) # 9. Test dialogues - template = env.get_template("protocols/test_dialogues.jinja") - generate_test_dialogues(protocol, template) + generate_test_dialogues(protocol, jinja_templates.test_dialogues) # 10. Test messages - template = env.get_template("protocols/test_messages.jinja") - generate_test_messages(protocol, template) + generate_test_messages(protocol, jinja_templates.test_messages) # 11. Update YAML dependencies = {"pydantic": {}, "hypothesis": {}} From b42b11a5a80d9fcb1423871bef75c210e1fa8f30 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 18:23:22 +0200 Subject: [PATCH 170/189] refactor: protodantic.py --- auto_dev/protocols/protodantic.py | 92 +++++++++++++++++++++---------- auto_dev/protocols/scaffolder.py | 3 - 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index a23835e4..92a668aa 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -6,7 +6,8 @@ from types import ModuleType from pathlib import Path -from jinja2 import Environment, FileSystemLoader +from jinja2 import Template, Environment, FileSystemLoader +from pydantic import BaseModel from proto_schema_parser.parser import Parser from auto_dev.constants import JINJA_TEMPLATE_FOLDER @@ -14,6 +15,20 @@ from auto_dev.protocols.adapters import FileAdapter +class JinjaTemplates(BaseModel, arbitrary_types_allowed=True): + """JinjaTemplates.""" + + primitive_strategies: Template + protodantic: Template + hypothesis: Template + + @classmethod + def load(cls): + """Load from jinja2.Environment.""" + env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa + return cls(**{field: env.get_template(f"protocols/{field}.jinja") for field in cls.model_fields}) + + def get_repo_root() -> Path: """Get repository root directory path.""" @@ -48,29 +63,15 @@ def locally_defined(obj): return list(filter(locally_defined, vars(module).values())) -def create( # noqa: PLR0914 - proto_inpath: Path, - code_outpath: Path, - test_outpath: Path, -) -> None: - """Main function to create pydantic models from a .proto file.""" - - repo_root = get_repo_root() - env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa - - content = proto_inpath.read_text() - +def copy_primitives(repo_root: Path, code_outpath: Path) -> Path: + """Copy primitives.""" primitives_py = repo_root / "auto_dev" / "protocols" / "primitives.py" - strategies_template = env.get_template("protocols/primitive_strategies.jinja") - protodantic_template = env.get_template("protocols/protodantic.jinja") - hypothesis_template = env.get_template("protocols/hypothesis.jinja") - primitives_outpath = code_outpath.parent / primitives_py.name primitives_outpath.write_text(primitives_py.read_text()) + return primitives_outpath - models_import_path = _compute_import_path(code_outpath, repo_root) - primitives_import_path = _compute_import_path(primitives_outpath, repo_root) +def _run_protoc(proto_inpath: Path, code_outpath: Path) -> Path: subprocess.run( [ "protoc", @@ -81,32 +82,63 @@ def create( # noqa: PLR0914 cwd=proto_inpath.parent, check=True, ) + return code_outpath.parent / f"{proto_inpath.stem}_pb2.py" + +def _extract_primitives(primitives_module) -> tuple[list[type], list[type]]: custom_primitives = _get_locally_defined_classes(primitives_module) primitives = [cls for cls in custom_primitives if not inspect.isabstract(cls)] float_primitives = [p for p in primitives if issubclass(p, float)] integer_primitives = [p for p in primitives if issubclass(p, int)] + return float_primitives, integer_primitives - file = FileAdapter.from_file(Parser().parse(content)) - generated_code = protodantic_template.render( - file=file, - formatter=formatter, - float_primitives=float_primitives, - integer_primitives=integer_primitives, - primitives_import_path=primitives_import_path, - ) - code_outpath.write_text(generated_code) +def create( # noqa: PLR0914 + proto_inpath: Path, + code_outpath: Path, + test_outpath: Path, +) -> None: + """Main function to create pydantic models from a .proto file.""" + + repo_root = get_repo_root() + jinja_templates = JinjaTemplates.load() + + # Copy primitives file + primitives_outpath = copy_primitives(repo_root, code_outpath) + + # Run protoc to generate pb2 file + pb2_path = _run_protoc(proto_inpath, code_outpath) + + # import the custom primitive types + float_primitives, integer_primitives = _extract_primitives(primitives_module) + # load the .proto file AST tree + file = FileAdapter.from_file(Parser().parse(proto_inpath.read_text())) + + # remove runtime imports from the pb2 file pb2_path = code_outpath.parent / f"{proto_inpath.stem}_pb2.py" pb2_content = pb2_path.read_text() pb2_content = _remove_runtime_version_code(pb2_content) pb2_path.write_text(pb2_content) + # compute import paths + models_import_path = _compute_import_path(code_outpath, repo_root) message_import_path = ".".join(models_import_path.split(".")[:-1]) or "." messages_pb2 = pb2_path.with_suffix("").name - generated_strategies = strategies_template.render( + primitives_import_path = _compute_import_path(primitives_outpath, repo_root) + + # render jinja templates + generated_code = jinja_templates.protodantic.render( + file=file, + formatter=formatter, + float_primitives=float_primitives, + integer_primitives=integer_primitives, + primitives_import_path=primitives_import_path, + ) + code_outpath.write_text(generated_code) + + generated_strategies = jinja_templates.primitive_strategies.render( float_primitives=float_primitives, integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, @@ -115,7 +147,7 @@ def create( # noqa: PLR0914 strategies_outpath.write_text(generated_strategies) strategies_import_path = _compute_import_path(strategies_outpath, repo_root) - generated_tests = hypothesis_template.render( + generated_tests = jinja_templates.hypothesis.render( file=file, float_primitives=float_primitives, integer_primitives=integer_primitives, diff --git a/auto_dev/protocols/scaffolder.py b/auto_dev/protocols/scaffolder.py index c3c1282a..74384419 100644 --- a/auto_dev/protocols/scaffolder.py +++ b/auto_dev/protocols/scaffolder.py @@ -309,7 +309,6 @@ def generate_performative_messages(protocol: ProtocolSpecification, template) -> def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: """Generate tests/test_dialogue.py.""" - output = template.render(**protocol.template_context.model_dump()) test_dialogues = protocol.outpath / "tests" / f"test_{protocol.name}_dialogues.py" test_dialogues.write_text(output) @@ -317,7 +316,6 @@ def generate_test_dialogues(protocol: ProtocolSpecification, template) -> None: def generate_test_messages(protocol: ProtocolSpecification, template) -> None: """Generate tests/test_messages.py.""" - output = template.render(**protocol.template_context.model_dump()) test_messages = protocol.outpath / "tests" / f"test_{protocol.name}_messages.py" test_messages.write_text(output) @@ -366,7 +364,6 @@ def protocol_scaffolder(protocol_specification_path: str, language, logger, verb jinja_templates = JinjaTemplates.load() agent_dir = Path.cwd() - env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa # 1. Read spec data protocol = read_protocol_spec(protocol_specification_path) From 2f0ff1b3972f23774f144386d140925f68e85b2d Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 22:26:07 +0200 Subject: [PATCH 171/189] refactor: TemplateContext in protodantic.py --- auto_dev/protocols/adapters.py | 2 +- auto_dev/protocols/protodantic.py | 61 ++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/auto_dev/protocols/adapters.py b/auto_dev/protocols/adapters.py index 5172a4c8..0de0e364 100644 --- a/auto_dev/protocols/adapters.py +++ b/auto_dev/protocols/adapters.py @@ -97,7 +97,7 @@ class FileAdapter: imports: list[ast.Import] = field(default_factory=list) packages: list[ast.Package] = field(default_factory=list) options: list[ast.Option] = field(default_factory=list) - messages: list[ast.MessageAdapter] = field(default_factory=list) + messages: list[MessageAdapter] = field(default_factory=list) enums: list[ast.Enum] = field(default_factory=list) extensions: list[ast.Extension] = field(default_factory=list) services: list[ast.Service] = field(default_factory=list) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index 92a668aa..e9b52c30 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -4,10 +4,11 @@ import inspect import subprocess # nosec: B404 from types import ModuleType +from typing import Any from pathlib import Path from jinja2 import Template, Environment, FileSystemLoader -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from proto_schema_parser.parser import Parser from auto_dev.constants import JINJA_TEMPLATE_FOLDER @@ -26,9 +27,33 @@ class JinjaTemplates(BaseModel, arbitrary_types_allowed=True): def load(cls): """Load from jinja2.Environment.""" env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa + env.globals["formatter"] = formatter return cls(**{field: env.get_template(f"protocols/{field}.jinja") for field in cls.model_fields}) +class TemplateContext(BaseModel): + """TemplateContext.""" + + model_config = ConfigDict( + extra="forbid", + str_strip_whitespace=True, + ) + + file: Any + float_primitives: list[type] + integer_primitives: list[type] + primitives_import_path: str + strategies_import_path: str + models_import_path: str + message_import_path: str + messages_pb2: str + + def shallow_dump(self) -> dict[str, Any]: + """Shallow dump pydantic model.""" + + return {name: getattr(self, name) for name in self.model_fields} + + def get_repo_root() -> Path: """Get repository root directory path.""" @@ -105,6 +130,7 @@ def create( # noqa: PLR0914 # Copy primitives file primitives_outpath = copy_primitives(repo_root, code_outpath) + primitives_import_path = _compute_import_path(primitives_outpath, repo_root) # Run protoc to generate pb2 file pb2_path = _run_protoc(proto_inpath, code_outpath) @@ -122,38 +148,31 @@ def create( # noqa: PLR0914 pb2_path.write_text(pb2_content) # compute import paths + strategies_outpath = test_outpath.parent / "primitive_strategies.py" + strategies_import_path = _compute_import_path(strategies_outpath, repo_root) + primitives_import_path = _compute_import_path(primitives_outpath, repo_root) models_import_path = _compute_import_path(code_outpath, repo_root) message_import_path = ".".join(models_import_path.split(".")[:-1]) or "." messages_pb2 = pb2_path.with_suffix("").name - primitives_import_path = _compute_import_path(primitives_outpath, repo_root) - # render jinja templates - generated_code = jinja_templates.protodantic.render( + template_context = TemplateContext( file=file, - formatter=formatter, - float_primitives=float_primitives, - integer_primitives=integer_primitives, - primitives_import_path=primitives_import_path, - ) - code_outpath.write_text(generated_code) - - generated_strategies = jinja_templates.primitive_strategies.render( float_primitives=float_primitives, integer_primitives=integer_primitives, primitives_import_path=primitives_import_path, - ) - strategies_outpath = test_outpath.parent / "primitive_strategies.py" - strategies_outpath.write_text(generated_strategies) - - strategies_import_path = _compute_import_path(strategies_outpath, repo_root) - generated_tests = jinja_templates.hypothesis.render( - file=file, - float_primitives=float_primitives, - integer_primitives=integer_primitives, strategies_import_path=strategies_import_path, models_import_path=models_import_path, message_import_path=message_import_path, messages_pb2=messages_pb2, ) + jinja_kwargs = template_context.shallow_dump() + + generated_code = jinja_templates.protodantic.render(**jinja_kwargs) + code_outpath.write_text(generated_code) + + generated_strategies = jinja_templates.primitive_strategies.render(**jinja_kwargs) + strategies_outpath.write_text(generated_strategies) + + generated_tests = jinja_templates.hypothesis.render(**jinja_kwargs) test_outpath.write_text(generated_tests) From 2965899c9cff57996d199d8ac0b5fa40b9fc1785 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 22:45:16 +0200 Subject: [PATCH 172/189] refactor: _prepare_pb2 in protodantic.py --- auto_dev/protocols/protodantic.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index e9b52c30..f6b125a5 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -118,6 +118,14 @@ def _extract_primitives(primitives_module) -> tuple[list[type], list[type]]: return float_primitives, integer_primitives +def _prepare_pb2(proto_inpath: Path, code_outpath: Path) -> Path: + pb2_path = _run_protoc(proto_inpath, code_outpath) + pb2_content = pb2_path.read_text() + pb2_content = _remove_runtime_version_code(pb2_content) + pb2_path.write_text(pb2_content) + return pb2_path + + def create( # noqa: PLR0914 proto_inpath: Path, code_outpath: Path, @@ -132,20 +140,14 @@ def create( # noqa: PLR0914 primitives_outpath = copy_primitives(repo_root, code_outpath) primitives_import_path = _compute_import_path(primitives_outpath, repo_root) - # Run protoc to generate pb2 file - pb2_path = _run_protoc(proto_inpath, code_outpath) - # import the custom primitive types float_primitives, integer_primitives = _extract_primitives(primitives_module) # load the .proto file AST tree file = FileAdapter.from_file(Parser().parse(proto_inpath.read_text())) - # remove runtime imports from the pb2 file - pb2_path = code_outpath.parent / f"{proto_inpath.stem}_pb2.py" - pb2_content = pb2_path.read_text() - pb2_content = _remove_runtime_version_code(pb2_content) - pb2_path.write_text(pb2_content) + # Run protoc to generate pb2 file, then remove runtime imports + pb2_path = _prepare_pb2(proto_inpath, code_outpath) # compute import paths strategies_outpath = test_outpath.parent / "primitive_strategies.py" From 87e70048548aece56752432f2e49f18e8a20dbec Mon Sep 17 00:00:00 2001 From: zarathustra Date: Sun, 13 Apr 2025 23:07:43 +0200 Subject: [PATCH 173/189] refactor: ImportPaths in protodantic.py --- .../data/templates/protocols/hypothesis.jinja | 6 +- .../protocols/primitive_strategies.jinja | 2 +- .../templates/protocols/protodantic.jinja | 2 +- auto_dev/protocols/protodantic.py | 67 +++++++++++++------ 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/auto_dev/data/templates/protocols/hypothesis.jinja b/auto_dev/data/templates/protocols/hypothesis.jinja index 112a8ac2..5a6b39cd 100644 --- a/auto_dev/data/templates/protocols/hypothesis.jinja +++ b/auto_dev/data/templates/protocols/hypothesis.jinja @@ -3,9 +3,9 @@ from hypothesis import given from hypothesis import strategies as st -from {{ message_import_path }} import {{ messages_pb2 }} +from {{ import_paths.message }} import {{ messages_pb2 }} -from {{ strategies_import_path }} import ( +from {{ import_paths.strategies }} import ( {%- for primitive in float_primitives %} {{ primitive.__name__ }}, {%- endfor %} @@ -13,7 +13,7 @@ from {{ strategies_import_path }} import ( {{ primitive.__name__ }}, {%- endfor %} ) -from {{ models_import_path }} import ( +from {{ import_paths.models }} import ( {%- for enum in file.enums %} {{ enum.name }}, {%- endfor %} diff --git a/auto_dev/data/templates/protocols/primitive_strategies.jinja b/auto_dev/data/templates/protocols/primitive_strategies.jinja index f5e5bcf0..c9e919c8 100644 --- a/auto_dev/data/templates/protocols/primitive_strategies.jinja +++ b/auto_dev/data/templates/protocols/primitive_strategies.jinja @@ -3,7 +3,7 @@ from hypothesis import given from hypothesis import strategies as st -from {{ primitives_import_path }} import ( +from {{ import_paths.primitives }} import ( {%- for primitive in float_primitives %} {{ primitive.__name__ }}, {%- endfor %} diff --git a/auto_dev/data/templates/protocols/protodantic.jinja b/auto_dev/data/templates/protocols/protodantic.jinja index 3551fe44..72167639 100644 --- a/auto_dev/data/templates/protocols/protodantic.jinja +++ b/auto_dev/data/templates/protocols/protodantic.jinja @@ -6,7 +6,7 @@ from enum import IntEnum from pydantic import BaseModel -from {{ primitives_import_path }} import ( +from {{ import_paths.primitives }} import ( {%- for primitive in float_primitives %} {{ primitive.__name__ }}, {%- endfor %} diff --git a/auto_dev/protocols/protodantic.py b/auto_dev/protocols/protodantic.py index f6b125a5..90b38eba 100644 --- a/auto_dev/protocols/protodantic.py +++ b/auto_dev/protocols/protodantic.py @@ -1,10 +1,11 @@ """Module for generating pydantic models and associated hypothesis tests.""" +from __future__ import annotations + import re import inspect import subprocess # nosec: B404 -from types import ModuleType -from typing import Any +from typing import TYPE_CHECKING, Any from pathlib import Path from jinja2 import Template, Environment, FileSystemLoader @@ -16,6 +17,10 @@ from auto_dev.protocols.adapters import FileAdapter +if TYPE_CHECKING: + from types import ModuleType + + class JinjaTemplates(BaseModel, arbitrary_types_allowed=True): """JinjaTemplates.""" @@ -31,6 +36,34 @@ def load(cls): return cls(**{field: env.get_template(f"protocols/{field}.jinja") for field in cls.model_fields}) +class ImportPaths(BaseModel): + """ImportPaths.""" + + strategies: str + primitives: str + models: str + message: str + + @classmethod + def from_paths( + cls, + *, + repo_root: Path, + strategies_outpath: Path, + primitives_outpath: Path, + code_outpath: Path, + ) -> ImportPaths: + """Determine necessary module paths from outpaths.""" + + models_import_path = _compute_import_path(code_outpath, repo_root) + return cls( + strategies=_compute_import_path(strategies_outpath, repo_root), + primitives=_compute_import_path(primitives_outpath, repo_root), + models=models_import_path, + message=".".join(models_import_path.split(".")[:-1]) or ".", + ) + + class TemplateContext(BaseModel): """TemplateContext.""" @@ -42,10 +75,7 @@ class TemplateContext(BaseModel): file: Any float_primitives: list[type] integer_primitives: list[type] - primitives_import_path: str - strategies_import_path: str - models_import_path: str - message_import_path: str + import_paths: ImportPaths messages_pb2: str def shallow_dump(self) -> dict[str, Any]: @@ -126,7 +156,7 @@ def _prepare_pb2(proto_inpath: Path, code_outpath: Path) -> Path: return pb2_path -def create( # noqa: PLR0914 +def create( proto_inpath: Path, code_outpath: Path, test_outpath: Path, @@ -138,7 +168,6 @@ def create( # noqa: PLR0914 # Copy primitives file primitives_outpath = copy_primitives(repo_root, code_outpath) - primitives_import_path = _compute_import_path(primitives_outpath, repo_root) # import the custom primitive types float_primitives, integer_primitives = _extract_primitives(primitives_module) @@ -151,23 +180,23 @@ def create( # noqa: PLR0914 # compute import paths strategies_outpath = test_outpath.parent / "primitive_strategies.py" - strategies_import_path = _compute_import_path(strategies_outpath, repo_root) - primitives_import_path = _compute_import_path(primitives_outpath, repo_root) - models_import_path = _compute_import_path(code_outpath, repo_root) - message_import_path = ".".join(models_import_path.split(".")[:-1]) or "." - messages_pb2 = pb2_path.with_suffix("").name - # render jinja templates + # generate template context + import_paths = ImportPaths.from_paths( + repo_root=repo_root, + strategies_outpath=strategies_outpath, + primitives_outpath=primitives_outpath, + code_outpath=code_outpath, + ) template_context = TemplateContext( file=file, float_primitives=float_primitives, integer_primitives=integer_primitives, - primitives_import_path=primitives_import_path, - strategies_import_path=strategies_import_path, - models_import_path=models_import_path, - message_import_path=message_import_path, - messages_pb2=messages_pb2, + import_paths=import_paths, + messages_pb2=pb2_path.with_suffix("").name, ) + + # render jinja templates jinja_kwargs = template_context.shallow_dump() generated_code = jinja_templates.protodantic.render(**jinja_kwargs) From 0119cfc2e8fce5d4c89561203618bab75b6ec1f6 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 15:11:32 +0200 Subject: [PATCH 174/189] feat: add pytest-xdist to pyproject.toml --- poetry.lock | 38 +++++++++++++++++++++++++++++++++++++- pyproject.toml | 10 +++++----- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 35f73e94..ceee067f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1757,6 +1757,21 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "execnet" +version = "2.1.1" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, + {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + [[package]] name = "filelock" version = "3.18.0" @@ -4125,6 +4140,27 @@ files = [ packaging = ">=17.1" pytest = ">=5.3" +[[package]] +name = "pytest-xdist" +version = "3.6.1" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, + {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, +] + +[package.dependencies] +execnet = ">=2.1" +pytest = ">=7.0.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + [[package]] name = "pytest-xprocess" version = "0.18.1" @@ -5538,4 +5574,4 @@ all = ["isort", "open-aea", "open-aea-ledger-cosmos", "open-aea-ledger-ethereum" [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.13" -content-hash = "93e7bfb47436b45e1b894cab192eacf821f9b48090f62075e110b52aeef34151" +content-hash = "d376a08f09ee17f8184866ffdb91d42bc9cf1cae4f2fe5ccd690a646464f7d80" diff --git a/pyproject.toml b/pyproject.toml index 41a5e543..eeefb0f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ typing_extensions = ">=3.10.0.2" protobuf = ">=3.19.1,<4.25.0" hypothesis = "==6.122.3" toml = "==0.10.2" -tomte = {version = "==0.2.17", extras = ["cli", "tests", "ledgers", "black"]} +tomte = { version = "==0.2.17", extras = ["cli", "tests", "ledgers", "black"] } py-multibase = "==1.0.3" py-multicodec = "==0.2.1" @@ -64,13 +64,14 @@ rich-click = "^1.8.2" tbump = "^6.11.0" requests = ">=2.28.1,<3" ruff = "^0.5.7" -pydoclint = {extras = ["all"], version = "^0.6.0"} +pydoclint = { extras = ["all"], version = "^0.6.0" } pydantic = "^2.8.2" isort = "^5.13.2" openapi-spec-validator = "0.2.8" disutils = "^1.4.32.post2" setuptools = "^75.8.0" proto-schema-parser = "^1.5.0" +pytest-xdist = "^3.6.1" [tool.poetry.group.dev.dependencies] @@ -80,7 +81,7 @@ mkdocs-include-markdown-plugin = "^7.0.0" mkdocs-mermaid2-plugin = "^1.1.1" mkdocs-material = "^9.5.47" mkdocs-material-extensions = "^1.3.1" -mkdocstrings = {extras = ["python"], version = ">=0.25.2,<0.28.0"} +mkdocstrings = { extras = ["python"], version = ">=0.25.2,<0.28.0" } twine = "^5.1.1" mkdocs-autorefs = "^1.0.1" @@ -110,8 +111,7 @@ filterwarnings = [ "ignore:There is no current event loop:DeprecationWarning", "ignore:DeprecationWarning*.py:DeprecationWarning", "ignore:CoverageWarning*.py:", - "ignore::DeprecationWarning" + "ignore::DeprecationWarning", ] addopts = "--cov=auto_dev --cov-report html" - From 1bc3635c20c7e6823b29d202fab0eafccd7574d3 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 15:13:14 +0200 Subject: [PATCH 175/189] feat: add tool.coverage settings to pyproject.toml to include branch and isolated filesystem paths --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index eeefb0f8..91d2fb83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -115,3 +115,10 @@ filterwarnings = [ ] addopts = "--cov=auto_dev --cov-report html" + +[tool.coverage.run] +source = ["."] +branch = true + +[tool.coverage.paths] +source = ["auto_dev", "/tmp/*/auto_dev"] From 7fa682e6525b7c6bc9c65f0e0013869e2e453c59 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 15:14:25 +0200 Subject: [PATCH 176/189] feat: monkeypatch PYTHONPATH in test_filesystem fixtures --- tests/conftest.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 088d3ea8..c73c150a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -67,16 +67,18 @@ def openapi_test_case(request): @pytest.fixture -def test_filesystem(): +def test_filesystem(monkeypatch): """Fixture for invoking command-line interfaces.""" with isolated_filesystem(copy_cwd=True) as directory: + monkeypatch.setenv("PYTHONPATH", directory) yield directory @pytest.fixture -def test_clean_filesystem(): +def test_clean_filesystem(monkeypatch): """Fixture for invoking command-line interfaces.""" with isolated_filesystem() as directory: + monkeypatch.setenv("PYTHONPATH", directory) yield directory @@ -109,10 +111,19 @@ def dummy_agent_tim(test_packages_filesystem) -> Path: @pytest.fixture(scope="module") -def module_scoped_dummy_agent_tim() -> Path: +def module_monkeypatch(): + """Module-scoped monkeypatch.""" + mp = pytest.MonkeyPatch() + yield mp + mp.undo() + + +@pytest.fixture(scope="module") +def module_scoped_dummy_agent_tim(module_monkeypatch) -> Path: """Fixture for module scoped dummy agent tim.""" with isolated_filesystem(copy_cwd=True) as directory: + module_monkeypatch.setenv("PYTHONPATH", directory) command = ["autonomy", "packages", "init"] result = subprocess.run(command, check=False, text=True, capture_output=True) if result.returncode != 0: From ca3c968e5c34ded97e3a08f88eb85d0a1520ebbc Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 15:15:52 +0200 Subject: [PATCH 177/189] feat: get_test_cpu_count in auto_dev/tests based on os.environ.get('CI') --- auto_dev/commands/test.py | 2 +- auto_dev/test.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/auto_dev/commands/test.py b/auto_dev/commands/test.py index 81cac598..41af58e5 100644 --- a/auto_dev/commands/test.py +++ b/auto_dev/commands/test.py @@ -117,7 +117,7 @@ def test(ctx, path, watch, coverage_report) -> None: results = {} for package in range(len(packages)): click.echo(f"Testing {packages[package]} {package + 1}/{len(packages)}") - result = test_path(str(packages[package]), verbose=verbose, watch=watch) + result = test_path(str(packages[package]), verbose=verbose, watch=watch, multiple=True) results[packages[package]] = result click.echo(f"{'👌' if result else '❗'} - {packages[package]}") diff --git a/auto_dev/test.py b/auto_dev/test.py index bf07d1ff..214874d6 100644 --- a/auto_dev/test.py +++ b/auto_dev/test.py @@ -14,6 +14,11 @@ """ +def get_test_cpu_count() -> str: + """Determine how many CPUs to use for pytest-xdist.""" + return str(cpu_count()) if os.getenv("CI") else "auto" + + def test_path( path: str, verbose: bool = False, @@ -57,7 +62,7 @@ def test_path( extra_args.append("-w") if multiple: - extra_args.extend(("-n", str(cpu_count()))) + extra_args.extend(("-n", get_test_cpu_count())) args = [path, *extra_args] os.environ["PYTHONPATH"] = "." From a5fd08a0b81413af9b2d275acae4478d27a7711e Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 15:18:54 +0200 Subject: [PATCH 178/189] tests: add HYPOTHESIS_SETTINGS to test_protocols.py --- tests/test_protocol.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 6acb3632..b4271c63 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -1,6 +1,5 @@ """Module for testing protocol generation.""" -import os import tempfile import functools import subprocess @@ -12,6 +11,14 @@ from auto_dev.protocols.scaffolder import read_protocol_spec +HYPOTHESIS_SETTINGS = """ +from hypothesis import HealthCheck, settings + +settings.register_profile("generated", deadline=1000, suppress_health_check=[HealthCheck.too_slow]) +settings.load_profile("generated") +""" + + @functools.lru_cache def _get_proto_files() -> dict[str, Path]: repo_root = protodantic.get_repo_root() @@ -67,7 +74,7 @@ def test_protodantic(proto_path: Path): tmp_path = Path(tmp_dir) code_out = tmp_path / "models.py" test_out = tmp_path / "test_models.py" - (tmp_path / "__init__.py").touch() + (tmp_path / "__init__.py").write_text(HYPOTHESIS_SETTINGS) protodantic.create(proto_path, code_out, test_out) exit_code = pytest.main([tmp_dir, "-vv", "-s", "--tb=long", "-p", "no:warnings"]) assert exit_code == 0 @@ -127,12 +134,8 @@ def test_scaffold_protocol(module_scoped_dummy_agent_tim, protocol_spec: Path): msg = f"Protocol already exists in dummy_agent_tim: {protocol_outpath}" raise ValueError(msg) - # Point PYTHONPATH to the temporary project root so generated modules are discoverable - env = os.environ.copy() - env["PYTHONPATH"] = str(repo_root) - command = ["adev", "-v", "scaffold", "protocol", str(protocol_spec)] - result = subprocess.run(command, env=env, check=False, text=True, capture_output=True) + result = subprocess.run(command, check=False, text=True, capture_output=True) if result.returncode != 0: msg = f"Protocol scaffolding failed: {result.stderr}" raise ValueError(msg) @@ -140,10 +143,10 @@ def test_scaffold_protocol(module_scoped_dummy_agent_tim, protocol_spec: Path): assert protocol_outpath.exists() test_dir = protocol_outpath / "tests" + (test_dir / "__init__.py").write_text(HYPOTHESIS_SETTINGS) command = ["pytest", str(test_dir), "-vv", "-s", "--tb=long", "-p", "no:warnings"] result = subprocess.run( command, - env=env, check=False, text=True, capture_output=True, From 66fb2a4a9627917a50803a89ed99b6473cae2170 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 15:19:33 +0200 Subject: [PATCH 179/189] chore: disable test_repo.py --- pyproject.toml | 1 - tests/test_repo.py | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 91d2fb83..c7405265 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -118,7 +118,6 @@ addopts = "--cov=auto_dev --cov-report html" [tool.coverage.run] source = ["."] -branch = true [tool.coverage.paths] source = ["auto_dev", "/tmp/*/auto_dev"] diff --git a/tests/test_repo.py b/tests/test_repo.py index f03970db..d30d9725 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -4,6 +4,7 @@ from pathlib import Path import toml +import pytest from aea.cli.utils.config import get_default_author_from_cli_config from auto_dev.utils import change_dir @@ -87,6 +88,7 @@ def test_make_command_executes(self, cli_runner, test_clean_filesystem): assert not error_messages +@pytest.mark.skip class TestRepoPython(BaseTestRepo): """Test scaffolding new python repository.""" @@ -94,6 +96,7 @@ class TestRepoPython(BaseTestRepo): make_commands = "fmt", "lint", "test" +@pytest.mark.skip class TestRepoAutonomy(BaseTestRepo): """Test scaffolding new autonomy repository.""" From 27f6b7712023ef776ff853b84c8e93e725b42d60 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:03:44 +0200 Subject: [PATCH 180/189] fix: remove monkeypath PYTHONPATH from test_clean_filesystem --- tests/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index c73c150a..e1457acd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -78,7 +78,6 @@ def test_filesystem(monkeypatch): def test_clean_filesystem(monkeypatch): """Fixture for invoking command-line interfaces.""" with isolated_filesystem() as directory: - monkeypatch.setenv("PYTHONPATH", directory) yield directory From 82479adddd44c949b0de972d72e9ba5b98370afb Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:10:43 +0200 Subject: [PATCH 181/189] feat: add THIS_REPO_ROOT to constants.py --- auto_dev/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/auto_dev/constants.py b/auto_dev/constants.py index 3a83f717..5af59da9 100644 --- a/auto_dev/constants.py +++ b/auto_dev/constants.py @@ -8,6 +8,8 @@ from aea.configurations.data_types import PublicId +THIS_REPO_ROOT = Path(__file__).parent.parent + DEFAULT_ENCODING = "utf-8" DEFAULT_TZ = "UTC" DEFAULT_TIMEOUT = 10 From a4c47f3ed69284e6e12478c5b39ada7f5340327c Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:12:17 +0200 Subject: [PATCH 182/189] tests: rewrite test_repo.py --- tests/test_repo.py | 201 ++++++++++++--------------------------------- 1 file changed, 52 insertions(+), 149 deletions(-) diff --git a/tests/test_repo.py b/tests/test_repo.py index d30d9725..132086d2 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -1,5 +1,6 @@ """Tests for the click cli.""" +import subprocess import subprocess from pathlib import Path @@ -10,157 +11,59 @@ from auto_dev.utils import change_dir -class BaseTestRepo: - """Test scaffolding new repository.""" - - repo_name = "dummy" - type_of_repo: str - make_commands: tuple[str] - - @property - def cli_args(self): - """CLI arguments.""" - return ["adev", "repo", "scaffold", self.repo_name, "-t", self.type_of_repo] - - @property - def parent_dir(self): - """Parent directory of newly scaffolded repo.""" - return Path.cwd() - - @property - def repo_path(self): - """Path of newly scaffolded repo.""" - return self.parent_dir / self.repo_name - - def test_repo_new(self, cli_runner, test_clean_filesystem): - """Test the format command works with the current package.""" - - assert test_clean_filesystem - runner = cli_runner(self.cli_args) - result = runner.execute() - assert result, runner.output - assert self.repo_path.exists(), f"Repository directory was not created: {self.repo_path}" - assert (self.repo_path / ".git").exists() - - def test_repo_new_fail(self, cli_runner, test_filesystem): - """Test the format command works with the current package.""" - - assert test_filesystem - self.repo_path.mkdir() - runner = cli_runner(self.cli_args) - result = runner.execute() - assert runner.return_code == 1, result.output - - def test_makefile(self, cli_runner, test_clean_filesystem): - """Test scaffolding of Makefile.""" - assert test_clean_filesystem - - runner = cli_runner(self.cli_args) - result = runner.execute(self.cli_args) - assert result, (runner.stdout, "\n".join(runner.stderr)) - makefile = self.repo_path / "Makefile" - assert makefile.exists(), result.output - assert makefile.read_text(encoding="utf-8") - assert self.repo_path.exists() - - def test_make_command_executes(self, cli_runner, test_clean_filesystem): - """Test that the make command can execute properly.""" - error_messages = {} - assert test_clean_filesystem - - # Ensure the repository is created before changing directory - runner = cli_runner(self.cli_args) - result = runner.execute() - assert result, runner.output - assert self.repo_path.exists(), f"Repository directory was not created: {self.repo_path}" +def test_python_repo(cli_runner, test_clean_filesystem): - with change_dir(self.repo_path): - for command in self.make_commands: - result = subprocess.run( - f"make {command}", - shell=True, - capture_output=True, - text=True, - check=False, - ) - if runner.return_code != 0: - error_messages[command] = runner.stderr - assert not error_messages + repo_root = Path(test_clean_filesystem) / "dummy_python" + command = ["adev", "repo", "scaffold", repo_root.name, "-t", "python"] + runner = cli_runner(command) + result = runner.execute() + makefile = repo_root / "Makefile" -@pytest.mark.skip -class TestRepoPython(BaseTestRepo): - """Test scaffolding new python repository.""" + assert result, runner.output + assert repo_root.exists() + assert (repo_root / ".git").exists() + assert makefile.exists() - type_of_repo = "python" + error_messages = {} make_commands = "fmt", "lint", "test" - - -@pytest.mark.skip -class TestRepoAutonomy(BaseTestRepo): - """Test scaffolding new autonomy repository.""" - - author = get_default_author_from_cli_config() - type_of_repo = "autonomy" - make_commands = "fmt", "test", "lint", "hashes" - - def test_gitignore(self, cli_runner, test_clean_filesystem): - """Test the .gitignore works as expected.""" - - assert test_clean_filesystem - runner = cli_runner(self.cli_args) - result = runner.execute() - assert runner.return_code == 0, runner.output - - packages_folder = self.repo_path / "packages" - author_packages = packages_folder / self.author - author_packages.mkdir(parents=True) - - # create files that should be ignored in the authors folder - for folder in ("protocols", "connections", "skills", "agents", "services"): - subfolder = author_packages / folder - subfolder.mkdir() - (subfolder / "keys.json").write_text("SECRET") - (subfolder / "ethereum_private_key.txt").write_text("SECRET") - (subfolder / "my_private_keys").write_text("SECRET") - (subfolder / "__pycache__").mkdir() - (subfolder / "__pycache__" / "cachefile").write_text("cache data") - - with change_dir(self.repo_path): - result = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=False) - assert result.returncode == 0 - - # any other file created in the author's own package directory should be detected - (author_packages / "some_other_file").write_text("to_be_committed") - result = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=False) - assert result.returncode == 0 - assert "packages" in result.stdout - - def test_pyproject_versions( - self, - ): - """Test the pyproject.toml versions are updated.""" - - # We read in the pyproject.toml file and check the versions - current_pyproject = self.parent_dir / "pyproject.toml" - repo_pyproject = ( - self.parent_dir / "auto_dev" / "data" / "repo" / "templates" / "autonomy" / "pyproject.toml.template" - ) # pylint: disable=line-too-long - - auto_dev_deps = toml.loads(current_pyproject.read_text())["tool"]["poetry"]["dependencies"] - repo_deps = toml.loads( - repo_pyproject.read_text().format( - project_name=self.repo_name, - author=self.author, - ) - )["tool"]["poetry"]["dependencies"] - - errors = [] - for key in auto_dev_deps: - if key not in repo_deps: - continue - if auto_dev_deps[key] in repo_deps[key]: - continue - val = f"{key} New: {auto_dev_deps[key]} old: {repo_deps[key]}" - errors.append(val) - assert not errors, errors + for command in make_commands: + result = subprocess.run( + ["make", command], + shell=False, + capture_output=True, + text=True, + check=False, + ) + if not runner.return_code == 0: + error_messages[command] = runner.stderr + assert not error_messages + + +def test_autonomy_repo(cli_runner, test_clean_filesystem): + + repo_root = Path(test_clean_filesystem) / "dummy_autonomy" + + command = ["adev", "repo", "scaffold", repo_root.name, "-t", "autonomy"] + runner = cli_runner(command) + result = runner.execute() + makefile = repo_root / "Makefile" + + assert result, runner.output + assert repo_root.exists() + assert (repo_root / ".git").exists() + assert makefile.exists() + + error_messages = {} + make_commands = "fmt", "lint", "test", "hashes" + for command in make_commands: + result = subprocess.run( + ["make", command], + shell=False, + capture_output=True, + text=True, + check=False, + ) + if not runner.return_code == 0: + error_messages[command] = runner.stderr + assert not error_messages From e0efc06d7ff0df285ff0c71bc276e043f03f5649 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:13:09 +0200 Subject: [PATCH 183/189] feat: autonomy/pyproject.jinja --- .../templates/repo/autonomy/pyproject.jinja | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 auto_dev/data/templates/repo/autonomy/pyproject.jinja diff --git a/auto_dev/data/templates/repo/autonomy/pyproject.jinja b/auto_dev/data/templates/repo/autonomy/pyproject.jinja new file mode 100644 index 00000000..11b24ad2 --- /dev/null +++ b/auto_dev/data/templates/repo/autonomy/pyproject.jinja @@ -0,0 +1,24 @@ +[build-system] +{{ build_system }} + +[tool.poetry] +name = "{{ project_name }}" +version = "0.1.0" +description = "" +authors = ["{{ authors }}"] +readme = "README.md" +license = "Apache-2.0" +classifiers = [ +{{ classifiers }} +] +package-mode = false + +[tool.poetry.dependencies] +python = "{{ python }}" +autonomy-dev = {extras = ["all"], version = "{{ version }}"} + +[tool.poetry.group.dev.dependencies] +{{ dev_dependencies }} + +[tool.black] +{{ black_config }} From c7947c54b3ffbffb1e32dace112bcdeb794884ad Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:13:55 +0200 Subject: [PATCH 184/189] fix: render autonomy pyproject.toml based on adev pyproject.toml --- auto_dev/commands/repo.py | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/auto_dev/commands/repo.py b/auto_dev/commands/repo.py index d5c463d0..ba941796 100644 --- a/auto_dev/commands/repo.py +++ b/auto_dev/commands/repo.py @@ -11,13 +11,17 @@ import os import sys import difflib +import subprocess from shutil import rmtree from pathlib import Path from dataclasses import dataclass +import toml import requests import rich_click as click from rich import print # pylint: disable=W0622 +from toml import TomlPreserveInlineDictEncoder +from jinja2 import Environment, FileSystemLoader from rich.prompt import Prompt from rich.progress import Progress, track from aea.cli.utils.config import get_default_author_from_cli_config @@ -26,9 +30,11 @@ from auto_dev.enums import UserInput from auto_dev.utils import change_dir from auto_dev.constants import ( + THIS_REPO_ROOT, DEFAULT_TIMEOUT, TEMPLATE_FOLDER, DEFAULT_ENCODING, + JINJA_TEMPLATE_FOLDER, SAMPLE_PYTHON_CLI_FILE, SAMPLE_PYTHON_MAIN_FILE, CheckResult, @@ -60,6 +66,34 @@ def execute_commands(*commands: str, verbose: bool, logger, shell: bool = False) sys.exit(1) +def _render_autonomy_pyproject_template(project_name: str, authors: str) -> str: + env = Environment(loader=FileSystemLoader(JINJA_TEMPLATE_FOLDER), autoescape=False) # noqa + template = env.get_template("repo/autonomy/pyproject.jinja") + + pyproject_path = THIS_REPO_ROOT / "pyproject.toml" + pyproject = toml.load(pyproject_path) + + build_system = pyproject["build-system"] + classifiers = pyproject["tool"]["poetry"]["classifiers"] + python = pyproject["tool"]["poetry"]["dependencies"]["python"] + current_version = pyproject["tool"]["poetry"]["version"] + min_minor_version = ".".join(current_version.split(".")[:2]) + version = f">={min_minor_version}.0,<={current_version}" + dev_dependencies = pyproject["tool"]["poetry"]["group"]["dev"]["dependencies"] + black_config = pyproject["tool"]["black"] + + return template.render( + build_system=toml.dumps(build_system), + project_name=project_name, + authors=authors, + classifiers=" " + ",\n ".join(f'"{c}"' for c in classifiers), + python=python, + version=version, + dev_dependencies=toml.dumps(dev_dependencies, TomlPreserveInlineDictEncoder()), + black_config=toml.dumps(black_config), + ) + + cli = build_cli() render_args = { @@ -102,6 +136,23 @@ def scaffold( """Scaffold files for a new repo.""" new_repo_dir = Path.cwd() template_folder = TEMPLATES[self.type_of_repo] + + if self.type_of_repo == "autonomy": + project_name = self.scaffold_kwargs["project_name"] + authors = self.scaffold_kwargs["author"] + pyproject_content = _render_autonomy_pyproject_template(project_name, authors) + (new_repo_dir / "pyproject.toml").write_text(pyproject_content) + result = subprocess.run( + ["poetry", "lock"], + capture_output=True, + text=True, + check=False, + cwd=new_repo_dir, + ) + if result.returncode != 0: + msg = f"Failed to lock packages:\n{result.stderr}" + raise ValueError(msg) + for file in track( self.template_files, description=f"Scaffolding {self.type_of_repo} repo", From 8e4035f23f5c70e80e1fb781d4b46625cc1b5755 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:15:38 +0200 Subject: [PATCH 185/189] chore: remove autonomy pyproject.toml.template poetry.lock --- .../data/repo/templates/autonomy/poetry.lock | 4708 ----------------- .../autonomy/pyproject.toml.template | 31 - 2 files changed, 4739 deletions(-) delete mode 100644 auto_dev/data/repo/templates/autonomy/poetry.lock delete mode 100644 auto_dev/data/repo/templates/autonomy/pyproject.toml.template diff --git a/auto_dev/data/repo/templates/autonomy/poetry.lock b/auto_dev/data/repo/templates/autonomy/poetry.lock deleted file mode 100644 index 0afd3c17..00000000 --- a/auto_dev/data/repo/templates/autonomy/poetry.lock +++ /dev/null @@ -1,4708 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "aiohappyeyeballs" -version = "2.5.0" -description = "Happy Eyeballs for asyncio" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "aiohappyeyeballs-2.5.0-py3-none-any.whl", hash = "sha256:0850b580748c7071db98bffff6d4c94028d0d3035acc20fd721a0ce7e8cac35d"}, - {file = "aiohappyeyeballs-2.5.0.tar.gz", hash = "sha256:18fde6204a76deeabc97c48bdd01d5801cfda5d6b9c8bbeb1aaaee9d648ca191"}, -] - -[[package]] -name = "aiohttp" -version = "3.11.13" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4fe27dbbeec445e6e1291e61d61eb212ee9fed6e47998b27de71d70d3e8777d"}, - {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e64ca2dbea28807f8484c13f684a2f761e69ba2640ec49dacd342763cc265ef"}, - {file = "aiohttp-3.11.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9840be675de208d1f68f84d578eaa4d1a36eee70b16ae31ab933520c49ba1325"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28a772757c9067e2aee8a6b2b425d0efaa628c264d6416d283694c3d86da7689"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b88aca5adbf4625e11118df45acac29616b425833c3be7a05ef63a6a4017bfdb"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce10ddfbe26ed5856d6902162f71b8fe08545380570a885b4ab56aecfdcb07f4"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa48dac27f41b36735c807d1ab093a8386701bbf00eb6b89a0f69d9fa26b3671"}, - {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89ce611b1eac93ce2ade68f1470889e0173d606de20c85a012bfa24be96cf867"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78e4dd9c34ec7b8b121854eb5342bac8b02aa03075ae8618b6210a06bbb8a115"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:66047eacbc73e6fe2462b77ce39fc170ab51235caf331e735eae91c95e6a11e4"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ad8f1c19fe277eeb8bc45741c6d60ddd11d705c12a4d8ee17546acff98e0802"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64815c6f02e8506b10113ddbc6b196f58dbef135751cc7c32136df27b736db09"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:967b93f21b426f23ca37329230d5bd122f25516ae2f24a9cea95a30023ff8283"}, - {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf1f31f83d16ec344136359001c5e871915c6ab685a3d8dee38e2961b4c81730"}, - {file = "aiohttp-3.11.13-cp310-cp310-win32.whl", hash = "sha256:00c8ac69e259c60976aa2edae3f13d9991cf079aaa4d3cd5a49168ae3748dee3"}, - {file = "aiohttp-3.11.13-cp310-cp310-win_amd64.whl", hash = "sha256:90d571c98d19a8b6e793b34aa4df4cee1e8fe2862d65cc49185a3a3d0a1a3996"}, - {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b35aab22419ba45f8fc290d0010898de7a6ad131e468ffa3922b1b0b24e9d2e"}, - {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81cba651db8795f688c589dd11a4fbb834f2e59bbf9bb50908be36e416dc760"}, - {file = "aiohttp-3.11.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f55d0f242c2d1fcdf802c8fabcff25a9d85550a4cf3a9cf5f2a6b5742c992839"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4bea08a6aad9195ac9b1be6b0c7e8a702a9cec57ce6b713698b4a5afa9c2e33"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6070bcf2173a7146bb9e4735b3c62b2accba459a6eae44deea0eb23e0035a23"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:718d5deb678bc4b9d575bfe83a59270861417da071ab44542d0fcb6faa686636"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f6b2c5b4a4d22b8fb2c92ac98e0747f5f195e8e9448bfb7404cd77e7bfa243f"}, - {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747ec46290107a490d21fe1ff4183bef8022b848cf9516970cb31de6d9460088"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:01816f07c9cc9d80f858615b1365f8319d6a5fd079cd668cc58e15aafbc76a54"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a08ad95fcbd595803e0c4280671d808eb170a64ca3f2980dd38e7a72ed8d1fea"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c97be90d70f7db3aa041d720bfb95f4869d6063fcdf2bb8333764d97e319b7d0"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ab915a57c65f7a29353c8014ac4be685c8e4a19e792a79fe133a8e101111438e"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:35cda4e07f5e058a723436c4d2b7ba2124ab4e0aa49e6325aed5896507a8a42e"}, - {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:af55314407714fe77a68a9ccaab90fdb5deb57342585fd4a3a8102b6d4370080"}, - {file = "aiohttp-3.11.13-cp311-cp311-win32.whl", hash = "sha256:42d689a5c0a0c357018993e471893e939f555e302313d5c61dfc566c2cad6185"}, - {file = "aiohttp-3.11.13-cp311-cp311-win_amd64.whl", hash = "sha256:b73a2b139782a07658fbf170fe4bcdf70fc597fae5ffe75e5b67674c27434a9f"}, - {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2eabb269dc3852537d57589b36d7f7362e57d1ece308842ef44d9830d2dc3c90"}, - {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b77ee42addbb1c36d35aca55e8cc6d0958f8419e458bb70888d8c69a4ca833d"}, - {file = "aiohttp-3.11.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55789e93c5ed71832e7fac868167276beadf9877b85697020c46e9a75471f55f"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c929f9a7249a11e4aa5c157091cfad7f49cc6b13f4eecf9b747104befd9f56f2"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d33851d85537bbf0f6291ddc97926a754c8f041af759e0aa0230fe939168852b"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9229d8613bd8401182868fe95688f7581673e1c18ff78855671a4b8284f47bcb"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669dd33f028e54fe4c96576f406ebb242ba534dd3a981ce009961bf49960f117"}, - {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1b20a1ace54af7db1f95af85da530fe97407d9063b7aaf9ce6a32f44730778"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5724cc77f4e648362ebbb49bdecb9e2b86d9b172c68a295263fa072e679ee69d"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa36c35e94ecdb478246dd60db12aba57cfcd0abcad43c927a8876f25734d496"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9b5b37c863ad5b0892cc7a4ceb1e435e5e6acd3f2f8d3e11fa56f08d3c67b820"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e06cf4852ce8c4442a59bae5a3ea01162b8fcb49ab438d8548b8dc79375dad8a"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5194143927e494616e335d074e77a5dac7cd353a04755330c9adc984ac5a628e"}, - {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afcb6b275c2d2ba5d8418bf30a9654fa978b4f819c2e8db6311b3525c86fe637"}, - {file = "aiohttp-3.11.13-cp312-cp312-win32.whl", hash = "sha256:7104d5b3943c6351d1ad7027d90bdd0ea002903e9f610735ac99df3b81f102ee"}, - {file = "aiohttp-3.11.13-cp312-cp312-win_amd64.whl", hash = "sha256:47dc018b1b220c48089b5b9382fbab94db35bef2fa192995be22cbad3c5730c8"}, - {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9862d077b9ffa015dbe3ce6c081bdf35135948cb89116e26667dd183550833d1"}, - {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbfef0666ae9e07abfa2c54c212ac18a1f63e13e0760a769f70b5717742f3ece"}, - {file = "aiohttp-3.11.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a1f7d857c4fcf7cabb1178058182c789b30d85de379e04f64c15b7e88d66fb"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba40b7ae0f81c7029583a338853f6607b6d83a341a3dcde8bed1ea58a3af1df9"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5b95787335c483cd5f29577f42bbe027a412c5431f2f80a749c80d040f7ca9f"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d474c5c1f0b9405c1565fafdc4429fa7d986ccbec7ce55bc6a330f36409cad"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e83fb1991e9d8982b3b36aea1e7ad27ea0ce18c14d054c7a404d68b0319eebb"}, - {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4586a68730bd2f2b04a83e83f79d271d8ed13763f64b75920f18a3a677b9a7f0"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fe4eb0e7f50cdb99b26250d9328faef30b1175a5dbcfd6d0578d18456bac567"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a8a6bc19818ac3e5596310ace5aa50d918e1ebdcc204dc96e2f4d505d51740c"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f27eec42f6c3c1df09cfc1f6786308f8b525b8efaaf6d6bd76c1f52c6511f6a"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a4a13dfbb23977a51853b419141cd0a9b9573ab8d3a1455c6e63561387b52ff"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:02876bf2f69b062584965507b07bc06903c2dc93c57a554b64e012d636952654"}, - {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b992778d95b60a21c4d8d4a5f15aaab2bd3c3e16466a72d7f9bfd86e8cea0d4b"}, - {file = "aiohttp-3.11.13-cp313-cp313-win32.whl", hash = "sha256:507ab05d90586dacb4f26a001c3abf912eb719d05635cbfad930bdbeb469b36c"}, - {file = "aiohttp-3.11.13-cp313-cp313-win_amd64.whl", hash = "sha256:5ceb81a4db2decdfa087381b5fc5847aa448244f973e5da232610304e199e7b2"}, - {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:51c3ff9c7a25f3cad5c09d9aacbc5aefb9267167c4652c1eb737989b554fe278"}, - {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e271beb2b1dabec5cd84eb488bdabf9758d22ad13471e9c356be07ad139b3012"}, - {file = "aiohttp-3.11.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e9eb7e5764abcb49f0e2bd8f5731849b8728efbf26d0cac8e81384c95acec3f"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baae005092e3f200de02699314ac8933ec20abf998ec0be39448f6605bce93df"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1982c98ac62c132d2b773d50e2fcc941eb0b8bad3ec078ce7e7877c4d5a2dce7"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2b25b2eeb35707113b2d570cadc7c612a57f1c5d3e7bb2b13870fe284e08fc0"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b27961d65639128336b7a7c3f0046dcc62a9443d5ef962e3c84170ac620cec47"}, - {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe9f1e05025eacdd97590895e2737b9f851d0eb2e017ae9574d9a4f0b6252"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa1fb1b61881c8405829c50e9cc5c875bfdbf685edf57a76817dfb50643e4a1a"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:25de43bb3cf83ad83efc8295af7310219af6dbe4c543c2e74988d8e9c8a2a917"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe7065e2215e4bba63dc00db9ae654c1ba3950a5fff691475a32f511142fcddb"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7836587eef675a17d835ec3d98a8c9acdbeb2c1d72b0556f0edf4e855a25e9c1"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:85fa0b18558eb1427090912bd456a01f71edab0872f4e0f9e4285571941e4090"}, - {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a86dc177eb4c286c19d1823ac296299f59ed8106c9536d2b559f65836e0fb2c6"}, - {file = "aiohttp-3.11.13-cp39-cp39-win32.whl", hash = "sha256:684eea71ab6e8ade86b9021bb62af4bf0881f6be4e926b6b5455de74e420783a"}, - {file = "aiohttp-3.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:82c249f2bfa5ecbe4a1a7902c81c0fba52ed9ebd0176ab3047395d02ad96cfcb"}, - {file = "aiohttp-3.11.13.tar.gz", hash = "sha256:8ce789231404ca8fff7f693cdce398abf6d90fd5dae2b1847477196c243b1fbb"}, -] - -[package.dependencies] -aiohappyeyeballs = ">=2.3.0" -aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -propcache = ">=0.2.0" -yarl = ">=1.17.0,<2.0" - -[package.extras] -speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""] - -[[package]] -name = "aiosignal" -version = "1.3.2" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, - {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "anchorpy" -version = "0.18.0" -description = "The Python Anchor client." -optional = false -python-versions = ">=3.9,<4.0" -groups = ["main"] -files = [ - {file = "anchorpy-0.18.0-py3-none-any.whl", hash = "sha256:664672c2de94ed8910173fd3235d918513a927de80612db625f395bc8a0160d1"}, - {file = "anchorpy-0.18.0.tar.gz", hash = "sha256:606c49f2dba41046ba60947d19c19eb17587b490b5d1a88642722b42159aa998"}, -] - -[package.dependencies] -anchorpy-core = ">=0.1.3,<0.2.0" -based58 = ">=0.1.1,<0.2.0" -borsh-construct = ">=0.1.0,<0.2.0" -construct-typing = ">=0.5.1,<0.6.0" -jsonrpcclient = ">=4.0.1,<5.0.0" -more-itertools = ">=8.11.0,<9.0.0" -py = ">=1.11.0,<2.0.0" -pyheck = ">=0.1.4,<0.2.0" -pytest = ">=7.2.0,<8.0.0" -pytest-asyncio = ">=0.21.0,<0.22.0" -pytest-xprocess = ">=0.18.1,<0.19.0" -solana = ">=0.30.2,<0.31.0" -solders = ">=0.18.0,<0.19.0" -toml = ">=0.10.2,<0.11.0" -toolz = ">=0.11.2,<0.12.0" -websockets = ">=9.0,<11.0" -zstandard = ">=0.18.0,<0.19.0" - -[package.extras] -cli = ["autoflake (>=1.4,<2.0)", "black (>=22.3.0,<23.0.0)", "genpy (>=2021.1,<2022.0)", "ipython (>=8.0.1,<9.0.0)", "typer (==0.4.1)"] - -[[package]] -name = "anchorpy-core" -version = "0.1.3" -description = "Python bindings for Anchor Rust code" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "anchorpy_core-0.1.3-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:c9af073115feaab9a7fd14bc9f0d19a87650042bd430e44e9c7714b18f5aeb3a"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4511a3a9a0425a84305e56087b81969d2929ac642b2c1d6fb2a500c8f987d8d3"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f5f37b3b75e891227beeb9f6ca35505317aa41e6f5a5ba92599aa3a4ecad9226"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3690504cd40e5ea62aa78d23de3e93a8e8929fe50a86412253f9705640ce8993"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8db7816180720041d7a756cd87e75fc9875c4e5b2c68faf8b440053d44d1a747"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41134b3c08ed405c92e247ba77e966edf6859e741ae20109bcc3d02dfd0d37fc"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:21a6cc01fb5932b9bbfcf3ab36e924c5a5f8897a4dfad73c96c2f6e934aeddf0"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:a6105025999e7270e0961e6c8a0436aa4218fc2d78ca056361d2aa2dffea46a3"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e9fe6f2e06dd0d3b27c079121a2bc0b495c7c1dc5026e81a2a0f947d7d840e5f"}, - {file = "anchorpy_core-0.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:c952fe786c126e3c8b902d10c6d423085654001478e9a77600b105b3c66ac8ec"}, - {file = "anchorpy_core-0.1.3.tar.gz", hash = "sha256:46a328ee5b6be730311ff673ad60e8e6e40e2eea7f8254c687ecff21416a2256"}, -] - -[package.dependencies] -jsonalias = "0.1.1" - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.8.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, - {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] -trio = ["trio (>=0.26.1)"] - -[[package]] -name = "asn1crypto" -version = "1.4.0" -description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "asn1crypto-1.4.0-py2.py3-none-any.whl", hash = "sha256:4bcdf33c861c7d40bdcd74d8e4dd7661aac320fcdf40b9a3f95b4ee12fde2fa8"}, - {file = "asn1crypto-1.4.0.tar.gz", hash = "sha256:f4f6e119474e58e04a2b1af817eb585b4fd72bdd89b998624712b5c99be7641c"}, -] - -[[package]] -name = "async-timeout" -version = "5.0.1" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version < \"3.11\"" -files = [ - {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, - {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, -] - -[[package]] -name = "asyncio" -version = "3.4.3" -description = "reference implementation of PEP 3156" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "asyncio-3.4.3-cp33-none-win32.whl", hash = "sha256:b62c9157d36187eca799c378e572c969f0da87cd5fc42ca372d92cdb06e7e1de"}, - {file = "asyncio-3.4.3-cp33-none-win_amd64.whl", hash = "sha256:c46a87b48213d7464f22d9a497b9eef8c1928b68320a2fa94240f969f6fec08c"}, - {file = "asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d"}, - {file = "asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41"}, -] - -[[package]] -name = "attrs" -version = "25.1.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, - {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "autonomy-dev" -version = "0.2.151" -description = "A collection of tooling to enable open source development of autonomy tools" -optional = false -python-versions = "<3.14,>=3.10" -groups = ["main"] -files = [ - {file = "autonomy_dev-0.2.151-py3-none-any.whl", hash = "sha256:55cb711367b32f0ac8bf394bb7dd9f1dff7d8dfdf81709055e84d2687d576280"}, - {file = "autonomy_dev-0.2.151.tar.gz", hash = "sha256:19c47ef313bcb097c5f5b84e28717534553111773795fd7c01e7f8210427e0a1"}, -] - -[package.dependencies] -asn1crypto = ">=1.4.0,<1.5.0" -disutils = ">=1.4.32.post2,<2.0.0" -eth-abi = "5.1.0" -eth-utils = "2.3.1" -grpcio = "1.69.0" -hypothesis = "6.122.3" -ipfshttpclient = "0.8.0a2" -isort = {version = ">=5.13.2,<6.0.0", optional = true, markers = "extra == \"all\""} -open-aea = {version = "1.65.0", optional = true, markers = "extra == \"all\""} -open-aea-cli-ipfs = "1.65.0" -open-aea-ledger-cosmos = {version = "1.65.0", optional = true, markers = "extra == \"all\""} -open-aea-ledger-ethereum = {version = "1.65.0", optional = true, markers = "extra == \"all\""} -open-aea-ledger-solana = {version = "1.65.0", optional = true, markers = "extra == \"all\""} -open-aea-test-autonomy = "0.19.7" -open-autonomy = {version = "0.19.7", optional = true, markers = "extra == \"all\""} -openapi-spec-validator = "0.2.8" -protobuf = ">=3.19.1,<4.25.0" -py-eth-sig-utils = "*" -py-multibase = "1.0.3" -py-multicodec = "0.2.1" -pycryptodome = "3.20.0" -pydantic = {version = ">=2.8.2,<3.0.0", optional = true, markers = "extra == \"all\""} -pydoclint = {version = ">=0.6.0,<0.7.0", extras = ["all"], optional = true, markers = "extra == \"all\""} -requests = ">=2.28.1,<3" -rich-click = ">=1.8.2,<2.0.0" -ruff = {version = ">=0.5.7,<0.6.0", optional = true, markers = "extra == \"all\""} -setuptools = {version = ">=75.8.0,<76.0.0", optional = true, markers = "extra == \"all\""} -tbump = {version = ">=6.11.0,<7.0.0", optional = true, markers = "extra == \"all\""} -toml = "0.10.2" -tomte = {version = "0.2.17", extras = ["black", "cli", "ledgers", "tests"]} -typing_extensions = ">=3.10.0.2" -web3 = ">=6.0.0,<7.0.0" - -[package.extras] -all = ["isort (>=5.13.2,<6.0.0)", "open-aea (==1.65.0)", "open-aea-ledger-cosmos (==1.65.0)", "open-aea-ledger-ethereum (==1.65.0)", "open-aea-ledger-solana (==1.65.0)", "open-autonomy (==0.19.7)", "pydantic (>=2.8.2,<3.0.0)", "pydoclint[all] (>=0.6.0,<0.7.0)", "ruff (>=0.5.7,<0.6.0)", "setuptools (>=75.8.0,<76.0.0)", "tbump (>=6.11.0,<7.0.0)"] - -[[package]] -name = "backoff" -version = "2.2.1" -description = "Function decoration for backoff and retry" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, - {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, -] - -[[package]] -name = "base58" -version = "2.1.1" -description = "Base58 and Base58Check implementation." -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "base58-2.1.1-py3-none-any.whl", hash = "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2"}, - {file = "base58-2.1.1.tar.gz", hash = "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c"}, -] - -[package.extras] -tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", "pytest-cov", "pytest-flake8"] - -[[package]] -name = "based58" -version = "0.1.1" -description = "A fast Python library for Base58 and Base58Check" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "based58-0.1.1-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:745851792ce5fada615f05ec61d7f360d19c76950d1e86163b2293c63a5d43bc"}, - {file = "based58-0.1.1-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f8448a71678bd1edc0a464033695686461ab9d6d0bc3282cb29b94f883583572"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:852c37206374a62c5d3ef7f6777746e2ad9106beec4551539e9538633385e613"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3fb17f0aaaad0381c8b676623c870c1a56aca039e2a7c8416e65904d80a415f7"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:06f3c40b358b0c6fc6fc614c43bb11ef851b6d04e519ac1eda2833420cb43799"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a9db744be79c8087eebedbffced00c608b3ed780668ab3c59f1d16e72c84947"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0506435e98836cc16e095e0d6dc428810e0acfb44bc2f3ac3e23e051a69c0e3e"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8937e97fa8690164fd11a7c642f6d02df58facd2669ae7355e379ab77c48c924"}, - {file = "based58-0.1.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14b01d91ac250300ca7f634e5bf70fb2b1b9aaa90cc14357943c7da525a35aff"}, - {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6c03c7f0023981c7d52fc7aad23ed1f3342819358b9b11898d693c9ef4577305"}, - {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:621269732454875510230b85053f462dffe7d7babecc8c553fdb488fd15810ff"}, - {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:aba18f6c869fade1d1551fe398a376440771d6ce288c54cba71b7090cf08af02"}, - {file = "based58-0.1.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ae7f17b67bf0c209da859a6b833504aa3b19dbf423cbd2369aa17e89299dc972"}, - {file = "based58-0.1.1-cp37-abi3-win32.whl", hash = "sha256:d8dece575de525c1ad889d9ab239defb7a6ceffc48f044fe6e14a408fb05bef4"}, - {file = "based58-0.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:ab85804a401a7b5a7141fbb14ef5b5f7d85288357d1d3f0085d47e616cef8f5a"}, - {file = "based58-0.1.1.tar.gz", hash = "sha256:80804b346b34196c89dc7a3dc89b6021f910f4cd75aac41d433ca1880b1672dc"}, -] - -[[package]] -name = "bcrypt" -version = "4.3.0" -description = "Modern password hashing for your software and your servers" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "bcrypt-4.3.0-cp313-cp313t-macosx_10_12_universal2.whl", hash = "sha256:f01e060f14b6b57bbb72fc5b4a83ac21c443c9a2ee708e04a10e9192f90a6281"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5eeac541cefd0bb887a371ef73c62c3cd78535e4887b310626036a7c0a817bb"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59e1aa0e2cd871b08ca146ed08445038f42ff75968c7ae50d2fdd7860ade2180"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:0042b2e342e9ae3d2ed22727c1262f76cc4f345683b5c1715f0250cf4277294f"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74a8d21a09f5e025a9a23e7c0fd2c7fe8e7503e4d356c0a2c1486ba010619f09"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:0142b2cb84a009f8452c8c5a33ace5e3dfec4159e7735f5afe9a4d50a8ea722d"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_34_aarch64.whl", hash = "sha256:12fa6ce40cde3f0b899729dbd7d5e8811cb892d31b6f7d0334a1f37748b789fd"}, - {file = "bcrypt-4.3.0-cp313-cp313t-manylinux_2_34_x86_64.whl", hash = "sha256:5bd3cca1f2aa5dbcf39e2aa13dd094ea181f48959e1071265de49cc2b82525af"}, - {file = "bcrypt-4.3.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:335a420cfd63fc5bc27308e929bee231c15c85cc4c496610ffb17923abf7f231"}, - {file = "bcrypt-4.3.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:0e30e5e67aed0187a1764911af023043b4542e70a7461ad20e837e94d23e1d6c"}, - {file = "bcrypt-4.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b8d62290ebefd49ee0b3ce7500f5dbdcf13b81402c05f6dafab9a1e1b27212f"}, - {file = "bcrypt-4.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2ef6630e0ec01376f59a006dc72918b1bf436c3b571b80fa1968d775fa02fe7d"}, - {file = "bcrypt-4.3.0-cp313-cp313t-win32.whl", hash = "sha256:7a4be4cbf241afee43f1c3969b9103a41b40bcb3a3f467ab19f891d9bc4642e4"}, - {file = "bcrypt-4.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c1949bf259a388863ced887c7861da1df681cb2388645766c89fdfd9004c669"}, - {file = "bcrypt-4.3.0-cp38-abi3-macosx_10_12_universal2.whl", hash = "sha256:f81b0ed2639568bf14749112298f9e4e2b28853dab50a8b357e31798686a036d"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:864f8f19adbe13b7de11ba15d85d4a428c7e2f344bac110f667676a0ff84924b"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e36506d001e93bffe59754397572f21bb5dc7c83f54454c990c74a468cd589e"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:842d08d75d9fe9fb94b18b071090220697f9f184d4547179b60734846461ed59"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7c03296b85cb87db865d91da79bf63d5609284fc0cab9472fdd8367bbd830753"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:62f26585e8b219cdc909b6a0069efc5e4267e25d4a3770a364ac58024f62a761"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:beeefe437218a65322fbd0069eb437e7c98137e08f22c4660ac2dc795c31f8bb"}, - {file = "bcrypt-4.3.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:97eea7408db3a5bcce4a55d13245ab3fa566e23b4c67cd227062bb49e26c585d"}, - {file = "bcrypt-4.3.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:191354ebfe305e84f344c5964c7cd5f924a3bfc5d405c75ad07f232b6dffb49f"}, - {file = "bcrypt-4.3.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:41261d64150858eeb5ff43c753c4b216991e0ae16614a308a15d909503617732"}, - {file = "bcrypt-4.3.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:33752b1ba962ee793fa2b6321404bf20011fe45b9afd2a842139de3011898fef"}, - {file = "bcrypt-4.3.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:50e6e80a4bfd23a25f5c05b90167c19030cf9f87930f7cb2eacb99f45d1c3304"}, - {file = "bcrypt-4.3.0-cp38-abi3-win32.whl", hash = "sha256:67a561c4d9fb9465ec866177e7aebcad08fe23aaf6fbd692a6fab69088abfc51"}, - {file = "bcrypt-4.3.0-cp38-abi3-win_amd64.whl", hash = "sha256:584027857bc2843772114717a7490a37f68da563b3620f78a849bcb54dc11e62"}, - {file = "bcrypt-4.3.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3efb1157edebfd9128e4e46e2ac1a64e0c1fe46fb023158a407c7892b0f8c3"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08bacc884fd302b611226c01014eca277d48f0a05187666bca23aac0dad6fe24"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6746e6fec103fcd509b96bacdfdaa2fbde9a553245dbada284435173a6f1aef"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:afe327968aaf13fc143a56a3360cb27d4ad0345e34da12c7290f1b00b8fe9a8b"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d9af79d322e735b1fc33404b5765108ae0ff232d4b54666d46730f8ac1a43676"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f1e3ffa1365e8702dc48c8b360fef8d7afeca482809c5e45e653af82ccd088c1"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3004df1b323d10021fda07a813fd33e0fd57bef0e9a480bb143877f6cba996fe"}, - {file = "bcrypt-4.3.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:531457e5c839d8caea9b589a1bcfe3756b0547d7814e9ce3d437f17da75c32b0"}, - {file = "bcrypt-4.3.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:17a854d9a7a476a89dcef6c8bd119ad23e0f82557afbd2c442777a16408e614f"}, - {file = "bcrypt-4.3.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6fb1fd3ab08c0cbc6826a2e0447610c6f09e983a281b919ed721ad32236b8b23"}, - {file = "bcrypt-4.3.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e965a9c1e9a393b8005031ff52583cedc15b7884fce7deb8b0346388837d6cfe"}, - {file = "bcrypt-4.3.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:79e70b8342a33b52b55d93b3a59223a844962bef479f6a0ea318ebbcadf71505"}, - {file = "bcrypt-4.3.0-cp39-abi3-win32.whl", hash = "sha256:b4d4e57f0a63fd0b358eb765063ff661328f69a04494427265950c71b992a39a"}, - {file = "bcrypt-4.3.0-cp39-abi3-win_amd64.whl", hash = "sha256:e53e074b120f2877a35cc6c736b8eb161377caae8925c17688bd46ba56daaa5b"}, - {file = "bcrypt-4.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c950d682f0952bafcceaf709761da0a32a942272fad381081b51096ffa46cea1"}, - {file = "bcrypt-4.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:107d53b5c67e0bbc3f03ebf5b030e0403d24dda980f8e244795335ba7b4a027d"}, - {file = "bcrypt-4.3.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b693dbb82b3c27a1604a3dff5bfc5418a7e6a781bb795288141e5f80cf3a3492"}, - {file = "bcrypt-4.3.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:b6354d3760fcd31994a14c89659dee887f1351a06e5dac3c1142307172a79f90"}, - {file = "bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a839320bf27d474e52ef8cb16449bb2ce0ba03ca9f44daba6d93fa1d8828e48a"}, - {file = "bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:bdc6a24e754a555d7316fa4774e64c6c3997d27ed2d1964d55920c7c227bc4ce"}, - {file = "bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:55a935b8e9a1d2def0626c4269db3fcd26728cbff1e84f0341465c31c4ee56d8"}, - {file = "bcrypt-4.3.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:57967b7a28d855313a963aaea51bf6df89f833db4320da458e5b3c5ab6d4c938"}, - {file = "bcrypt-4.3.0.tar.gz", hash = "sha256:3a3fd2204178b6d2adcf09cb4f6426ffef54762577a7c9b54c159008cb288c18"}, -] - -[package.extras] -tests = ["pytest (>=3.2.1,!=3.3.0)"] -typecheck = ["mypy"] - -[[package]] -name = "bech32" -version = "1.2.0" -description = "Reference implementation for Bech32 and segwit addresses." -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "bech32-1.2.0-py3-none-any.whl", hash = "sha256:990dc8e5a5e4feabbdf55207b5315fdd9b73db40be294a19b3752cde9e79d981"}, - {file = "bech32-1.2.0.tar.gz", hash = "sha256:7d6db8214603bd7871fcfa6c0826ef68b85b0abd90fa21c285a9c5e21d2bd899"}, -] - -[[package]] -name = "bitarray" -version = "2.9.3" -description = "efficient arrays of booleans -- C extension" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "bitarray-2.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2cf5f5400636c7dda797fd681795ce63932458620fe8c40955890380acba9f62"}, - {file = "bitarray-2.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3487b4718ffa5942fab777835ee36085f8dda7ec4bd0b28433efb117f84852b6"}, - {file = "bitarray-2.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10f44b1e4994035408bea54d7bf0aec79744cad709706bedf28091a48bb7f1a4"}, - {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5c16f97c65add6535748a9c98c70e7ca79759c38a2eb990127fef72f76111a"}, - {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13dbfc42971ba84e9c4ba070f720df6570285a3f89187f07ef422efcb611c19f"}, - {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c28076acfbe7f9a5494d7ae98094a6e209c390c340938845f294818ebf5e4d3"}, - {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7cdd21835936d9a66477836ca23b2cb63295142cb9d9158883e2c0f1f8f6bd"}, - {file = "bitarray-2.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f60887ab3a46e507fa6f8544d8d4b0748da48718591dfe3fe80c62bdea60f10"}, - {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f75e1abd4a37cba3002521d3f5e2b50ef4f4a74342207cad3f52468411d5d8ba"}, - {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dc63da9695383c048b83f5ab77eab35a55bbb2e77c7b6e762eba219929b45b84"}, - {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6fe5a57b859d9bc9c2fd27c78c4b7b83158faf984202de6fb44618caeebfff10"}, - {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1fe5a37bd9441a5ecc2f6e71b43df7176fa376a542ef97484310b8b46a45649a"}, - {file = "bitarray-2.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8a16e42c169ca818d6a15b5dd5acd5d2a26af0fa0588e1036e0e58d01f8387d4"}, - {file = "bitarray-2.9.3-cp310-cp310-win32.whl", hash = "sha256:5e6b5e7940af3474ffaa930cd1ce8215181cbe864d6b5ddb67a15d3c15e935cd"}, - {file = "bitarray-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:c63dbb99ef2ab1281871678624f9c9a5f1682b826e668ce559275ec488b3fa8b"}, - {file = "bitarray-2.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:49fb93b488d180f5c84b79fe687c585a84bf0295ff035d63e09ee24ce1da0558"}, - {file = "bitarray-2.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c2944fb83bbc2aa7f29a713bc4f8c1318e54fa0d06a72bedd350a3fb4a4b91d8"}, - {file = "bitarray-2.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3612d9d3788dc62f1922c917b1539f1cdf02cecc9faef8ae213a8b36093136ca"}, - {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90a9300cdb7c99b1e692bb790cba8acecee1a345a83e58e28c94a0d87c522237"}, - {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1211ed66acbbb221fd7554abf4206a384d79e6192d5cb95325c5c361bbb52a74"}, - {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67757279386accf93eba76b8f97b5acf1664a3e350cbea5f300f53490f8764fd"}, - {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64e19c6a99c32f460c2613f797f77aa37d8e298891d00ea5355158cce80e11ec"}, - {file = "bitarray-2.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72734bd3775f43c5a75385730abb9f84fee6c627eb14f579de4be478f1615c8c"}, - {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a92703471b5d3316c7481bc1852f620f42f7a1b62be27f39d13694827635786f"}, - {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d5d77c81300ca430d4b195ccfbb629d6858258f541b6e96c6b11ec1563cd2681"}, - {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3ba8a29c0d091c952ced1607ce715f5e0524899f24333a493807d00f5938463d"}, - {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:418171d035b191dbe5e86cd2bfb5c3e1ae7d947edc22857a897d1c7251674ae5"}, - {file = "bitarray-2.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e0bd272eba256183be2a17488f9cb096d2e6d3435ecf2e28c1e0857c6d20749"}, - {file = "bitarray-2.9.3-cp311-cp311-win32.whl", hash = "sha256:cc3fd2b0637a619cf13e122bbcf4729ae214d5f25623675597e67c25f9edfe61"}, - {file = "bitarray-2.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1fc2a81a585dbe5e367682156e6350d908a56e2ffd6ca651b0af01994db596f"}, - {file = "bitarray-2.9.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dc47be026f76f1728af00dc7140cec8483fe2f0c476bbf2a59ef47865e00ff96"}, - {file = "bitarray-2.9.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:82b091742ff511cdb06f90af0d2c22e7af3dbff9b8212e2e0d88dfef6a8570b3"}, - {file = "bitarray-2.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d5edb4302a0e3a3d1d0eeb891de3c615d4cb7a446fb41c21eecdcfb29400a6f"}, - {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4786c5525069c19820549dd2f42d33632bc42959ad167138bd8ee5024b922b"}, - {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bfe2de2b4df61ccb9244871a0fdf1fff83be0c1bd7187048c3cf7f81c5fe631"}, - {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31e4f69538f95d2934587d957eea0d283162322dd1af29e57122b20b8cd60f92"}, - {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca44908b2bc08d8995770018638d62626706864f9c599b7818225a12f3dbc2c"}, - {file = "bitarray-2.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:279f8de5d251ee521e365df29c927d9b5732f1ed4f373d2dbbd278fcbad94ff5"}, - {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49bb631b38431c09ecd534d56ef04264397d24d18c4ee6653c84e14ae09d92d"}, - {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:192bffc93ee9a5b6c833c98d1dcc81f5633ddd726b85e18341387d0c1d51f691"}, - {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c516cec28c6511df51d87033f40ec420324a2247469b0c989d344f4d27ea37d2"}, - {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:66241cb9a1c1db294f46cd440141e57e8242874e38f3f61877f72d92ae14768a"}, - {file = "bitarray-2.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ab1f0e7631110c89bea7b605c0c35832333eb9cc97e5de05d71c76d42a1858c9"}, - {file = "bitarray-2.9.3-cp312-cp312-win32.whl", hash = "sha256:42aa5bee6fe8ad3385eaf5c6585016bbc38a7b75efb52ce5c6f8e00e05237dfa"}, - {file = "bitarray-2.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:dc3fd647d845b94fac3652390866f921f914a17f3807a031c826f68dae3f43e3"}, - {file = "bitarray-2.9.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fcfcc1989e3e021a282624017b7fb754210f5332e933b1c3ebc79643727b6551"}, - {file = "bitarray-2.9.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:71b1e229a706798a9e106ca7b03d4c63455deb40b18c92950ec073a05a8f8285"}, - {file = "bitarray-2.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4bb49556d3d505d24c942a4206ad4d0d40e89fa3016a7ea6edc994d5c08d4a8e"}, - {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4466aa1e533a59d5f7fd37219d154ec3f2ba73fce3d8a2e11080ec475bc15fb"}, - {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a9b75adc0fd0bf278bea89dc3d679d74e10d2df98d3d074b7f3d36f323138818"}, - {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:701582bbbeac372b1cd8a3c9daf6c2336dc2d22e14373a6271d788bc4f2b6edc"}, - {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea1f119668bbdbd68008031491515e84441e505163918819994b28f295f762c"}, - {file = "bitarray-2.9.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f400bc18a70bfdb073532c3054ecd78a0e64f96ff7b6140adde5b122580ec2b"}, - {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:aacff5656fb3e15cede7d02903da2634d376aa928d7a81ec8df19b0724d7972a"}, - {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8a2ae42a14cbf766d4478d7101da6359b0648dd813e60eb3486ac56ad2f5add3"}, - {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:616698edb547d10f0b960cb9f2e8629c55a420dd4c2b1ab46706f49a1815621d"}, - {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f277c50ba184929dfeed39b6cf9468e3446093521b0aeb52bd54a21ca08f5473"}, - {file = "bitarray-2.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:661237739b385c90d8837d5e96b06de093cc6e610236977e198f88f5a979686e"}, - {file = "bitarray-2.9.3-cp313-cp313-win32.whl", hash = "sha256:68acec6c19d798051f178a1197b76f891985f683f95a4b12811b68e58b080f5a"}, - {file = "bitarray-2.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:3055720afdcfd7e8f630fa16db7bed7e55c9d0a1f4756195e3b250e203f3b436"}, - {file = "bitarray-2.9.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:72bf17d0e7d8a4f645655a07999d23e42472cbf2100b8dad7ce26586075241d7"}, - {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cfd332b5f1ad8c4dc3cc79ecef33c19b42d8d8e6a39fd5c9ecb5855be0b9723"}, - {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5b466ef1e48f25621c9d27e95deb5e33b8656827ed8aa530b972de73870bd1f"}, - {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:938cf26fdaf4d0adfac82d830c025523c5d36ddead0470b735286028231c1784"}, - {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0f766669e768ef9a2b23ecfa710b38b6a48da3f91755113c79320b207ae255d"}, - {file = "bitarray-2.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6337c0c64044f35ddfb241143244aac707a68f34ae31a71dad115f773ccc8b"}, - {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:731b59540167f8b2b20f69f487ecee2339fc4657059906a16cb51acac17f89c3"}, - {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:4feed0539a9d6432361fc4d3820eea3a81fa631d542f166cf8430aad81a971da"}, - {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:eb65c96a42e73f35175ec738d67992ffdf054c20abee3933cfcfa2343fa1187d"}, - {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:4f40ceac94d182de6135759d81289683ff3e4cf0da709bc5826a7fe00d754114"}, - {file = "bitarray-2.9.3-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:5b29f7844080a281635a231a37e99f0bd6f567af6cf19f4f6d212137f99a9cdf"}, - {file = "bitarray-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:947cf522a3b339b73114d12417fd848fa01303dbaa7883ced4c87688dba5637c"}, - {file = "bitarray-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:ea794ea60d514d68777a87a74106110db7a4bbc2c46720e67010e3071afefb95"}, - {file = "bitarray-2.9.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c7bc7cb79dcac8bdce23b305e671c06eaeffb012fa065b8c33bc51df7e1733f0"}, - {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6380ad0f929ad9220abadd1c9b7234271c4b6ea9c753a88611d489e93a8f2e"}, - {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05f4e2451e2ad450b41ede8440e52c1fd798e81027e1dc2256292ec0787d3bf1"}, - {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7267885c98138f3707c710d5b08eedef150a3e5112c760cfe1200f3366fd7064"}, - {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:976957423cb41df8fe0eb811dbb53d8c5ab1ca3beec7a3ca7ff679be44a72714"}, - {file = "bitarray-2.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0ec5141a69f73ed6ff17ea7344d5cc166e087095bfe3661dbb42b519e76aa16"}, - {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:218a1b7c0652a3c1020f903ded0f9768c3719fb6d43a6e9d346e985292992d35"}, - {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:cf0c9ebf2df280794244e1e12ed626357506ddaa2f0d6f69efe493ae7bbf4bf7"}, - {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:c450a04a7e091b57d4c0bd1531648522cd0ef26913ad0e5dea0432ea29b0e5c1"}, - {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:a212eb89a50e32ef4969387e44a7410447dc59587615e3966d090edc338a1b85"}, - {file = "bitarray-2.9.3-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:4269232026212ee6b73379b88a578107a6b36a6182307a49d5509686c7495261"}, - {file = "bitarray-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:8a0fb358e6a43f216c3fb0871e2ac14c16563aec363c23bc2fbbb18f6201285d"}, - {file = "bitarray-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:a8368774cdc737eec8fce6f28d0abc095fbc0edccf8fab8d29fddc264b68def9"}, - {file = "bitarray-2.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7d0724a4fef6ded914075a3385ea2d05afdeed567902f83490ed4e7e7e75d9bf"}, - {file = "bitarray-2.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0e11b37c6dff6f41ebc49914628824ceb8c8d6ebd0fda2ebe3c0fe0c63e8621e"}, - {file = "bitarray-2.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:085f4081d72c7468f82f722a9f113e03a1f7a4c132ef4c2a4e680c5d78b7db00"}, - {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b530b5fbed2900634fbc43f546e384abd72ad9c49795ff5bd6a93cac1aa9c4d8"}, - {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09ff88e4385967571146fb0d270442de39393d44198f4d108f3350cfd6486f0b"}, - {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344bb212ddf87db4976a6711d274660a5d887da4fd3faafcdaa092152f85a6d"}, - {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc569c96b990f92fd5946d5b50501fee48b01a116a286d1de7961ebd9c6f06f3"}, - {file = "bitarray-2.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2fbbe7938ef8a7abe3e8519fa0578b51d2787f7171d3144e7d373551b5851fd"}, - {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0b5912fab904507b47217509b01aa903d7f98b6e725e490a7f01661f4d9a4fa7"}, - {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:0c836ccfca9cf60927256738ef234dfe500565492eff269610cdd1bca56801d0"}, - {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:af0e4441ebf51c18fc450962f1e201c96f444d63b17cc8dcf7c0b05111bd4486"}, - {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:9e9b57175fb6fe76d7ddd0647e06a25f6e23f4b54b5febf337c5a840ab37dc3b"}, - {file = "bitarray-2.9.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:7f7de81721ae9492926bd067007ac974692182bb83fc8f0ba330a67f37a018bd"}, - {file = "bitarray-2.9.3-cp38-cp38-win32.whl", hash = "sha256:4beafb6b6e344385480df6611fdebfcb3579bbb40636ce1ddf5e72fb744e095f"}, - {file = "bitarray-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:d8eaeca98900bd6f06a29cdef57999813a67d314f661d14901d71e04f4cf9f00"}, - {file = "bitarray-2.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:413965d9d384aef90e58b959f4a39f1d5060b145c26080297b7b4cf23cf38faa"}, - {file = "bitarray-2.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2fbb56f2bb89c3a15304a6c0ea56013dc340a98337d9bbd7fc5c21451dc05f8c"}, - {file = "bitarray-2.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b8a84f39f7885627711473872d8fc58fc7a0a1e4ecd9ddf42daf9a3643432742"}, - {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45147a9c8580e857c1344d15bd49d2b4387777bd582a2ede11be2ba740653f28"}, - {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed255423dc60c6b2d5c0d90c13dea2962a31929767fdf1c525ab3210269e75c5"}, - {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f5bd02671ea5c4ad52bbfe0e8e8197b6e8fa85dec1e93a4a05448c19354cc65"}, - {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1c99c58f044549c93fb6d4cda22678deccaed19845eaa2e6917b5b7ca058f2d"}, - {file = "bitarray-2.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:921ee87681e32e17d1849e11c96eb6a8a7edaa1269dd26831013daf8546bde05"}, - {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2ed97d8ec40c4658d9f9aa8f26cb473f44fa1dbccba3fa3fbe4a102e38c6a8d7"}, - {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d7f7db37edb9c50c9aad6a18f2e87dd7dc5ff2a33406821804a03263fedb2ca"}, - {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:292f726cdb9efc744ed0a1d7453c44151526648148a28d9a2495cc7c7b2c62a8"}, - {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2cc94784238782a9376f307b1aa9a85ce77b6eded9f82d2fe062db7fdb02c645"}, - {file = "bitarray-2.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5051436b1d318f6ce0df3b2f8a60bfa66a54c1d9e8719d6cb6b448140e7061f2"}, - {file = "bitarray-2.9.3-cp39-cp39-win32.whl", hash = "sha256:a3d436c686ce59fd0b93438ed2c0e1d3e1716e56bce64b874d05b9f49f1ca5d1"}, - {file = "bitarray-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:f168fc45664266a560f2cb28a327041b7f69d4a7faad8ab89e0a1dd7c270a70d"}, - {file = "bitarray-2.9.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ae36787299cff41f212aee33cfe1defee13979a41552665a412b6ca3fa8f7eb8"}, - {file = "bitarray-2.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42afe48abb8eeb386d93e7f1165ace1dd027f136a8a31edd2b20bc57a0c071d7"}, - {file = "bitarray-2.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451ceecdb86bb95ae101b0d65c8c4524d692ae3666662fef8c89877ce17748c5"}, - {file = "bitarray-2.9.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4d67d3e3de2aede737b12cd75a84963700c941b77b579c14bd05517e05d7a9f"}, - {file = "bitarray-2.9.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2406d13ded84049b4238815a5821e44d6f58ba00fbb6b705b6ef8ccd88be8f03"}, - {file = "bitarray-2.9.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0db944fc2a048020fc940841ef46c0295b045d45a5a582cba69f78962a49a384"}, - {file = "bitarray-2.9.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25c603f141171a7d108773d5136d14e572c473e4cdb3fb464c39c8a138522eb2"}, - {file = "bitarray-2.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86c06b02705305cab0914d209caa24effda81316e2f2555a71a9aa399b75c5a5"}, - {file = "bitarray-2.9.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ddda45b24a802eaaca8f794e6267ff2b62de5fe7b900b76d6f662d95192bebf"}, - {file = "bitarray-2.9.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:81490623950d04870c6dd4d7e6df2eb68dd04eca8bec327895ebee8bbe0cc3c7"}, - {file = "bitarray-2.9.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a9e69ac6a514cc574891c24a50847022dac2fef8c3f4df530f92820a07337755"}, - {file = "bitarray-2.9.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:545c695ee69d26b41351ced4c76244d8b6225669fc0af3652ff8ed5a6b28325d"}, - {file = "bitarray-2.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbb2e6daabd2a64d091ac7460b0c5c5f9268199ae9a8ce32737cf5273987f1fa"}, - {file = "bitarray-2.9.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a969e5cf63144b944ee8d0a0739f53ef1ae54725b5e01258d690a8995d880526"}, - {file = "bitarray-2.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:73bbb9301ac9000f869c51db2cc5fcc6541985d3fcdcfe6e02f90c9e672a00be"}, - {file = "bitarray-2.9.3-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c07e346926488a85a48542d898f4168f3587ec42379fef0d18be301e08a3f27"}, - {file = "bitarray-2.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a26d8a14cd8ee496306f2afac34833502dd1ae826355af309333b6f252b23fe"}, - {file = "bitarray-2.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cef148ed37c892395ca182d6a235524165a9f765f4283d0a1ced891e7c43c67a"}, - {file = "bitarray-2.9.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94f35a8f0c8a50ee98a8bef9a070d0b68ecf623f20a2148cc039aba5557346a6"}, - {file = "bitarray-2.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b03207460daae828e2743874c84264e8d96a8c6156490279092b624cd5d2de08"}, - {file = "bitarray-2.9.3.tar.gz", hash = "sha256:9eff55cf189b0c37ba97156a00d640eb7392db58a8049be6f26ff2712b93fa89"}, -] - -[[package]] -name = "black" -version = "23.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "black-23.1.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:b6a92a41ee34b883b359998f0c8e6eb8e99803aa8bf3123bf2b2e6fec505a221"}, - {file = "black-23.1.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:57c18c5165c1dbe291d5306e53fb3988122890e57bd9b3dcb75f967f13411a26"}, - {file = "black-23.1.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:9880d7d419bb7e709b37e28deb5e68a49227713b623c72b2b931028ea65f619b"}, - {file = "black-23.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6663f91b6feca5d06f2ccd49a10f254f9298cc1f7f49c46e498a0771b507104"}, - {file = "black-23.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9afd3f493666a0cd8f8df9a0200c6359ac53940cbde049dcb1a7eb6ee2dd7074"}, - {file = "black-23.1.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:bfffba28dc52a58f04492181392ee380e95262af14ee01d4bc7bb1b1c6ca8d27"}, - {file = "black-23.1.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c1c476bc7b7d021321e7d93dc2cbd78ce103b84d5a4cf97ed535fbc0d6660648"}, - {file = "black-23.1.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:382998821f58e5c8238d3166c492139573325287820963d2f7de4d518bd76958"}, - {file = "black-23.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bf649fda611c8550ca9d7592b69f0637218c2369b7744694c5e4902873b2f3a"}, - {file = "black-23.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:121ca7f10b4a01fd99951234abdbd97728e1240be89fde18480ffac16503d481"}, - {file = "black-23.1.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:a8471939da5e824b891b25751955be52ee7f8a30a916d570a5ba8e0f2eb2ecad"}, - {file = "black-23.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8178318cb74f98bc571eef19068f6ab5613b3e59d4f47771582f04e175570ed8"}, - {file = "black-23.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a436e7881d33acaf2536c46a454bb964a50eff59b21b51c6ccf5a40601fbef24"}, - {file = "black-23.1.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:a59db0a2094d2259c554676403fa2fac3473ccf1354c1c63eccf7ae65aac8ab6"}, - {file = "black-23.1.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:0052dba51dec07ed029ed61b18183942043e00008ec65d5028814afaab9a22fd"}, - {file = "black-23.1.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:49f7b39e30f326a34b5c9a4213213a6b221d7ae9d58ec70df1c4a307cf2a1580"}, - {file = "black-23.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:162e37d49e93bd6eb6f1afc3e17a3d23a823042530c37c3c42eeeaf026f38468"}, - {file = "black-23.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b70eb40a78dfac24842458476135f9b99ab952dd3f2dab738c1881a9b38b753"}, - {file = "black-23.1.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:a29650759a6a0944e7cca036674655c2f0f63806ddecc45ed40b7b8aa314b651"}, - {file = "black-23.1.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:bb460c8561c8c1bec7824ecbc3ce085eb50005883a6203dcfb0122e95797ee06"}, - {file = "black-23.1.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c91dfc2c2a4e50df0026f88d2215e166616e0c80e86004d0003ece0488db2739"}, - {file = "black-23.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a951cc83ab535d248c89f300eccbd625e80ab880fbcfb5ac8afb5f01a258ac9"}, - {file = "black-23.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0680d4380db3719ebcfb2613f34e86c8e6d15ffeabcf8ec59355c5e7b85bb555"}, - {file = "black-23.1.0-py3-none-any.whl", hash = "sha256:7a0f701d314cfa0896b9001df70a530eb2472babb76086344e688829efd97d32"}, - {file = "black-23.1.0.tar.gz", hash = "sha256:b0bd97bea8903f5a2ba7219257a44e3f1f9d00073d6cc1add68f0beec69692ac"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "borsh-construct" -version = "0.1.0" -description = "Python implementation of Borsh serialization, built on the Construct library." -optional = false -python-versions = ">=3.8.3,<4.0.0" -groups = ["main"] -files = [ - {file = "borsh-construct-0.1.0.tar.gz", hash = "sha256:c916758ceba70085d8f456a1cc26991b88cb64233d347767766473b651b37263"}, - {file = "borsh_construct-0.1.0-py3-none-any.whl", hash = "sha256:f584c791e2a03f8fc36e6c13011a27bcaf028c9c54ba89cd70f485a7d1c687ed"}, -] - -[package.dependencies] -construct-typing = ">=0.5.1,<0.6.0" -sumtypes = ">=0.1a5,<0.2" - -[[package]] -name = "cached-property" -version = "2.0.1" -description = "A decorator for caching properties in classes." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cached_property-2.0.1-py3-none-any.whl", hash = "sha256:f617d70ab1100b7bcf6e42228f9ddcb78c676ffa167278d9f730d1c2fba69ccb"}, - {file = "cached_property-2.0.1.tar.gz", hash = "sha256:484d617105e3ee0e4f1f58725e72a8ef9e93deee462222dbd51cd91230897641"}, -] - -[[package]] -name = "cachetools" -version = "4.2.4" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = "~=3.5" -groups = ["main"] -files = [ - {file = "cachetools-4.2.4-py3-none-any.whl", hash = "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1"}, - {file = "cachetools-4.2.4.tar.gz", hash = "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693"}, -] - -[[package]] -name = "certifi" -version = "2025.1.31" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.4.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, -] - -[[package]] -name = "ckzg" -version = "1.0.2" -description = "Python bindings for C-KZG-4844" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "ckzg-1.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bdd082bc0f2a595e3546658ecbe1ff78fe65b0ab7e619a8197a62d94f46b5b46"}, - {file = "ckzg-1.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:50ca4af4e2f1a1e8b0a7e97b3aef39dedbb0d52d90866ece424f13f8df1b5972"}, - {file = "ckzg-1.0.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e9dc671b0a307ea65d0a216ca496c272dd3c1ed890ddc2a306da49b0d8ffc83"}, - {file = "ckzg-1.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d95e97a0d0f7758119bb905fb5688222b1556de465035614883c42fe4a047d1f"}, - {file = "ckzg-1.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27261672154cbd477d84d289845b0022fbdbe2ba45b7a2a2051c345fa04c8334"}, - {file = "ckzg-1.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c16d5ee1ddbbbad0367ff970b3ec9f6d1879e9f928023beda59ae9e16ad99e4c"}, - {file = "ckzg-1.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:09043738b029bdf4fdc82041b395cfc6f5b5cf63435e5d4d685d24fd14c834d3"}, - {file = "ckzg-1.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3c0afa232d2312e3101aaddb6971b486b0038a0f9171500bc23143f5749eff55"}, - {file = "ckzg-1.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:96e8281b6d58cf91b9559e1bd38132161d63467500838753364c68e825df2e2c"}, - {file = "ckzg-1.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b874167de1d6de72890a2ad5bd9aa7adbddc41c3409923b59cf4ef27f83f79da"}, - {file = "ckzg-1.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d2ccd68b0743e20e853e31a08da490a8d38c7f12b9a0c4ee63ef5afa0dc2427"}, - {file = "ckzg-1.0.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e8d534ddbe785c44cf1cd62ee32d78b4310d66dd70e42851f5468af655b81f5"}, - {file = "ckzg-1.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c732cda00c76b326f39ae97edfc6773dd231b7c77288b38282584a7aee77c3a7"}, - {file = "ckzg-1.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abc5a27284db479ead4c053ff086d6e222914f1b0aa08b80eabfa116dbed4f7a"}, - {file = "ckzg-1.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6bd5006cb3e802744309450183087a6594d50554814eee19065f7064dff7b05"}, - {file = "ckzg-1.0.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3594470134eda7adf2813ad3f1da55ced98c8a393262f47ce3890c5afa05b23e"}, - {file = "ckzg-1.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fea56f39e48b60c1ff6f751c47489e353d1bd95cae65c429cf5f87735d794431"}, - {file = "ckzg-1.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:f769eb2e1056ca396462460079f6849c778f58884bb24b638ff7028dd2120b65"}, - {file = "ckzg-1.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e3cb2f8c767aee57e88944f90848e8689ce43993b9ff21589cfb97a562208fe7"}, - {file = "ckzg-1.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b29889f5bc5db530f766871c0ff4133e7270ecf63aaa3ca756d3b2731980802"}, - {file = "ckzg-1.0.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfcc70fb76b3d36125d646110d5001f2aa89c1c09ff5537a4550cdb7951f44d4"}, - {file = "ckzg-1.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ca8a256cdd56d06bc5ef24caac64845240dbabca402c5a1966d519b2514b4ec"}, - {file = "ckzg-1.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ea91b0236384f93ad1df01d530672f09e254bd8c3cf097ebf486aebb97f6c8c"}, - {file = "ckzg-1.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:65311e72780105f239d1d66512629a9f468b7c9f2609b8567fc68963ac638ef9"}, - {file = "ckzg-1.0.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0d7600ce7a73ac41d348712d0c1fe5e4cb6caa329377064cfa3a6fd8fbffb410"}, - {file = "ckzg-1.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:19893ee7bd7da8688382cb134cb9ee7bce5c38e3a9386e3ed99bb010487d2d17"}, - {file = "ckzg-1.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:c3e1a9a72695e777497e95bb2213316a1138f82d1bb5d67b9c029a522d24908e"}, - {file = "ckzg-1.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a2f59da9cb82b6a4be615f2561a255731eededa7ecd6ba4b2f2dedfc918ef137"}, - {file = "ckzg-1.0.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c915e1f2ef51657c3255d8b1e2aea6e0b93348ae316b2b79eaadfb17ad8f514e"}, - {file = "ckzg-1.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcc0d2031fcabc4be37e9e602c926ef9347238d2f58c1b07e0c147f60b9e760b"}, - {file = "ckzg-1.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cdaad2745425d7708e76e8e56a52fdaf5c5cc1cfefd5129d24ff8dbe06a012d"}, - {file = "ckzg-1.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1ec775649daade1b93041aac9c1660c2ad9828b57ccd2eeb5a3074d8f05e544a"}, - {file = "ckzg-1.0.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:02f9cc3e38b3702ec5895a1ebf927fd02b8f5c2f93c7cb9e438581b5b74472c8"}, - {file = "ckzg-1.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0e816af31951b5e94e6bc069f21fe783427c190526e0437e16c4488a34ddcacc"}, - {file = "ckzg-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:651ba33ee2d7fefff14ca519a72996b733402f8b043fbfef12d5fe2a442d86d8"}, - {file = "ckzg-1.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:489763ad92e2175fb6ab455411f03ec104c630470d483e11578bf2e00608f283"}, - {file = "ckzg-1.0.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69e1376284e9a5094d7c4d3e552202d6b32a67c5acc461b0b35718d8ec5c7363"}, - {file = "ckzg-1.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb9d0b09ca1bdb5955b626d6645f811424ae0fcab47699a1a938a3ce0438c25f"}, - {file = "ckzg-1.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d87a121ace8feb6c9386f247e7e36ef55e584fc8a6b1bc2c60757a59c1efe364"}, - {file = "ckzg-1.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:97c27153fab853f017fed159333b27beeb2e0da834c92c9ecdc26d0e5c3983b3"}, - {file = "ckzg-1.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b26799907257c39471cb3665f66f7630797140131606085c2c94a7094ab6ddf2"}, - {file = "ckzg-1.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:283a40c625222560fda3dcb912b666f7d50f9502587b73c4358979f519f1c961"}, - {file = "ckzg-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:5f029822d27c52b9c3dbe5706408b099da779f10929be0422a09a34aa026a872"}, - {file = "ckzg-1.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edaea8fb50b01c6c19768d9305ad365639a8cd804754277d5108dcae4808f00b"}, - {file = "ckzg-1.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27be65c88d5d773a30e6f198719cefede7e25cad807384c3d65a09c11616fc9d"}, - {file = "ckzg-1.0.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9ac729c5c6f3d2c030c0bc8c9e10edc253e36f002cfe227292035009965d349"}, - {file = "ckzg-1.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1528bc2b95aac6d184a90b023602c40d7b11b577235848c1b5593c00cf51d37"}, - {file = "ckzg-1.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071dc7fc179316ce1bfabaa056156e4e84f312c4560ab7b9529a3b9a84019df3"}, - {file = "ckzg-1.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:895044069de7010be6c7ee703f03fd7548267a0823cf60b9dd26ec50267dd9e8"}, - {file = "ckzg-1.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ed8c99cd3d9af596470e0481fd58931007288951719bad026f0dd486dd0ec11"}, - {file = "ckzg-1.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74d87eafe561d4bfb544a4f3419d26c56ad7de00f39789ef0fdb09515544d12e"}, - {file = "ckzg-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:54d71e5ca416bd51c543f9f51e426e6792f8a0280b83aef92faad1b826f401ea"}, - {file = "ckzg-1.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:da2d9988781a09a4577ee7ea8f51fe4a94b4422789a523164f5ba3118566ad41"}, - {file = "ckzg-1.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d9e030af7d6acdcb356fddfb095048bc8e880fe4cd70ff2206c64f33bf384a0d"}, - {file = "ckzg-1.0.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:145ae31c3d499d1950567bd636dc5b24292b600296b9deb5523bc20d8f7b51c3"}, - {file = "ckzg-1.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d81e68e84d80084da298471ad5eaddfcc1cf73545cb24e9453550c8186870982"}, - {file = "ckzg-1.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c67064bbbeba1a6892c9c80b3d0c2a540ff48a5ca5356fdb2a8d998b264e43e6"}, - {file = "ckzg-1.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:99694917eb6decefc0d330d9887a89ea770824b2fa76eb830bab5fe57ea5c20c"}, - {file = "ckzg-1.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fca227ce0ce3427254a113fdb3aed5ecd99c1fc670cb0c60cc8a2154793678e4"}, - {file = "ckzg-1.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a66a690d3d1801085d11de6825df47a99b465ff32dbe90be4a3c9f43c577da96"}, - {file = "ckzg-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:272adfe471380d10e4a0e1639d877e504555079a60233dd82249c799b15be81e"}, - {file = "ckzg-1.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f37be0054ebb4b8ac6e6d5267290b239b09e7ddc611776051b4c3c4032d161ba"}, - {file = "ckzg-1.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:611c03a170f0f746180eeb0cc28cdc6f954561b8eb9013605a046de86520ee6b"}, - {file = "ckzg-1.0.2-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75b2f0ab341f3c33702ce64e1c101116c7462a25686d0b1a0193ca654ad4f96e"}, - {file = "ckzg-1.0.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab29fc61fbd32096b82b02e6b18ae0d7423048d3540b7b90805b16ae10bdb769"}, - {file = "ckzg-1.0.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e43741e7453262aa3ba1754623d7864250b33751bd850dd548e3ed6bd1911093"}, - {file = "ckzg-1.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:155eacc237cb28c9eafda1c47a89e6e4550f1c2e711f2eee21e0bb2f4df75546"}, - {file = "ckzg-1.0.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31d7fbe396a51f43375e38c31bc3a96c7996882582f95f3fcfd54acfa7b3ce6"}, - {file = "ckzg-1.0.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d3d049186c9966e9140de39a9979d7adcfe22f8b02d2852c94d3c363235cc18"}, - {file = "ckzg-1.0.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88728fbd410d61bd5d655ac50b842714c38bc34ff717f73592132d28911fc88e"}, - {file = "ckzg-1.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:052d302058d72431acc9dd4a9c76854c8dfce10c698deef5252884e32a1ac7bf"}, - {file = "ckzg-1.0.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:633110a9431231664be2ad32baf10971547f18289d33967654581b9ae9c94a7e"}, - {file = "ckzg-1.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f439c9e5297ae29a700f6d55de1525e2e295dbbb7366f0974c8702fca9e536b9"}, - {file = "ckzg-1.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:94f7eb080c00c0ccbd4fafad69f0b35b624a6a229a28e11d365b60b58a072832"}, - {file = "ckzg-1.0.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f876783ec654b7b9525503c2a0a1b086e5d4f52ff65cac7e8747769b0c2e5468"}, - {file = "ckzg-1.0.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7e039800e50592580171830e788ef4a1d6bb54300d074ae9f9119e92aefc568"}, - {file = "ckzg-1.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a8cccf0070a29bc01493179db2e61220ee1a6cb17f8ea41c68a2f043ace87f"}, - {file = "ckzg-1.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f86cef801d7b0838e17b6ee2f2c9e747447d91ad1220a701baccdf7ef11a3c8"}, - {file = "ckzg-1.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2433a89af4158beddebbdd66fae95b34d40f2467bee8dc40df0333de5e616b5f"}, - {file = "ckzg-1.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c49d5dc0918ad912777720035f9820bdbb6c7e7d1898e12506d44ab3c938d525"}, - {file = "ckzg-1.0.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:331d49bc72430a3f85ea6ecb55a0d0d65f66a21d61af5783b465906a741366d5"}, - {file = "ckzg-1.0.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86627bc33bc63b8de869d7d5bfa9868619a4f3e4e7082103935c52f56c66b5"}, - {file = "ckzg-1.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab6a2ba2706b5eaa1ce6bc7c4e72970bf9587e2e0e482e5fb4df1996bccb7a40"}, - {file = "ckzg-1.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8bca5e7c38d913fabc24ad09545f78ba23cfc13e1ac8250644231729ca908549"}, - {file = "ckzg-1.0.2.tar.gz", hash = "sha256:4295acc380f8d42ebea4a4a0a68c424a322bb335a33bad05c72ead8cbb28d118"}, -] - -[[package]] -name = "cli-ui" -version = "0.18.0" -description = "Build Nice User Interfaces In The Terminal" -optional = false -python-versions = "<4.0.0,>=3.8.1" -groups = ["main"] -files = [ - {file = "cli_ui-0.18.0-py3-none-any.whl", hash = "sha256:8d9484586d8eaba9f94aebaa12aa876fabdf1a3a50bdca113b2cb739eeaf78fa"}, - {file = "cli_ui-0.18.0.tar.gz", hash = "sha256:3e6c80ada5b4b09c6701ca93daf31df8b70486c64348d1fc7f3288ef3bd0479c"}, -] - -[package.dependencies] -colorama = ">=0.4.1,<0.5.0" -tabulate = ">=0.9.0,<0.10.0" -unidecode = ">=1.3.6,<2.0.0" - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "construct" -version = "2.10.68" -description = "A powerful declarative symmetric parser/builder for binary data" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "construct-2.10.68.tar.gz", hash = "sha256:7b2a3fd8e5f597a5aa1d614c3bd516fa065db01704c72a1efaaeec6ef23d8b45"}, -] - -[package.extras] -extras = ["arrow", "cloudpickle", "enum34", "lz4", "numpy", "ruamel.yaml"] - -[[package]] -name = "construct-typing" -version = "0.5.6" -description = "Extension for the python package 'construct' that adds typing features" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "construct-typing-0.5.6.tar.gz", hash = "sha256:0dc501351cd6b308f15ec54e5fe7c0fbc07cc1530a1b77b4303062a0a93c1297"}, - {file = "construct_typing-0.5.6-py3-none-any.whl", hash = "sha256:39c948329e880564e33521cba497b21b07967c465b9c9037d6334e2cffa1ced9"}, -] - -[package.dependencies] -construct = "2.10.68" - -[[package]] -name = "cosmpy" -version = "0.9.2" -description = "A library for interacting with the cosmos networks" -optional = false -python-versions = ">=3.8,<4.0" -groups = ["main"] -files = [ - {file = "cosmpy-0.9.2-py3-none-any.whl", hash = "sha256:3591311198b08a0aa75340851ca166669974f17ffaa207a8d2cb26504fb0fa19"}, - {file = "cosmpy-0.9.2.tar.gz", hash = "sha256:0f0eb80152f28ef5ee4d846d581d2e34ba2d952900f0e3570cacb84bb376f664"}, -] - -[package.dependencies] -bech32 = "*" -ecdsa = "*" -googleapis-common-protos = "*" -grpcio = "*" -jsonschema = ">=3.2.0,<5" -protobuf = ">=4.21.6,<5.0dev" -pycryptodome = ">=3.18.0,<4.0.0" -python-dateutil = "*" -requests = "*" - -[[package]] -name = "coverage" -version = "7.6.12" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "coverage-7.6.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8"}, - {file = "coverage-7.6.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879"}, - {file = "coverage-7.6.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06097c7abfa611c91edb9e6920264e5be1d6ceb374efb4986f38b09eed4cb2fe"}, - {file = "coverage-7.6.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:220fa6c0ad7d9caef57f2c8771918324563ef0d8272c94974717c3909664e674"}, - {file = "coverage-7.6.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3688b99604a24492bcfe1c106278c45586eb819bf66a654d8a9a1433022fb2eb"}, - {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1a987778b9c71da2fc8948e6f2656da6ef68f59298b7e9786849634c35d2c3c"}, - {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cec6b9ce3bd2b7853d4a4563801292bfee40b030c05a3d29555fd2a8ee9bd68c"}, - {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ace9048de91293e467b44bce0f0381345078389814ff6e18dbac8fdbf896360e"}, - {file = "coverage-7.6.12-cp310-cp310-win32.whl", hash = "sha256:ea31689f05043d520113e0552f039603c4dd71fa4c287b64cb3606140c66f425"}, - {file = "coverage-7.6.12-cp310-cp310-win_amd64.whl", hash = "sha256:676f92141e3c5492d2a1596d52287d0d963df21bf5e55c8b03075a60e1ddf8aa"}, - {file = "coverage-7.6.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015"}, - {file = "coverage-7.6.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45"}, - {file = "coverage-7.6.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702"}, - {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0"}, - {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f"}, - {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f"}, - {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d"}, - {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba"}, - {file = "coverage-7.6.12-cp311-cp311-win32.whl", hash = "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f"}, - {file = "coverage-7.6.12-cp311-cp311-win_amd64.whl", hash = "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558"}, - {file = "coverage-7.6.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad"}, - {file = "coverage-7.6.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3"}, - {file = "coverage-7.6.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574"}, - {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985"}, - {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750"}, - {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea"}, - {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3"}, - {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a"}, - {file = "coverage-7.6.12-cp312-cp312-win32.whl", hash = "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95"}, - {file = "coverage-7.6.12-cp312-cp312-win_amd64.whl", hash = "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288"}, - {file = "coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1"}, - {file = "coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd"}, - {file = "coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9"}, - {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e"}, - {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4"}, - {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6"}, - {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3"}, - {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc"}, - {file = "coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3"}, - {file = "coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef"}, - {file = "coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e"}, - {file = "coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703"}, - {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0"}, - {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924"}, - {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b"}, - {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d"}, - {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827"}, - {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9"}, - {file = "coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3"}, - {file = "coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f"}, - {file = "coverage-7.6.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e7575ab65ca8399c8c4f9a7d61bbd2d204c8b8e447aab9d355682205c9dd948d"}, - {file = "coverage-7.6.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8161d9fbc7e9fe2326de89cd0abb9f3599bccc1287db0aba285cb68d204ce929"}, - {file = "coverage-7.6.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a1e465f398c713f1b212400b4e79a09829cd42aebd360362cd89c5bdc44eb87"}, - {file = "coverage-7.6.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f25d8b92a4e31ff1bd873654ec367ae811b3a943583e05432ea29264782dc32c"}, - {file = "coverage-7.6.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a936309a65cc5ca80fa9f20a442ff9e2d06927ec9a4f54bcba9c14c066323f2"}, - {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aa6f302a3a0b5f240ee201297fff0bbfe2fa0d415a94aeb257d8b461032389bd"}, - {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f973643ef532d4f9be71dd88cf7588936685fdb576d93a79fe9f65bc337d9d73"}, - {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:78f5243bb6b1060aed6213d5107744c19f9571ec76d54c99cc15938eb69e0e86"}, - {file = "coverage-7.6.12-cp39-cp39-win32.whl", hash = "sha256:69e62c5034291c845fc4df7f8155e8544178b6c774f97a99e2734b05eb5bed31"}, - {file = "coverage-7.6.12-cp39-cp39-win_amd64.whl", hash = "sha256:b01a840ecc25dce235ae4c1b6a0daefb2a203dba0e6e980637ee9c2f6ee0df57"}, - {file = "coverage-7.6.12-pp39.pp310-none-any.whl", hash = "sha256:7e39e845c4d764208e7b8f6a21c541ade741e2c41afabdfa1caa28687a3c98cf"}, - {file = "coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953"}, - {file = "coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2"}, -] - -[package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli ; python_full_version <= \"3.11.0a6\""] - -[[package]] -name = "cryptography" -version = "44.0.2" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] -files = [ - {file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a"}, - {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308"}, - {file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688"}, - {file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7"}, - {file = "cryptography-44.0.2-cp37-abi3-win32.whl", hash = "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79"}, - {file = "cryptography-44.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa"}, - {file = "cryptography-44.0.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9"}, - {file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23"}, - {file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922"}, - {file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4"}, - {file = "cryptography-44.0.2-cp39-abi3-win32.whl", hash = "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5"}, - {file = "cryptography-44.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6"}, - {file = "cryptography-44.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb"}, - {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41"}, - {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562"}, - {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5"}, - {file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa"}, - {file = "cryptography-44.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d"}, - {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d"}, - {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471"}, - {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615"}, - {file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390"}, - {file = "cryptography-44.0.2.tar.gz", hash = "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] -pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "cytoolz" -version = "1.0.1" -description = "Cython implementation of Toolz: High performance functional utilities" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "implementation_name == \"cpython\"" -files = [ - {file = "cytoolz-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cec9af61f71fc3853eb5dca3d42eb07d1f48a4599fa502cbe92adde85f74b042"}, - {file = "cytoolz-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:140bbd649dbda01e91add7642149a5987a7c3ccc251f2263de894b89f50b6608"}, - {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e90124bdc42ff58b88cdea1d24a6bc5f776414a314cc4d94f25c88badb3a16d1"}, - {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e74801b751e28f7c5cc3ad264c123954a051f546f2fdfe089f5aa7a12ccfa6da"}, - {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:582dad4545ddfb5127494ef23f3fa4855f1673a35d50c66f7638e9fb49805089"}, - {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7bd0618e16efe03bd12f19c2a26a27e6e6b75d7105adb7be1cd2a53fa755d8"}, - {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d74cca6acf1c4af58b2e4a89cc565ed61c5e201de2e434748c93e5a0f5c541a5"}, - {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:823a3763828d8d457f542b2a45d75d6b4ced5e470b5c7cf2ed66a02f508ed442"}, - {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:51633a14e6844c61db1d68c1ffd077cf949f5c99c60ed5f1e265b9e2966f1b52"}, - {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f3ec9b01c45348f1d0d712507d54c2bfd69c62fbd7c9ef555c9d8298693c2432"}, - {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1855022b712a9c7a5bce354517ab4727a38095f81e2d23d3eabaf1daeb6a3b3c"}, - {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9930f7288c4866a1dc1cc87174f0c6ff4cad1671eb1f6306808aa6c445857d78"}, - {file = "cytoolz-1.0.1-cp310-cp310-win32.whl", hash = "sha256:a9baad795d72fadc3445ccd0f122abfdbdf94269157e6d6d4835636dad318804"}, - {file = "cytoolz-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:ad95b386a84e18e1f6136f6d343d2509d4c3aae9f5a536f3dc96808fcc56a8cf"}, - {file = "cytoolz-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d958d4f04d9d7018e5c1850790d9d8e68b31c9a2deebca74b903706fdddd2b6"}, - {file = "cytoolz-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f445b8b731fc0ecb1865b8e68a070084eb95d735d04f5b6c851db2daf3048ab"}, - {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f546a96460a7e28eb2ec439f4664fa646c9b3e51c6ebad9a59d3922bbe65e30"}, - {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0317681dd065532d21836f860b0563b199ee716f55d0c1f10de3ce7100c78a3b"}, - {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c0ef52febd5a7821a3fd8d10f21d460d1a3d2992f724ba9c91fbd7a96745d41"}, - {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5ebaf419acf2de73b643cf96108702b8aef8e825cf4f63209ceb078d5fbbbfd"}, - {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f7f04eeb4088947585c92d6185a618b25ad4a0f8f66ea30c8db83cf94a425e3"}, - {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f61928803bb501c17914b82d457c6f50fe838b173fb40d39c38d5961185bd6c7"}, - {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d2960cb4fa01ccb985ad1280db41f90dc97a80b397af970a15d5a5de403c8c61"}, - {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2b407cc3e9defa8df5eb46644f6f136586f70ba49eba96f43de67b9a0984fd3"}, - {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8245f929144d4d3bd7b972c9593300195c6cea246b81b4c46053c48b3f044580"}, - {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e37385db03af65763933befe89fa70faf25301effc3b0485fec1c15d4ce4f052"}, - {file = "cytoolz-1.0.1-cp311-cp311-win32.whl", hash = "sha256:50f9c530f83e3e574fc95c264c3350adde8145f4f8fc8099f65f00cc595e5ead"}, - {file = "cytoolz-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:b7f6b617454b4326af7bd3c7c49b0fc80767f134eb9fd6449917a058d17a0e3c"}, - {file = "cytoolz-1.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fcb8f7d0d65db1269022e7e0428471edee8c937bc288ebdcb72f13eaa67c2fe4"}, - {file = "cytoolz-1.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:207d4e4b445e087e65556196ff472ff134370d9a275d591724142e255f384662"}, - {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21cdf6bac6fd843f3b20280a66fd8df20dea4c58eb7214a2cd8957ec176f0bb3"}, - {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a55ec098036c0dea9f3bdc021f8acd9d105a945227d0811589f0573f21c9ce1"}, - {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a13ab79ff4ce202e03ab646a2134696988b554b6dc4b71451e948403db1331d8"}, - {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2d944799026e1ff08a83241f1027a2d9276c41f7a74224cd98b7df6e03957d"}, - {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88ba85834cd523b91fdf10325e1e6d71c798de36ea9bdc187ca7bd146420de6f"}, - {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a750b1af7e8bf6727f588940b690d69e25dc47cce5ce467925a76561317eaf7"}, - {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44a71870f7eae31d263d08b87da7c2bf1176f78892ed8bdade2c2850478cb126"}, - {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8231b9abbd8e368e036f4cc2e16902c9482d4cf9e02a6147ed0e9a3cd4a9ab0"}, - {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:aa87599ccc755de5a096a4d6c34984de6cd9dc928a0c5eaa7607457317aeaf9b"}, - {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:67cd16537df51baabde3baa770ab7b8d16839c4d21219d5b96ac59fb012ebd2d"}, - {file = "cytoolz-1.0.1-cp312-cp312-win32.whl", hash = "sha256:fb988c333f05ee30ad4693fe4da55d95ec0bb05775d2b60191236493ea2e01f9"}, - {file = "cytoolz-1.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:8f89c48d8e5aec55ffd566a8ec858706d70ed0c6a50228eca30986bfa5b4da8b"}, - {file = "cytoolz-1.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6944bb93b287032a4c5ca6879b69bcd07df46f3079cf8393958cf0b0454f50c0"}, - {file = "cytoolz-1.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e027260fd2fc5cb041277158ac294fc13dca640714527219f702fb459a59823a"}, - {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88662c0e07250d26f5af9bc95911e6137e124a5c1ec2ce4a5d74de96718ab242"}, - {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309dffa78b0961b4c0cf55674b828fbbc793cf2d816277a5c8293c0c16155296"}, - {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:edb34246e6eb40343c5860fc51b24937698e4fa1ee415917a73ad772a9a1746b"}, - {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54da7a8e4348a18d45d4d5bc84af6c716d7f131113a4f1cc45569d37edff1b"}, - {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:241c679c3b1913c0f7259cf1d9639bed5084c86d0051641d537a0980548aa266"}, - {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5bfc860251a8f280ac79696fc3343cfc3a7c30b94199e0240b6c9e5b6b01a2a5"}, - {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c8edd1547014050c1bdad3ff85d25c82bd1c2a3c96830c6181521eb78b9a42b3"}, - {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b349bf6162e8de215403d7f35f8a9b4b1853dc2a48e6e1a609a5b1a16868b296"}, - {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1b18b35256219b6c3dd0fa037741b85d0bea39c552eab0775816e85a52834140"}, - {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:738b2350f340ff8af883eb301054eb724997f795d20d90daec7911c389d61581"}, - {file = "cytoolz-1.0.1-cp313-cp313-win32.whl", hash = "sha256:9cbd9c103df54fcca42be55ef40e7baea624ac30ee0b8bf1149f21146d1078d9"}, - {file = "cytoolz-1.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:90e577e08d3a4308186d9e1ec06876d4756b1e8164b92971c69739ea17e15297"}, - {file = "cytoolz-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3a509e4ac8e711703c368476b9bbce921fcef6ebb87fa3501525f7000e44185"}, - {file = "cytoolz-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a7eecab6373e933dfbf4fdc0601d8fd7614f8de76793912a103b5fccf98170cd"}, - {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e55ed62087f6e3e30917b5f55350c3b6be6470b849c6566018419cd159d2cebc"}, - {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43de33d99a4ccc07234cecd81f385456b55b0ea9c39c9eebf42f024c313728a5"}, - {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:139bed875828e1727018aa0982aa140e055cbafccb7fd89faf45cbb4f2a21514"}, - {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22c12671194b518aa8ce2f4422bd5064f25ab57f410ba0b78705d0a219f4a97a"}, - {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79888f2f7dc25709cd5d37b032a8833741e6a3692c8823be181d542b5999128e"}, - {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:51628b4eb41fa25bd428f8f7b5b74fbb05f3ae65fbd265019a0dd1ded4fdf12a"}, - {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:1db9eb7179285403d2fb56ba1ff6ec35a44921b5e2fa5ca19d69f3f9f0285ea5"}, - {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:08ab7efae08e55812340bfd1b3f09f63848fe291675e2105eab1aa5327d3a16e"}, - {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e5fdc5264f884e7c0a1711a81dff112708a64b9c8561654ee578bfdccec6be09"}, - {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:90d6a2e6ab891043ee655ec99d5e77455a9bee9e1131bdfcfb745edde81200dd"}, - {file = "cytoolz-1.0.1-cp38-cp38-win32.whl", hash = "sha256:08946e083faa5147751b34fbf78ab931f149ef758af5c1092932b459e18dcf5c"}, - {file = "cytoolz-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:a91b4e10a9c03796c0dc93e47ebe25bb41ecc6fafc3cf5197c603cf767a3d44d"}, - {file = "cytoolz-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:980c323e626ba298b77ae62871b2de7c50b9d7219e2ddf706f52dd34b8be7349"}, - {file = "cytoolz-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:45f6fa1b512bc2a0f2de5123db932df06c7f69d12874fe06d67772b2828e2c8b"}, - {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93f42d9100c415155ad1f71b0de362541afd4ac95e3153467c4c79972521b6b"}, - {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a76d20dec9c090cdf4746255bbf06a762e8cc29b5c9c1d138c380bbdb3122ade"}, - {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:239039585487c69aa50c5b78f6a422016297e9dea39755761202fb9f0530fe87"}, - {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28307640ca2ab57b9fbf0a834b9bf563958cd9e038378c3a559f45f13c3c541"}, - {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:454880477bb901cee3a60f6324ec48c95d45acc7fecbaa9d49a5af737ded0595"}, - {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:902115d1b1f360fd81e44def30ac309b8641661150fcbdde18ead446982ada6a"}, - {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e68e6b38473a3a79cee431baa22be31cac39f7df1bf23eaa737eaff42e213883"}, - {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:32fba3f63fcb76095b0a22f4bdcc22bc62a2bd2d28d58bf02fd21754c155a3ec"}, - {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0724ba4cf41eb40b6cf75250820ab069e44bdf4183ff78857aaf4f0061551075"}, - {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c42420e0686f887040d5230420ed44f0e960ccbfa29a0d65a3acd9ca52459209"}, - {file = "cytoolz-1.0.1-cp39-cp39-win32.whl", hash = "sha256:4ba8b16358ea56b1fe8e637ec421e36580866f2e787910bac1cf0a6997424a34"}, - {file = "cytoolz-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:92d27f84bf44586853d9562bfa3610ecec000149d030f793b4cb614fd9da1813"}, - {file = "cytoolz-1.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:83d19d55738ad9c60763b94f3f6d3c6e4de979aeb8d76841c1401081e0e58d96"}, - {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f112a71fad6ea824578e6393765ce5c054603afe1471a5c753ff6c67fd872d10"}, - {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a515df8f8aa6e1eaaf397761a6e4aff2eef73b5f920aedf271416d5471ae5ee"}, - {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92c398e7b7023460bea2edffe5fcd0a76029580f06c3f6938ac3d198b47156f3"}, - {file = "cytoolz-1.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3237e56211e03b13df47435b2369f5df281e02b04ad80a948ebd199b7bc10a47"}, - {file = "cytoolz-1.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba0d1da50aab1909b165f615ba1125c8b01fcc30d606c42a61c42ea0269b5e2c"}, - {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25b6e8dec29aa5a390092d193abd673e027d2c0b50774ae816a31454286c45c7"}, - {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36cd6989ebb2f18fe9af8f13e3c61064b9f741a40d83dc5afeb0322338ad25f2"}, - {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47394f8ab7fca3201f40de61fdeea20a2baffb101485ae14901ea89c3f6c95d"}, - {file = "cytoolz-1.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d00ac423542af944302e034e618fb055a0c4e87ba704cd6a79eacfa6ac83a3c9"}, - {file = "cytoolz-1.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a5ca923d1fa632f7a4fb33c0766c6fba7f87141a055c305c3e47e256fb99c413"}, - {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058bf996bcae9aad3acaeeb937d42e0c77c081081e67e24e9578a6a353cb7fb2"}, - {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69e2a1f41a3dad94a17aef4a5cc003323359b9f0a9d63d4cc867cb5690a2551d"}, - {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67daeeeadb012ec2b59d63cb29c4f2a2023b0c4957c3342d354b8bb44b209e9a"}, - {file = "cytoolz-1.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:54d3d36bbf0d4344d1afa22c58725d1668e30ff9de3a8f56b03db1a6da0acb11"}, - {file = "cytoolz-1.0.1.tar.gz", hash = "sha256:89cc3161b89e1bb3ed7636f74ed2e55984fd35516904fc878cae216e42b2c7d6"}, -] - -[package.dependencies] -toolz = ">=0.8.0" - -[package.extras] -cython = ["cython"] - -[[package]] -name = "distlib" -version = "0.3.9" -description = "Distribution utilities" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, - {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, -] - -[[package]] -name = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "disutils" -version = "1.4.32.post2" -description = "disutils is a very useful library made to be used with discord.py" -optional = false -python-versions = ">= 3.6" -groups = ["main"] -files = [ - {file = "disutils-1.4.32.post2-py3-none-any.whl", hash = "sha256:fbd5402027e3ad99402d889b79f76f6e045bbdb7aa6a4a43abf7a136e46cd019"}, - {file = "disutils-1.4.32.post2.tar.gz", hash = "sha256:29529e3436a95e9863934d6ce3f20335860c7fdffe5e6f95b5ceaeb3ffea4574"}, -] - -[package.dependencies] -aiohttp = "*" -asyncio = "*" - -[package.extras] -docs = ["Sphinx (==4.5.0)", "py-cord (==2.0.0b7)", "sphinx-rtd-theme (==1.0.0)", "sphinxcontrib-napoleon (==0.7)", "sphinxcontrib-trio (==1.1.2)", "typing-extensions"] -voice = ["youtube-dl"] - -[[package]] -name = "docker" -version = "6.1.2" -description = "A Python library for the Docker Engine API." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "docker-6.1.2-py3-none-any.whl", hash = "sha256:134cd828f84543cbf8e594ff81ca90c38288df3c0a559794c12f2e4b634ea19e"}, - {file = "docker-6.1.2.tar.gz", hash = "sha256:dcc088adc2ec4e7cfc594e275d8bd2c9738c56c808de97476939ef67db5af8c2"}, -] - -[package.dependencies] -packaging = ">=14.0" -paramiko = {version = ">=2.4.3", optional = true, markers = "extra == \"ssh\""} -pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} -requests = ">=2.26.0" -urllib3 = ">=1.26.0" -websocket-client = ">=0.32.0" - -[package.extras] -ssh = ["paramiko (>=2.4.3)"] - -[[package]] -name = "dockerpty" -version = "0.4.1" -description = "Python library to use the pseudo-tty of a docker container" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "dockerpty-0.4.1.tar.gz", hash = "sha256:69a9d69d573a0daa31bcd1c0774eeed5c15c295fe719c61aca550ed1393156ce"}, -] - -[package.dependencies] -six = ">=1.3.0" - -[[package]] -name = "docopt" -version = "0.6.2" -description = "Pythonic argument parser, that will make you smile" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, -] - -[[package]] -name = "docstring-parser-fork" -version = "0.0.12" -description = "Parse Python docstrings in reST, Google and Numpydoc format" -optional = false -python-versions = "<4.0,>=3.7" -groups = ["main"] -files = [ - {file = "docstring_parser_fork-0.0.12-py3-none-any.whl", hash = "sha256:55d7cbbc8b367655efd64372b9a0b33a49bae930a8ddd5cdc4c6112312e28a87"}, - {file = "docstring_parser_fork-0.0.12.tar.gz", hash = "sha256:b44c5e0be64ae80f395385f01497d381bd094a57221fd9ff020987d06857b2a0"}, -] - -[[package]] -name = "ecdsa" -version = "0.16.1" -description = "ECDSA cryptographic signature library (pure python)" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] -files = [ - {file = "ecdsa-0.16.1-py2.py3-none-any.whl", hash = "sha256:881fa5e12bb992972d3d1b3d4dfbe149ab76a89f13da02daa5ea1ec7dea6e747"}, - {file = "ecdsa-0.16.1.tar.gz", hash = "sha256:cfc046a2ddd425adbd1a78b3c46f0d1325c657811c0f45ecc3a0a6236c1e50ff"}, -] - -[package.dependencies] -six = ">=1.9.0" - -[package.extras] -gmpy = ["gmpy"] -gmpy2 = ["gmpy2"] - -[[package]] -name = "eth-abi" -version = "5.1.0" -description = "eth_abi: Python utilities for working with Ethereum ABI definitions, especially encoding and decoding" -optional = false -python-versions = "<4,>=3.8" -groups = ["main"] -files = [ - {file = "eth_abi-5.1.0-py3-none-any.whl", hash = "sha256:84cac2626a7db8b7d9ebe62b0fdca676ab1014cc7f777189e3c0cd721a4c16d8"}, - {file = "eth_abi-5.1.0.tar.gz", hash = "sha256:33ddd756206e90f7ddff1330cc8cac4aa411a824fe779314a0a52abea2c8fc14"}, -] - -[package.dependencies] -eth-typing = ">=3.0.0" -eth-utils = ">=2.0.0" -parsimonious = ">=0.10.0,<0.11.0" - -[package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["eth-hash[pycryptodome]", "hypothesis (>=4.18.2,<5.0.0)", "pytest (>=7.0.0)", "pytest-pythonpath (>=0.7.1)", "pytest-timeout (>=2.0.0)", "pytest-xdist (>=2.4.0)"] -tools = ["hypothesis (>=4.18.2,<5.0.0)"] - -[[package]] -name = "eth-account" -version = "0.8.0" -description = "eth-account: Sign Ethereum transactions and messages with local private keys" -optional = false -python-versions = ">=3.6, <4" -groups = ["main"] -files = [ - {file = "eth-account-0.8.0.tar.gz", hash = "sha256:ccb2d90a16c81c8ea4ca4dc76a70b50f1d63cea6aff3c5a5eddedf9e45143eca"}, - {file = "eth_account-0.8.0-py3-none-any.whl", hash = "sha256:0ccc0edbb17021004356ae6e37887528b6e59e6ae6283f3917b9759a5887203b"}, -] - -[package.dependencies] -bitarray = ">=2.4.0,<3" -eth-abi = ">=3.0.1" -eth-keyfile = ">=0.6.0,<0.7.0" -eth-keys = ">=0.4.0,<0.5" -eth-rlp = ">=0.3.0,<1" -eth-utils = ">=2.0.0,<3" -hexbytes = ">=0.1.0,<1" -rlp = ">=1.0.0,<4" - -[package.extras] -dev = ["Sphinx (>=1.6.5,<5)", "black (>=22,<23)", "bumpversion (>=0.5.3,<1)", "coverage", "flake8 (==3.7.9)", "hypothesis (>=4.18.0,<5)", "ipython", "isort (>=4.2.15,<5)", "jinja2 (>=3.0.0,<3.1.0)", "mypy (==0.910)", "pydocstyle (>=5.0.0,<6)", "pytest (>=6.2.5,<7)", "pytest-watch (>=4.1.0,<5)", "pytest-xdist", "sphinx-rtd-theme (>=0.1.9,<1)", "towncrier (>=21,<22)", "tox (==3.25.0)", "twine", "wheel"] -doc = ["Sphinx (>=1.6.5,<5)", "jinja2 (>=3.0.0,<3.1.0)", "sphinx-rtd-theme (>=0.1.9,<1)", "towncrier (>=21,<22)"] -lint = ["black (>=22,<23)", "flake8 (==3.7.9)", "isort (>=4.2.15,<5)", "mypy (==0.910)", "pydocstyle (>=5.0.0,<6)"] -test = ["coverage", "hypothesis (>=4.18.0,<5)", "pytest (>=6.2.5,<7)", "pytest-xdist", "tox (==3.25.0)"] - -[[package]] -name = "eth-hash" -version = "0.7.1" -description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" -optional = false -python-versions = "<4,>=3.8" -groups = ["main"] -files = [ - {file = "eth_hash-0.7.1-py3-none-any.whl", hash = "sha256:0fb1add2adf99ef28883fd6228eb447ef519ea72933535ad1a0b28c6f65f868a"}, - {file = "eth_hash-0.7.1.tar.gz", hash = "sha256:d2411a403a0b0a62e8247b4117932d900ffb4c8c64b15f92620547ca5ce46be5"}, -] - -[package.dependencies] -pycryptodome = {version = ">=3.6.6,<4", optional = true, markers = "extra == \"pycryptodome\""} - -[package.extras] -dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] -pycryptodome = ["pycryptodome (>=3.6.6,<4)"] -pysha3 = ["pysha3 (>=1.0.0,<2.0.0) ; python_version < \"3.9\"", "safe-pysha3 (>=1.0.0) ; python_version >= \"3.9\""] -test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] - -[[package]] -name = "eth-keyfile" -version = "0.6.1" -description = "A library for handling the encrypted keyfiles used to store ethereum private keys." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "eth-keyfile-0.6.1.tar.gz", hash = "sha256:471be6e5386fce7b22556b3d4bde5558dbce46d2674f00848027cb0a20abdc8c"}, - {file = "eth_keyfile-0.6.1-py3-none-any.whl", hash = "sha256:609773a1ad5956944a33348413cad366ec6986c53357a806528c8f61c4961560"}, -] - -[package.dependencies] -eth-keys = ">=0.4.0,<0.5.0" -eth-utils = ">=2,<3" -pycryptodome = ">=3.6.6,<4" - -[package.extras] -dev = ["bumpversion (>=0.5.3,<1)", "eth-keys (>=0.4.0,<0.5.0)", "eth-utils (>=2,<3)", "flake8 (==4.0.1)", "idna (==2.7)", "pluggy (>=1.0.0,<2)", "pycryptodome (>=3.6.6,<4)", "pytest (>=6.2.5,<7)", "requests (>=2.20,<3)", "setuptools (>=38.6.0)", "tox (>=2.7.0)", "twine", "wheel"] -keyfile = ["eth-keys (>=0.4.0,<0.5.0)", "eth-utils (>=2,<3)", "pycryptodome (>=3.6.6,<4)"] -lint = ["flake8 (==4.0.1)"] -test = ["pytest (>=6.2.5,<7)"] - -[[package]] -name = "eth-keys" -version = "0.4.0" -description = "Common API for Ethereum key operations." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "eth-keys-0.4.0.tar.gz", hash = "sha256:7d18887483bc9b8a3fdd8e32ddcb30044b9f08fcb24a380d93b6eee3a5bb3216"}, - {file = "eth_keys-0.4.0-py3-none-any.whl", hash = "sha256:e07915ffb91277803a28a379418bdd1fad1f390c38ad9353a0f189789a440d5d"}, -] - -[package.dependencies] -eth-typing = ">=3.0.0,<4" -eth-utils = ">=2.0.0,<3.0.0" - -[package.extras] -coincurve = ["coincurve (>=7.0.0,<16.0.0)"] -dev = ["asn1tools (>=0.146.2,<0.147)", "bumpversion (==0.5.3)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)", "factory-boy (>=3.0.1,<3.1)", "flake8 (==3.0.4)", "hypothesis (>=5.10.3,<6.0.0)", "mypy (==0.782)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)", "tox (==3.20.0)", "twine"] -eth-keys = ["eth-typing (>=3.0.0,<4)", "eth-utils (>=2.0.0,<3.0.0)"] -lint = ["flake8 (==3.0.4)", "mypy (==0.782)"] -test = ["asn1tools (>=0.146.2,<0.147)", "eth-hash[pycryptodome] ; implementation_name == \"pypy\"", "eth-hash[pysha3] ; implementation_name == \"cpython\"", "factory-boy (>=3.0.1,<3.1)", "hypothesis (>=5.10.3,<6.0.0)", "pyasn1 (>=0.4.5,<0.5)", "pytest (==6.2.5)"] - -[[package]] -name = "eth-rlp" -version = "0.3.0" -description = "eth-rlp: RLP definitions for common Ethereum objects in Python" -optional = false -python-versions = ">=3.7, <4" -groups = ["main"] -files = [ - {file = "eth-rlp-0.3.0.tar.gz", hash = "sha256:f3263b548df718855d9a8dbd754473f383c0efc82914b0b849572ce3e06e71a6"}, - {file = "eth_rlp-0.3.0-py3-none-any.whl", hash = "sha256:e88e949a533def85c69fa94224618bbbd6de00061f4cff645c44621dab11cf33"}, -] - -[package.dependencies] -eth-utils = ">=2.0.0,<3" -hexbytes = ">=0.1.0,<1" -rlp = ">=0.6.0,<4" - -[package.extras] -dev = ["Sphinx (>=1.6.5,<2)", "bumpversion (>=0.5.3,<1)", "eth-hash[pycryptodome]", "flake8 (==3.7.9)", "ipython", "isort (>=4.2.15,<5)", "mypy (==0.770)", "pydocstyle (>=3.0.0,<4)", "pytest (>=6.2.5,<7)", "pytest-watch (>=4.1.0,<5)", "pytest-xdist", "sphinx-rtd-theme (>=0.1.9)", "towncrier (>=19.2.0,<20)", "tox (==3.14.6)", "twine", "wheel"] -doc = ["Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)", "towncrier (>=19.2.0,<20)"] -lint = ["flake8 (==3.7.9)", "isort (>=4.2.15,<5)", "mypy (==0.770)", "pydocstyle (>=3.0.0,<4)"] -test = ["eth-hash[pycryptodome]", "pytest (>=6.2.5,<7)", "pytest-xdist", "tox (==3.14.6)"] - -[[package]] -name = "eth-typing" -version = "3.5.2" -description = "eth-typing: Common type annotations for ethereum python packages" -optional = false -python-versions = ">=3.7.2, <4" -groups = ["main"] -files = [ - {file = "eth-typing-3.5.2.tar.gz", hash = "sha256:22bf051ddfaa35ff827c30090de167e5c5b8cc6d343f7f35c9b1c7553f6ab64d"}, - {file = "eth_typing-3.5.2-py3-none-any.whl", hash = "sha256:1842e628fb1ffa929b94f89a9d33caafbeb9978dc96abb6036a12bc91f1c624b"}, -] - -[package.dependencies] -typing-extensions = ">=4.0.1" - -[package.extras] -dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "types-setuptools", "wheel"] -docs = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=23)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=6.0.0)", "types-setuptools"] -test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] - -[[package]] -name = "eth-utils" -version = "2.3.1" -description = "eth-utils: Common utility functions for python code that interacts with Ethereum" -optional = false -python-versions = ">=3.7,<4" -groups = ["main"] -files = [ - {file = "eth-utils-2.3.1.tar.gz", hash = "sha256:56a969b0536d4969dcb27e580521de35abf2dbed8b1bf072b5c80770c4324e27"}, - {file = "eth_utils-2.3.1-py3-none-any.whl", hash = "sha256:614eedc5ffcaf4e6708ca39e23b12bd69526a312068c1170c773bd1307d13972"}, -] - -[package.dependencies] -cytoolz = {version = ">=0.10.1", markers = "implementation_name == \"cpython\""} -eth-hash = ">=0.3.1" -eth-typing = ">=3.0.0" -toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""} - -[package.extras] -dev = ["black (>=23)", "build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "flake8 (==3.8.3)", "hypothesis (>=4.43.0)", "ipython", "isort (>=5.11.0)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "types-setuptools", "wheel"] -docs = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=23)", "flake8 (==3.8.3)", "isort (>=5.11.0)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "types-setuptools"] -test = ["hypothesis (>=4.43.0)", "mypy (==0.971)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "types-setuptools"] - -[[package]] -name = "exceptiongroup" -version = "1.2.2" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version < \"3.11\"" -files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "filelock" -version = "3.17.0" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, - {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] - -[[package]] -name = "flask" -version = "2.1.3" -description = "A simple framework for building complex web applications." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "Flask-2.1.3-py3-none-any.whl", hash = "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"}, - {file = "Flask-2.1.3.tar.gz", hash = "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb"}, -] - -[package.dependencies] -click = ">=8.0" -itsdangerous = ">=2.0" -Jinja2 = ">=3.0" -Werkzeug = ">=2.0" - -[package.extras] -async = ["asgiref (>=3.2)"] -dotenv = ["python-dotenv"] - -[[package]] -name = "frozenlist" -version = "1.5.0" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, - {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, - {file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"}, - {file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"}, - {file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"}, - {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"}, - {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"}, - {file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"}, - {file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"}, - {file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"}, - {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"}, - {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"}, - {file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"}, - {file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"}, - {file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"}, - {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"}, - {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"}, - {file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"}, - {file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"}, - {file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"}, - {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"}, - {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"}, - {file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"}, - {file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"}, - {file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"}, - {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"}, - {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"}, - {file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"}, - {file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"}, - {file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"}, - {file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"}, - {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"}, -] - -[[package]] -name = "googleapis-common-protos" -version = "1.69.0" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "googleapis_common_protos-1.69.0-py2.py3-none-any.whl", hash = "sha256:17835fdc4fa8da1d61cfe2d4d5d57becf7c61d4112f8d81c67eaa9d7ce43042d"}, - {file = "googleapis_common_protos-1.69.0.tar.gz", hash = "sha256:5a46d58af72846f59009b9c4710425b9af2139555c71837081706b213b298187"}, -] - -[package.dependencies] -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - -[[package]] -name = "gql" -version = "3.5.0" -description = "GraphQL client for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "gql-3.5.0-py2.py3-none-any.whl", hash = "sha256:70dda5694a5b194a8441f077aa5fb70cc94e4ec08016117523f013680901ecb7"}, - {file = "gql-3.5.0.tar.gz", hash = "sha256:ccb9c5db543682b28f577069950488218ed65d4ac70bb03b6929aaadaf636de9"}, -] - -[package.dependencies] -anyio = ">=3.0,<5" -backoff = ">=1.11.1,<3.0" -graphql-core = ">=3.2,<3.3" -yarl = ">=1.6,<2.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\""] -all = ["aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] -botocore = ["botocore (>=1.21,<2)"] -dev = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] -httpx = ["httpx (>=0.23.1,<1)"] -requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)"] -test = ["aiofiles", "aiohttp (>=3.8.0,<4) ; python_version <= \"3.11\"", "aiohttp (>=3.9.0b0,<4) ; python_version > \"3.11\"", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] -test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.4.0)"] -websockets = ["websockets (>=10,<12)"] - -[[package]] -name = "graphql-core" -version = "3.2.6" -description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." -optional = false -python-versions = "<4,>=3.6" -groups = ["main"] -files = [ - {file = "graphql_core-3.2.6-py3-none-any.whl", hash = "sha256:78b016718c161a6fb20a7d97bbf107f331cd1afe53e45566c59f776ed7f0b45f"}, - {file = "graphql_core-3.2.6.tar.gz", hash = "sha256:c08eec22f9e40f0bd61d805907e3b3b1b9a320bc606e23dc145eebca07c8fbab"}, -] - -[[package]] -name = "grpcio" -version = "1.69.0" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "grpcio-1.69.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:2060ca95a8db295ae828d0fc1c7f38fb26ccd5edf9aa51a0f44251f5da332e97"}, - {file = "grpcio-1.69.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2e52e107261fd8fa8fa457fe44bfadb904ae869d87c1280bf60f93ecd3e79278"}, - {file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:316463c0832d5fcdb5e35ff2826d9aa3f26758d29cdfb59a368c1d6c39615a11"}, - {file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26c9a9c4ac917efab4704b18eed9082ed3b6ad19595f047e8173b5182fec0d5e"}, - {file = "grpcio-1.69.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90b3646ced2eae3a0599658eeccc5ba7f303bf51b82514c50715bdd2b109e5ec"}, - {file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3b75aea7c6cb91b341c85e7c1d9db1e09e1dd630b0717f836be94971e015031e"}, - {file = "grpcio-1.69.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5cfd14175f9db33d4b74d63de87c64bb0ee29ce475ce3c00c01ad2a3dc2a9e51"}, - {file = "grpcio-1.69.0-cp310-cp310-win32.whl", hash = "sha256:9031069d36cb949205293cf0e243abd5e64d6c93e01b078c37921493a41b72dc"}, - {file = "grpcio-1.69.0-cp310-cp310-win_amd64.whl", hash = "sha256:cc89b6c29f3dccbe12d7a3b3f1b3999db4882ae076c1c1f6df231d55dbd767a5"}, - {file = "grpcio-1.69.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:8de1b192c29b8ce45ee26a700044717bcbbd21c697fa1124d440548964328561"}, - {file = "grpcio-1.69.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:7e76accf38808f5c5c752b0ab3fd919eb14ff8fafb8db520ad1cc12afff74de6"}, - {file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:d5658c3c2660417d82db51e168b277e0ff036d0b0f859fa7576c0ffd2aec1442"}, - {file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5494d0e52bf77a2f7eb17c6da662886ca0a731e56c1c85b93505bece8dc6cf4c"}, - {file = "grpcio-1.69.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ed866f9edb574fd9be71bf64c954ce1b88fc93b2a4cbf94af221e9426eb14d6"}, - {file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c5ba38aeac7a2fe353615c6b4213d1fbb3a3c34f86b4aaa8be08baaaee8cc56d"}, - {file = "grpcio-1.69.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f79e05f5bbf551c4057c227d1b041ace0e78462ac8128e2ad39ec58a382536d2"}, - {file = "grpcio-1.69.0-cp311-cp311-win32.whl", hash = "sha256:bf1f8be0da3fcdb2c1e9f374f3c2d043d606d69f425cd685110dd6d0d2d61258"}, - {file = "grpcio-1.69.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb9302afc3a0e4ba0b225cd651ef8e478bf0070cf11a529175caecd5ea2474e7"}, - {file = "grpcio-1.69.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:fc18a4de8c33491ad6f70022af5c460b39611e39578a4d84de0fe92f12d5d47b"}, - {file = "grpcio-1.69.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:0f0270bd9ffbff6961fe1da487bdcd594407ad390cc7960e738725d4807b18c4"}, - {file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc48f99cc05e0698e689b51a05933253c69a8c8559a47f605cff83801b03af0e"}, - {file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e925954b18d41aeb5ae250262116d0970893b38232689c4240024e4333ac084"}, - {file = "grpcio-1.69.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87d222569273720366f68a99cb62e6194681eb763ee1d3b1005840678d4884f9"}, - {file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b62b0f41e6e01a3e5082000b612064c87c93a49b05f7602fe1b7aa9fd5171a1d"}, - {file = "grpcio-1.69.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:db6f9fd2578dbe37db4b2994c94a1d9c93552ed77dca80e1657bb8a05b898b55"}, - {file = "grpcio-1.69.0-cp312-cp312-win32.whl", hash = "sha256:b192b81076073ed46f4b4dd612b8897d9a1e39d4eabd822e5da7b38497ed77e1"}, - {file = "grpcio-1.69.0-cp312-cp312-win_amd64.whl", hash = "sha256:1227ff7836f7b3a4ab04e5754f1d001fa52a730685d3dc894ed8bc262cc96c01"}, - {file = "grpcio-1.69.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:a78a06911d4081a24a1761d16215a08e9b6d4d29cdbb7e427e6c7e17b06bcc5d"}, - {file = "grpcio-1.69.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:dc5a351927d605b2721cbb46158e431dd49ce66ffbacb03e709dc07a491dde35"}, - {file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:3629d8a8185f5139869a6a17865d03113a260e311e78fbe313f1a71603617589"}, - {file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9a281878feeb9ae26db0622a19add03922a028d4db684658f16d546601a4870"}, - {file = "grpcio-1.69.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc614e895177ab7e4b70f154d1a7c97e152577ea101d76026d132b7aaba003b"}, - {file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:1ee76cd7e2e49cf9264f6812d8c9ac1b85dda0eaea063af07292400f9191750e"}, - {file = "grpcio-1.69.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0470fa911c503af59ec8bc4c82b371ee4303ececbbdc055f55ce48e38b20fd67"}, - {file = "grpcio-1.69.0-cp313-cp313-win32.whl", hash = "sha256:b650f34aceac8b2d08a4c8d7dc3e8a593f4d9e26d86751ebf74ebf5107d927de"}, - {file = "grpcio-1.69.0-cp313-cp313-win_amd64.whl", hash = "sha256:028337786f11fecb5d7b7fa660475a06aabf7e5e52b5ac2df47414878c0ce7ea"}, - {file = "grpcio-1.69.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:b7f693db593d6bf285e015d5538bf1c86cf9c60ed30b6f7da04a00ed052fe2f3"}, - {file = "grpcio-1.69.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:8b94e83f66dbf6fd642415faca0608590bc5e8d30e2c012b31d7d1b91b1de2fd"}, - {file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:b634851b92c090763dde61df0868c730376cdb73a91bcc821af56ae043b09596"}, - {file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf5f680d3ed08c15330d7830d06bc65f58ca40c9999309517fd62880d70cb06e"}, - {file = "grpcio-1.69.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:200e48a6e7b00f804cf00a1c26292a5baa96507c7749e70a3ec10ca1a288936e"}, - {file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:45a4704339b6e5b24b0e136dea9ad3815a94f30eb4f1e1d44c4ac484ef11d8dd"}, - {file = "grpcio-1.69.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:85d347cb8237751b23539981dbd2d9d8f6e9ff90082b427b13022b948eb6347a"}, - {file = "grpcio-1.69.0-cp38-cp38-win32.whl", hash = "sha256:60e5de105dc02832dc8f120056306d0ef80932bcf1c0e2b4ca3b676de6dc6505"}, - {file = "grpcio-1.69.0-cp38-cp38-win_amd64.whl", hash = "sha256:282f47d0928e40f25d007f24eb8fa051cb22551e3c74b8248bc9f9bea9c35fe0"}, - {file = "grpcio-1.69.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:dd034d68a2905464c49479b0c209c773737a4245d616234c79c975c7c90eca03"}, - {file = "grpcio-1.69.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:01f834732c22a130bdf3dc154d1053bdbc887eb3ccb7f3e6285cfbfc33d9d5cc"}, - {file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:a7f4ed0dcf202a70fe661329f8874bc3775c14bb3911d020d07c82c766ce0eb1"}, - {file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd7ea241b10bc5f0bb0f82c0d7896822b7ed122b3ab35c9851b440c1ccf81588"}, - {file = "grpcio-1.69.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f03dc9b4da4c0dc8a1db7a5420f575251d7319b7a839004d8916257ddbe4816"}, - {file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ca71d73a270dff052fe4edf74fef142d6ddd1f84175d9ac4a14b7280572ac519"}, - {file = "grpcio-1.69.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ccbed100dc43704e94ccff9e07680b540d64e4cc89213ab2832b51b4f68a520"}, - {file = "grpcio-1.69.0-cp39-cp39-win32.whl", hash = "sha256:1514341def9c6ec4b7f0b9628be95f620f9d4b99331b7ef0a1845fd33d9b579c"}, - {file = "grpcio-1.69.0-cp39-cp39-win_amd64.whl", hash = "sha256:c1fea55d26d647346acb0069b08dca70984101f2dc95066e003019207212e303"}, - {file = "grpcio-1.69.0.tar.gz", hash = "sha256:936fa44241b5379c5afc344e1260d467bee495747eaf478de825bab2791da6f5"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.69.0)"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "hexbytes" -version = "0.3.1" -description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" -optional = false -python-versions = ">=3.7, <4" -groups = ["main"] -files = [ - {file = "hexbytes-0.3.1-py3-none-any.whl", hash = "sha256:383595ad75026cf00abd570f44b368c6cdac0c6becfae5c39ff88829877f8a59"}, - {file = "hexbytes-0.3.1.tar.gz", hash = "sha256:a3fe35c6831ee8fafd048c4c086b986075fc14fd46258fa24ecb8d65745f9a9d"}, -] - -[package.extras] -dev = ["black (>=22)", "bumpversion (>=0.5.3)", "eth-utils (>=1.0.1,<3)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=5.0.0)", "pytest (>=7.0.0)", "pytest-watch (>=4.1.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -doc = ["sphinx (>=5.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -lint = ["black (>=22)", "flake8 (==6.0.0)", "flake8-bugbear (==23.3.23)", "isort (>=5.10.1)", "mypy (==0.971)", "pydocstyle (>=5.0.0)"] -test = ["eth-utils (>=1.0.1,<3)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] - -[[package]] -name = "httpcore" -version = "0.16.3" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, - {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, -] - -[package.dependencies] -anyio = ">=3.0,<5.0" -certifi = "*" -h11 = ">=0.13,<0.15" -sniffio = "==1.*" - -[package.extras] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] - -[[package]] -name = "httpx" -version = "0.23.3" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, - {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, -] - -[package.dependencies] -certifi = "*" -httpcore = ">=0.15.0,<0.17.0" -rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} -sniffio = "*" - -[package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] - -[[package]] -name = "hypothesis" -version = "6.122.3" -description = "A library for property-based testing" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "hypothesis-6.122.3-py3-none-any.whl", hash = "sha256:f0f57036d3b95b979491602b32c95b6725c3af678cccb6165d8de330857f3c83"}, - {file = "hypothesis-6.122.3.tar.gz", hash = "sha256:f4c927ce0ec739fa6266e4572949d0b54e24a14601a2bc5fec8f78e16af57918"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} -sortedcontainers = ">=2.1.0,<3.0.0" - -[package.extras] -all = ["black (>=19.10b0)", "click (>=7.0)", "crosshair-tool (>=0.0.78)", "django (>=4.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.18)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.19.3)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] -cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] -codemods = ["libcst (>=0.3.16)"] -crosshair = ["crosshair-tool (>=0.0.78)", "hypothesis-crosshair (>=0.0.18)"] -dateutil = ["python-dateutil (>=1.4)"] -django = ["django (>=4.2)"] -dpcontracts = ["dpcontracts (>=0.4)"] -ghostwriter = ["black (>=19.10b0)"] -lark = ["lark (>=0.10.1)"] -numpy = ["numpy (>=1.19.3)"] -pandas = ["pandas (>=1.1)"] -pytest = ["pytest (>=4.6)"] -pytz = ["pytz (>=2014.1)"] -redis = ["redis (>=3.0.0)"] -zoneinfo = ["tzdata (>=2024.2) ; sys_platform == \"win32\" or sys_platform == \"emscripten\""] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "ipfshttpclient" -version = "0.8.0a2" -description = "Python IPFS HTTP CLIENT library" -optional = false -python-versions = ">=3.6.2,!=3.7.0,!=3.7.1" -groups = ["main"] -files = [ - {file = "ipfshttpclient-0.8.0a2-py3-none-any.whl", hash = "sha256:ce6bac0e3963c4ced74d7eb6978125362bb05bbe219088ca48f369ce14d3cc39"}, - {file = "ipfshttpclient-0.8.0a2.tar.gz", hash = "sha256:0d80e95ee60b02c7d414e79bf81a36fc3c8fbab74265475c52f70b2620812135"}, -] - -[package.dependencies] -multiaddr = ">=0.0.7" -requests = ">=2.11" - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "itsdangerous" -version = "2.2.0" -description = "Safely pass data to untrusted environments and back." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, - {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, -] - -[[package]] -name = "jinja2" -version = "3.1.6" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, - {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jsonalias" -version = "0.1.1" -description = "A microlibrary that defines a Json type alias for Python." -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "jsonalias-0.1.1-py3-none-any.whl", hash = "sha256:a56d2888e6397812c606156504e861e8ec00e188005af149f003c787db3d3f18"}, - {file = "jsonalias-0.1.1.tar.gz", hash = "sha256:64f04d935397d579fc94509e1fcb6212f2d081235d9d6395bd10baedf760a769"}, -] - -[[package]] -name = "jsonrpcclient" -version = "4.0.3" -description = "Send JSON-RPC requests" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "jsonrpcclient-4.0.3-py3-none-any.whl", hash = "sha256:3cbb9e27e1be29821becf135ea183144a836215422727e1ffe5056a49a670f0d"}, -] - -[package.extras] -qa = ["pytest", "pytest-cov", "tox"] - -[[package]] -name = "jsonschema" -version = "4.3.3" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jsonschema-4.3.3-py3-none-any.whl", hash = "sha256:eb7a69801beb7325653aa8fd373abbf9ff8f85b536ab2812e5e8287b522fb6a2"}, - {file = "jsonschema-4.3.3.tar.gz", hash = "sha256:f210d4ce095ed1e8af635d15c8ee79b586f656ab54399ba87b8ab87e5bff0ade"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "lru-dict" -version = "1.2.0" -description = "An Dict like LRU container." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "lru-dict-1.2.0.tar.gz", hash = "sha256:13c56782f19d68ddf4d8db0170041192859616514c706b126d0df2ec72a11bd7"}, - {file = "lru_dict-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:de906e5486b5c053d15b7731583c25e3c9147c288ac8152a6d1f9bccdec72641"}, - {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604d07c7604b20b3130405d137cae61579578b0e8377daae4125098feebcb970"}, - {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:203b3e78d03d88f491fa134f85a42919020686b6e6f2d09759b2f5517260c651"}, - {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:020b93870f8c7195774cbd94f033b96c14f51c57537969965c3af300331724fe"}, - {file = "lru_dict-1.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1184d91cfebd5d1e659d47f17a60185bbf621635ca56dcdc46c6a1745d25df5c"}, - {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fc42882b554a86e564e0b662da47b8a4b32fa966920bd165e27bb8079a323bc1"}, - {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:18ee88ada65bd2ffd483023be0fa1c0a6a051ef666d1cd89e921dcce134149f2"}, - {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:756230c22257597b7557eaef7f90484c489e9ba78e5bb6ab5a5bcfb6b03cb075"}, - {file = "lru_dict-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c4da599af36618881748b5db457d937955bb2b4800db891647d46767d636c408"}, - {file = "lru_dict-1.2.0-cp310-cp310-win32.whl", hash = "sha256:35a142a7d1a4fd5d5799cc4f8ab2fff50a598d8cee1d1c611f50722b3e27874f"}, - {file = "lru_dict-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:6da5b8099766c4da3bf1ed6e7d7f5eff1681aff6b5987d1258a13bd2ed54f0c9"}, - {file = "lru_dict-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b20b7c9beb481e92e07368ebfaa363ed7ef61e65ffe6e0edbdbaceb33e134124"}, - {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22147367b296be31cc858bf167c448af02435cac44806b228c9be8117f1bfce4"}, - {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a3091abeb95e707f381a8b5b7dc8e4ee016316c659c49b726857b0d6d1bd7a"}, - {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877801a20f05c467126b55338a4e9fa30e2a141eb7b0b740794571b7d619ee11"}, - {file = "lru_dict-1.2.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d3336e901acec897bcd318c42c2b93d5f1d038e67688f497045fc6bad2c0be7"}, - {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8dafc481d2defb381f19b22cc51837e8a42631e98e34b9e0892245cc96593deb"}, - {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:87bbad3f5c3de8897b8c1263a9af73bbb6469fb90e7b57225dad89b8ef62cd8d"}, - {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:25f9e0bc2fe8f41c2711ccefd2871f8a5f50a39e6293b68c3dec576112937aad"}, - {file = "lru_dict-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ae301c282a499dc1968dd633cfef8771dd84228ae9d40002a3ea990e4ff0c469"}, - {file = "lru_dict-1.2.0-cp311-cp311-win32.whl", hash = "sha256:c9617583173a29048e11397f165501edc5ae223504a404b2532a212a71ecc9ed"}, - {file = "lru_dict-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6b7a031e47421d4b7aa626b8c91c180a9f037f89e5d0a71c4bb7afcf4036c774"}, - {file = "lru_dict-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ea2ac3f7a7a2f32f194c84d82a034e66780057fd908b421becd2f173504d040e"}, - {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd46c94966f631a81ffe33eee928db58e9fbee15baba5923d284aeadc0e0fa76"}, - {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:086ce993414f0b28530ded7e004c77dc57c5748fa6da488602aa6e7f79e6210e"}, - {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df25a426446197488a6702954dcc1de511deee20c9db730499a2aa83fddf0df1"}, - {file = "lru_dict-1.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c53b12b89bd7a6c79f0536ff0d0a84fdf4ab5f6252d94b24b9b753bd9ada2ddf"}, - {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f9484016e6765bd295708cccc9def49f708ce07ac003808f69efa386633affb9"}, - {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d0f7ec902a0097ac39f1922c89be9eaccf00eb87751e28915320b4f72912d057"}, - {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:981ef3edc82da38d39eb60eae225b88a538d47b90cce2e5808846fd2cf64384b"}, - {file = "lru_dict-1.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e25b2e90a032dc248213af7f3f3e975e1934b204f3b16aeeaeaff27a3b65e128"}, - {file = "lru_dict-1.2.0-cp36-cp36m-win32.whl", hash = "sha256:59f3df78e94e07959f17764e7fa7ca6b54e9296953d2626a112eab08e1beb2db"}, - {file = "lru_dict-1.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:de24b47159e07833aeab517d9cb1c3c5c2d6445cc378b1c2f1d8d15fb4841d63"}, - {file = "lru_dict-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d0dd4cd58220351233002f910e35cc01d30337696b55c6578f71318b137770f9"}, - {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a87bdc291718bbdf9ea4be12ae7af26cbf0706fa62c2ac332748e3116c5510a7"}, - {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05fb8744f91f58479cbe07ed80ada6696ec7df21ea1740891d4107a8dd99a970"}, - {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00f6e8a3fc91481b40395316a14c94daa0f0a5de62e7e01a7d589f8d29224052"}, - {file = "lru_dict-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b172fce0a0ffc0fa6d282c14256d5a68b5db1e64719c2915e69084c4b6bf555"}, - {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e707d93bae8f0a14e6df1ae8b0f076532b35f00e691995f33132d806a88e5c18"}, - {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b9ec7a4a0d6b8297102aa56758434fb1fca276a82ed7362e37817407185c3abb"}, - {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f404dcc8172da1f28da9b1f0087009578e608a4899b96d244925c4f463201f2a"}, - {file = "lru_dict-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1171ad3bff32aa8086778be4a3bdff595cc2692e78685bcce9cb06b96b22dcc2"}, - {file = "lru_dict-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:0c316dfa3897fabaa1fe08aae89352a3b109e5f88b25529bc01e98ac029bf878"}, - {file = "lru_dict-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5919dd04446bc1ee8d6ecda2187deeebfff5903538ae71083e069bc678599446"}, - {file = "lru_dict-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fbf36c5a220a85187cacc1fcb7dd87070e04b5fc28df7a43f6842f7c8224a388"}, - {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:712e71b64da181e1c0a2eaa76cd860265980cd15cb0e0498602b8aa35d5db9f8"}, - {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f54908bf91280a9b8fa6a8c8f3c2f65850ce6acae2852bbe292391628ebca42f"}, - {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3838e33710935da2ade1dd404a8b936d571e29268a70ff4ca5ba758abb3850df"}, - {file = "lru_dict-1.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5d5a5f976b39af73324f2b793862859902ccb9542621856d51a5993064f25e4"}, - {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8bda3a9afd241ee0181661decaae25e5336ce513ac268ab57da737eacaa7871f"}, - {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd2cd1b998ea4c8c1dad829fc4fa88aeed4dee555b5e03c132fc618e6123f168"}, - {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b55753ee23028ba8644fd22e50de7b8f85fa60b562a0fafaad788701d6131ff8"}, - {file = "lru_dict-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7e51fa6a203fa91d415f3b2900e5748ec8e06ad75777c98cc3aeb3983ca416d7"}, - {file = "lru_dict-1.2.0-cp38-cp38-win32.whl", hash = "sha256:cd6806313606559e6c7adfa0dbeb30fc5ab625f00958c3d93f84831e7a32b71e"}, - {file = "lru_dict-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d90a70c53b0566084447c3ef9374cc5a9be886e867b36f89495f211baabd322"}, - {file = "lru_dict-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3ea7571b6bf2090a85ff037e6593bbafe1a8598d5c3b4560eb56187bcccb4dc"}, - {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:287c2115a59c1c9ed0d5d8ae7671e594b1206c36ea9df2fca6b17b86c468ff99"}, - {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5ccfd2291c93746a286c87c3f895165b697399969d24c54804ec3ec559d4e43"}, - {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b710f0f4d7ec4f9fa89dfde7002f80bcd77de8024017e70706b0911ea086e2ef"}, - {file = "lru_dict-1.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5345bf50e127bd2767e9fd42393635bbc0146eac01f6baf6ef12c332d1a6a329"}, - {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:291d13f85224551913a78fe695cde04cbca9dcb1d84c540167c443eb913603c9"}, - {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d5bb41bc74b321789803d45b124fc2145c1b3353b4ad43296d9d1d242574969b"}, - {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0facf49b053bf4926d92d8d5a46fe07eecd2af0441add0182c7432d53d6da667"}, - {file = "lru_dict-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:987b73a06bcf5a95d7dc296241c6b1f9bc6cda42586948c9dabf386dc2bef1cd"}, - {file = "lru_dict-1.2.0-cp39-cp39-win32.whl", hash = "sha256:231d7608f029dda42f9610e5723614a35b1fff035a8060cf7d2be19f1711ace8"}, - {file = "lru_dict-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:71da89e134747e20ed5b8ad5b4ee93fc5b31022c2b71e8176e73c5a44699061b"}, - {file = "lru_dict-1.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:21b3090928c7b6cec509e755cc3ab742154b33660a9b433923bd12c37c448e3e"}, - {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaecd7085212d0aa4cd855f38b9d61803d6509731138bf798a9594745953245b"}, - {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead83ac59a29d6439ddff46e205ce32f8b7f71a6bd8062347f77e232825e3d0a"}, - {file = "lru_dict-1.2.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:312b6b2a30188586fe71358f0f33e4bac882d33f5e5019b26f084363f42f986f"}, - {file = "lru_dict-1.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b30122e098c80e36d0117810d46459a46313421ce3298709170b687dc1240b02"}, - {file = "lru_dict-1.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f010cfad3ab10676e44dc72a813c968cd586f37b466d27cde73d1f7f1ba158c2"}, - {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20f5f411f7751ad9a2c02e80287cedf69ae032edd321fe696e310d32dd30a1f8"}, - {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afdadd73304c9befaed02eb42f5f09fdc16288de0a08b32b8080f0f0f6350aa6"}, - {file = "lru_dict-1.2.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7ab0c10c4fa99dc9e26b04e6b62ac32d2bcaea3aad9b81ec8ce9a7aa32b7b1b"}, - {file = "lru_dict-1.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:edad398d5d402c43d2adada390dd83c74e46e020945ff4df801166047013617e"}, - {file = "lru_dict-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:91d577a11b84387013815b1ad0bb6e604558d646003b44c92b3ddf886ad0f879"}, - {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb12f19cdf9c4f2d9aa259562e19b188ff34afab28dd9509ff32a3f1c2c29326"}, - {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e4c85aa8844bdca3c8abac3b7f78da1531c74e9f8b3e4890c6e6d86a5a3f6c0"}, - {file = "lru_dict-1.2.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c6acbd097b15bead4de8e83e8a1030bb4d8257723669097eac643a301a952f0"}, - {file = "lru_dict-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b6613daa851745dd22b860651de930275be9d3e9373283a2164992abacb75b62"}, -] - -[package.extras] -test = ["pytest"] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "markupsafe" -version = "3.0.2" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "more-itertools" -version = "8.14.0" -description = "More routines for operating on iterables, beyond itertools" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "more-itertools-8.14.0.tar.gz", hash = "sha256:c09443cd3d5438b8dafccd867a6bc1cb0894389e90cb53d227456b0b0bccb750"}, - {file = "more_itertools-8.14.0-py3-none-any.whl", hash = "sha256:1bc4f91ee5b1b31ac7ceacc17c09befe6a40a503907baf9c839c229b5095cfd2"}, -] - -[[package]] -name = "morphys" -version = "1.0" -description = "Smart conversions between unicode and bytes types for common cases" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "morphys-1.0-py2.py3-none-any.whl", hash = "sha256:76d6dbaa4d65f597e59d332c81da786d83e4669387b9b2a750cfec74e7beec20"}, -] - -[[package]] -name = "multiaddr" -version = "0.0.9" -description = "Python implementation of jbenet's multiaddr" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -groups = ["main"] -files = [ - {file = "multiaddr-0.0.9-py2.py3-none-any.whl", hash = "sha256:5c0f862cbcf19aada2a899f80ef896ddb2e85614e0c8f04dd287c06c69dac95b"}, - {file = "multiaddr-0.0.9.tar.gz", hash = "sha256:30b2695189edc3d5b90f1c303abb8f02d963a3a4edf2e7178b975eb417ab0ecf"}, -] - -[package.dependencies] -base58 = "*" -netaddr = "*" -six = "*" -varint = "*" - -[[package]] -name = "multidict" -version = "6.1.0" -description = "multidict implementation" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, - {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, - {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, - {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, - {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, - {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, - {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, - {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, - {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, - {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, - {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, - {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, - {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, - {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, - {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "netaddr" -version = "1.3.0" -description = "A network address manipulation library for Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "netaddr-1.3.0-py3-none-any.whl", hash = "sha256:c2c6a8ebe5554ce33b7d5b3a306b71bbb373e000bbbf2350dd5213cc56e3dbbe"}, - {file = "netaddr-1.3.0.tar.gz", hash = "sha256:5c3c3d9895b551b763779ba7db7a03487dc1f8e3b385af819af341ae9ef6e48a"}, -] - -[package.extras] -nicer-shell = ["ipython"] - -[[package]] -name = "open-aea" -version = "1.65.0" -description = "Open Autonomous Economic Agent framework (without vendor lock-in)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "open_aea-1.65.0-py3-none-any.whl", hash = "sha256:e6353ccc29014e1015acabc4b4b83756bbfc955d6f0a8fa9e8104f3daef5eb5a"}, - {file = "open_aea-1.65.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:bdba7028bb7c85e1ec267d0dbdf372843a2492c5cf220c4d6badc45bd206c31d"}, - {file = "open_aea-1.65.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:d0195e1eeae6620cf04898800fad0bc89f460c5d4c4e89e5e54f8d4ced7337b2"}, - {file = "open_aea-1.65.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:fc636b22af8c3160911e857692126ab7dadf5af834ed5b52559e4ab9c3d4935f"}, - {file = "open_aea-1.65.0-py3-none-win32.whl", hash = "sha256:b3bddcb64ec1852f59d6c730ad1ee825b0243d8bd4d25c744b5087ae40f0e04d"}, - {file = "open_aea-1.65.0-py3-none-win_amd64.whl", hash = "sha256:5fdba41e7ffafd47e56e83f20fec4d764b5db5a57fba56c39c134ef1c602d479"}, - {file = "open_aea-1.65.0.tar.gz", hash = "sha256:7be549fd41ae423f527146c80435bf4a5002dd85d2e4cef368f344e8641aab80"}, -] - -[package.dependencies] -base58 = ">=1.0.3,<3.0.0" -click = {version = ">=8.1.0,<9", optional = true, markers = "extra == \"all\""} -coverage = {version = ">=6.4.4,<8.0.0", optional = true, markers = "extra == \"all\""} -ecdsa = ">=0.15,<0.17.0" -jsonschema = ">=4.3.0,<4.4.0" -morphys = ">=1.0" -packaging = ">=23.1,<24.0" -protobuf = ">=4.21.6,<4.25.0" -py-multibase = ">=1.0.0" -py-multicodec = ">=0.2.0" -pymultihash = "0.8.2" -pytest = {version = ">=7.0.0,<7.3.0", optional = true, markers = "extra == \"all\""} -python-dotenv = ">=0.14.0,<1.0.1" -pyyaml = [ - {version = ">=6.0.1,<7"}, - {version = ">=6.0.1,<7", optional = true, markers = "extra == \"all\""}, -] -requests = ">=2.28.1,<3" -semver = ">=2.9.1,<3.0.0" - -[package.extras] -all = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "jsonschema (>=4.3.0,<4.4.0)", "packaging (>=23.1,<24.0)", "pytest (>=7.0.0,<7.3.0)", "pyyaml (>=6.0.1,<9)", "semver (>=2.9.1,<3.0.0)"] -cli = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "jsonschema (>=4.3.0,<4.4.0)", "packaging (>=23.1,<24.0)", "pytest (>=7.0.0,<7.3.0)", "pyyaml (>=6.0.1,<9)", "semver (>=2.9.1,<3.0.0)"] -test-tools = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "jsonschema (>=4.3.0,<4.4.0)", "packaging (>=23.1,<24.0)", "pytest (>=7.0.0,<7.3.0)", "pyyaml (>=6.0.1,<9)", "semver (>=2.9.1,<3.0.0)"] - -[[package]] -name = "open-aea-cli-ipfs" -version = "1.65.0" -description = "CLI extension for open AEA framework wrapping IPFS functionality." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "open_aea_cli_ipfs-1.65.0-py3-none-any.whl", hash = "sha256:5f1e730d0821bf5b85c3dc8cc049e94a885b7ea042e8cf1cf573956576d91a49"}, - {file = "open_aea_cli_ipfs-1.65.0.tar.gz", hash = "sha256:2e9875b1b334aa3f949fa2e52c4870f697c9550d02bbde1847fff603fb069205"}, -] - -[package.dependencies] -ipfshttpclient = ">=0.8.0a2" -open-aea = ">=1.0.0,<2.0.0" -pytest = ">=7.0.0,<7.3.0" - -[[package]] -name = "open-aea-ledger-cosmos" -version = "1.65.0" -description = "Python package wrapping the public and private key cryptography and ledger api of Cosmos." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "open_aea_ledger_cosmos-1.65.0-py3-none-any.whl", hash = "sha256:58a5816c2dc7657cf26a93a934958f3f1b5f7744664770cf182903cd74a0aa22"}, - {file = "open_aea_ledger_cosmos-1.65.0.tar.gz", hash = "sha256:8da7f5081ff569eb4caa9a7c2a3afe9c03aa9d0d81f060746f949596ae344304"}, -] - -[package.dependencies] -bech32 = ">=1.2.0,<2" -cosmpy = "0.9.2" -ecdsa = ">=0.15,<0.17.0" -open-aea = ">=1.0.0,<2.0.0" -pycryptodome = ">=3.10.1,<4.0.0" - -[[package]] -name = "open-aea-ledger-ethereum" -version = "1.65.0" -description = "Python package wrapping the public and private key cryptography and ledger api of Ethereum." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "open_aea_ledger_ethereum-1.65.0-py3-none-any.whl", hash = "sha256:88d0f571a2a0f247cfe581ac8a4273541da1bf4e9e7ae88197ed24e945f26ba4"}, - {file = "open_aea_ledger_ethereum-1.65.0.tar.gz", hash = "sha256:7ee3e58e6eee025008f7f2550fdfc315b41bb1e3d961187ef760a196995134c1"}, -] - -[package.dependencies] -eth-account = ">=0.8.0,<0.9.0" -ipfshttpclient = "0.8.0a2" -open-aea = ">=1.0.0,<2.0.0" -web3 = ">=6.0.0,<7" - -[[package]] -name = "open-aea-ledger-solana" -version = "1.65.0" -description = "Python package wrapping the public and private key cryptography and ledger api of solana." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "open_aea_ledger_solana-1.65.0-py3-none-any.whl", hash = "sha256:d1b01b733b1da655d0b3bc690daa7d26e6dff8135ed41b31c77215f125f915cc"}, - {file = "open_aea_ledger_solana-1.65.0.tar.gz", hash = "sha256:0527bed29828616d38438493c14961a60012b3ccbeda2dc7a6bc58f01977009b"}, -] - -[package.dependencies] -anchorpy = ">=0.17.0,<0.19.0" -cryptography = "*" -open-aea = ">=1.0.0,<2.0.0" -PyNaCl = ">=1.5.0,<2" -solana = ">=0.29.0" -solders = ">=0.14.0" - -[[package]] -name = "open-aea-test-autonomy" -version = "0.19.7" -description = "Plugin containing test tools for open-autonomy packages." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "open_aea_test_autonomy-0.19.7-py3-none-any.whl", hash = "sha256:317d7012ccb59b3252634bc7f02f618dbb41e5a88bf1d73c0c8b180e649ebac7"}, - {file = "open_aea_test_autonomy-0.19.7.tar.gz", hash = "sha256:dee5a345e2ece72a313aeccdb4f61ad70510bf70583dc5c7b441d1b859f840f7"}, -] - -[package.dependencies] -docker = "6.1.2" -open-aea = {version = ">=1.65.0,<2.0.0", extras = ["all"]} -open-aea-ledger-ethereum = ">=1.65.0,<2.0.0" -pytest = "7.2.1" - -[[package]] -name = "open-autonomy" -version = "0.19.7" -description = "A framework for the creation of autonomous agent services." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "open_autonomy-0.19.7-py3-none-any.whl", hash = "sha256:74458c054a8df2aa08c435f7838cfc18dbbb7967e5bddf4a65344003e907ac24"}, - {file = "open_autonomy-0.19.7.tar.gz", hash = "sha256:d49cf8605308ff60700d1c28f48eed1241ab06057d47dac41f7e96e6ae81b476"}, -] - -[package.dependencies] -aiohttp = ">=3.8.5,<4.0.0" -click = ">=8.1.0,<9" -coverage = ">=6.4.4,<8.0.0" -docker = "6.1.2" -Flask = ">=2.0.2,<3.0.0" -gql = "3.5.0" -hexbytes = "*" -jsonschema = ">=4.3.0,<4.4.0" -open-aea = {version = "1.65.0", extras = ["all"]} -open-aea-cli-ipfs = "1.65.0" -protobuf = ">=4.21.6,<4.25.0" -pytest = "7.2.1" -python-dotenv = ">=0.14.5,<0.22.0" -requests = ">=2.28.1,<2.31.2" -requests-toolbelt = "1.0.0" -texttable = "1.6.7" -typing_extensions = ">=3.10.0.2" -valory-docker-compose = "1.29.3" -watchdog = ">=2.1.6" -werkzeug = "2.0.3" - -[package.extras] -all = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (==1.65.0)", "pytest (>=7.0.0,<7.3.0)", "python-dotenv (>=0.14.5,<0.22.0)", "texttable (==1.6.7)"] -cli = ["click (>=8.1.0,<9)", "coverage (>=6.4.4,<8.0.0)", "open-aea-cli-ipfs (==1.65.0)", "pytest (>=7.0.0,<7.3.0)", "python-dotenv (>=0.14.5,<0.22.0)", "texttable (==1.6.7)"] - -[[package]] -name = "openapi-spec-validator" -version = "0.2.8" -description = "" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "openapi-spec-validator-0.2.8.tar.gz", hash = "sha256:e489c7a273284bc78277ac22791482e8058d323b4a265015e9fcddf6a8045bcd"}, - {file = "openapi_spec_validator-0.2.8-py2-none-any.whl", hash = "sha256:d4da8aef72bf5be40cf0df444abd20009a41baf9048a8e03750c07a934f1bdd8"}, - {file = "openapi_spec_validator-0.2.8-py3-none-any.whl", hash = "sha256:0caacd9829e9e3051e830165367bf58d436d9487b29a09220fa7edb9f47ff81b"}, -] - -[package.dependencies] -jsonschema = "*" -PyYAML = ">=5.1" -six = "*" - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "paramiko" -version = "3.5.1" -description = "SSH2 protocol library" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "paramiko-3.5.1-py3-none-any.whl", hash = "sha256:43b9a0501fc2b5e70680388d9346cf252cfb7d00b0667c39e80eb43a408b8f61"}, - {file = "paramiko-3.5.1.tar.gz", hash = "sha256:b2c665bc45b2b215bd7d7f039901b14b067da00f3a11e6640995fd58f2664822"}, -] - -[package.dependencies] -bcrypt = ">=3.2" -cryptography = ">=3.3" -pynacl = ">=1.5" - -[package.extras] -all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] -gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""] -invoke = ["invoke (>=2.0)"] - -[[package]] -name = "parsimonious" -version = "0.10.0" -description = "(Soon to be) the fastest pure-Python PEG parser I could muster" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "parsimonious-0.10.0-py3-none-any.whl", hash = "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f"}, - {file = "parsimonious-0.10.0.tar.gz", hash = "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c"}, -] - -[package.dependencies] -regex = ">=2022.3.15" - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.6" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "propcache" -version = "0.3.0" -description = "Accelerated property cache" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d"}, - {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c"}, - {file = "propcache-0.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc"}, - {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d"}, - {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f"}, - {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf"}, - {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9"}, - {file = "propcache-0.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc"}, - {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0"}, - {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b"}, - {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f"}, - {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a"}, - {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25"}, - {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f"}, - {file = "propcache-0.3.0-cp310-cp310-win32.whl", hash = "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c"}, - {file = "propcache-0.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340"}, - {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51"}, - {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e"}, - {file = "propcache-0.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa"}, - {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf"}, - {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b"}, - {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9"}, - {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6"}, - {file = "propcache-0.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c"}, - {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075"}, - {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c"}, - {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810"}, - {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3"}, - {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7"}, - {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c"}, - {file = "propcache-0.3.0-cp311-cp311-win32.whl", hash = "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d"}, - {file = "propcache-0.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32"}, - {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e"}, - {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af"}, - {file = "propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5"}, - {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b"}, - {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667"}, - {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7"}, - {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7"}, - {file = "propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf"}, - {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138"}, - {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86"}, - {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d"}, - {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e"}, - {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64"}, - {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c"}, - {file = "propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d"}, - {file = "propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57"}, - {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568"}, - {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9"}, - {file = "propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767"}, - {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8"}, - {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0"}, - {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d"}, - {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05"}, - {file = "propcache-0.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe"}, - {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1"}, - {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92"}, - {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787"}, - {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545"}, - {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e"}, - {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626"}, - {file = "propcache-0.3.0-cp313-cp313-win32.whl", hash = "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374"}, - {file = "propcache-0.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a"}, - {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf"}, - {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0"}, - {file = "propcache-0.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829"}, - {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa"}, - {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6"}, - {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db"}, - {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54"}, - {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121"}, - {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e"}, - {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e"}, - {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a"}, - {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac"}, - {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e"}, - {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf"}, - {file = "propcache-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863"}, - {file = "propcache-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46"}, - {file = "propcache-0.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc"}, - {file = "propcache-0.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b"}, - {file = "propcache-0.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649"}, - {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce"}, - {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe"}, - {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14"}, - {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe"}, - {file = "propcache-0.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e"}, - {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07"}, - {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90"}, - {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641"}, - {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f"}, - {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7"}, - {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f"}, - {file = "propcache-0.3.0-cp39-cp39-win32.whl", hash = "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663"}, - {file = "propcache-0.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929"}, - {file = "propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043"}, - {file = "propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5"}, -] - -[[package]] -name = "protobuf" -version = "4.24.4" -description = "" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "protobuf-4.24.4-cp310-abi3-win32.whl", hash = "sha256:ec9912d5cb6714a5710e28e592ee1093d68c5ebfeda61983b3f40331da0b1ebb"}, - {file = "protobuf-4.24.4-cp310-abi3-win_amd64.whl", hash = "sha256:1badab72aa8a3a2b812eacfede5020472e16c6b2212d737cefd685884c191085"}, - {file = "protobuf-4.24.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e61a27f362369c2f33248a0ff6896c20dcd47b5d48239cb9720134bef6082e4"}, - {file = "protobuf-4.24.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:bffa46ad9612e6779d0e51ae586fde768339b791a50610d85eb162daeb23661e"}, - {file = "protobuf-4.24.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:b493cb590960ff863743b9ff1452c413c2ee12b782f48beca77c8da3e2ffe9d9"}, - {file = "protobuf-4.24.4-cp37-cp37m-win32.whl", hash = "sha256:dbbed8a56e56cee8d9d522ce844a1379a72a70f453bde6243e3c86c30c2a3d46"}, - {file = "protobuf-4.24.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6b7d2e1c753715dcfe9d284a25a52d67818dd43c4932574307daf836f0071e37"}, - {file = "protobuf-4.24.4-cp38-cp38-win32.whl", hash = "sha256:02212557a76cd99574775a81fefeba8738d0f668d6abd0c6b1d3adcc75503dbe"}, - {file = "protobuf-4.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:2fa3886dfaae6b4c5ed2730d3bf47c7a38a72b3a1f0acb4d4caf68e6874b947b"}, - {file = "protobuf-4.24.4-cp39-cp39-win32.whl", hash = "sha256:b77272f3e28bb416e2071186cb39efd4abbf696d682cbb5dc731308ad37fa6dd"}, - {file = "protobuf-4.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:9fee5e8aa20ef1b84123bb9232b3f4a5114d9897ed89b4b8142d81924e05d79b"}, - {file = "protobuf-4.24.4-py3-none-any.whl", hash = "sha256:80797ce7424f8c8d2f2547e2d42bfbb6c08230ce5832d6c099a37335c9c90a92"}, - {file = "protobuf-4.24.4.tar.gz", hash = "sha256:5a70731910cd9104762161719c3d883c960151eea077134458503723b60e3667"}, -] - -[[package]] -name = "psutil" -version = "7.0.0" -description = "Cross-platform lib for process and system monitoring in Python. NOTE: the syntax of this script MUST be kept compatible with Python 2.7." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25"}, - {file = "psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da"}, - {file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91"}, - {file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34"}, - {file = "psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993"}, - {file = "psutil-7.0.0-cp36-cp36m-win32.whl", hash = "sha256:84df4eb63e16849689f76b1ffcb36db7b8de703d1bc1fe41773db487621b6c17"}, - {file = "psutil-7.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1e744154a6580bc968a0195fd25e80432d3afec619daf145b9e5ba16cc1d688e"}, - {file = "psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99"}, - {file = "psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553"}, - {file = "psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456"}, -] - -[package.extras] -dev = ["abi3audit", "black (==24.10.0)", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest", "pytest-cov", "pytest-xdist", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"] -test = ["pytest", "pytest-xdist", "setuptools"] - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] - -[[package]] -name = "py-ecc" -version = "7.0.1" -description = "py-ecc: Elliptic curve crypto in python including secp256k1, alt_bn128, and bls12_381" -optional = false -python-versions = "<4,>=3.8" -groups = ["main"] -files = [ - {file = "py_ecc-7.0.1-py3-none-any.whl", hash = "sha256:84a8b4d436163c83c65345a68e32f921ef6e64374a36f8e561f0455b4b08f5f2"}, - {file = "py_ecc-7.0.1.tar.gz", hash = "sha256:557461f42e57294d734305a30faf6b8903421651871e9cdeff8d8e67c6796c70"}, -] - -[package.dependencies] -cached-property = ">=1.5.1" -eth-typing = ">=3.0.0" -eth-utils = ">=2.0.0" - -[package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] - -[[package]] -name = "py-eth-sig-utils" -version = "0.4.0" -description = "Python Ethereum Signing Utils" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "py_eth_sig_utils-0.4.0-py3-none-any.whl", hash = "sha256:8f2fe9b8d3c475bfca3b3bb901f6ef79e42b7b4abcd00ad5de5d483fff8359e9"}, - {file = "py_eth_sig_utils-0.4.0.tar.gz", hash = "sha256:bdf76b06677a43eba42e29ddebe6832bfbdda4c09a6b171d0de318e5a06992ad"}, -] - -[package.dependencies] -eth-abi = ">=1.1.1" -py-ecc = ">=1.7.1" -pycryptodome = ">=3.4.7" -rlp = ">=1.1.0" - -[[package]] -name = "py-multibase" -version = "1.0.3" -description = "Multibase implementation for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "py-multibase-1.0.3.tar.gz", hash = "sha256:d28a20efcbb61eec28f55827a0bf329c7cea80fffd933aecaea6ae8431267fe4"}, - {file = "py_multibase-1.0.3-py2.py3-none-any.whl", hash = "sha256:2677c1fafcc0ae15ddb9c7f444c5becc2530b3889124fd4fa2959ddfefb8c15b"}, -] - -[package.dependencies] -morphys = ">=1.0,<2.0" -python-baseconv = ">=1.2.0,<2.0" -six = ">=1.10.0,<2.0" - -[[package]] -name = "py-multicodec" -version = "0.2.1" -description = "Multicodec implementation in Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "py-multicodec-0.2.1.tar.gz", hash = "sha256:83021ffe8c0e272d19b5b86bc5b39efa67c8e9f4735ce6cafdbc1ace767ec647"}, - {file = "py_multicodec-0.2.1-py2.py3-none-any.whl", hash = "sha256:55b6bb53088a63e56c434cb11b29795e8805652bac43d50a8f2a9bcf5ca84e1f"}, -] - -[package.dependencies] -morphys = ">=1.0,<2.0" -six = ">=1.10.0,<2.0" -varint = ">=1.0.2,<2.0.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pycryptodome" -version = "3.20.0" -description = "Cryptographic library for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"}, - {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"}, - {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"}, - {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"}, - {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"}, - {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"}, - {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"}, - {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"}, - {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"}, - {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"}, - {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"}, - {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"}, - {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"}, - {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"}, -] - -[[package]] -name = "pydantic" -version = "2.10.6" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pydoclint" -version = "0.6.2" -description = "A Python docstring linter that checks arguments, returns, yields, and raises sections" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydoclint-0.6.2-py2.py3-none-any.whl", hash = "sha256:1db52b9949c11c1e84b9be1ae757beffcb50477af90f5b8d83e7290bde5dee45"}, - {file = "pydoclint-0.6.2.tar.gz", hash = "sha256:f6d22ccdc41047ad4cdfd1a4b6ac197e834af3c8c249a97da23705fde3cff70f"}, -] - -[package.dependencies] -click = ">=8.1.0" -docstring_parser_fork = ">=0.0.12" -tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -flake8 = ["flake8 (>=4)"] - -[[package]] -name = "pygments" -version = "2.19.1" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyheck" -version = "0.1.5" -description = "Python bindings for heck, the Rust case conversion library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pyheck-0.1.5-cp37-abi3-macosx_10_7_x86_64.whl", hash = "sha256:44caf2b7a49d71fdeb0469e9f35886987ad815a8638b3c5b5c83f351d6aed413"}, - {file = "pyheck-0.1.5-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:316a842b94beff6e59a97dbcc590e9be92a932e59126b0faa9ac750384f27eaf"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b6169397395ff041f056bfb36c1957a788a1cd7cb967a927fcae7917ff1b6aa"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e9d101e1c599227280e34eeccab0414246e70a91a1cabb4c4868dca284f2be7d"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:69d6509138909df92b2f2f837518dca118ef08ae3c804044ae511b81b7aecb4d"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ce4a2e1b4778051b8f31183e321a034603f3957b6e95cf03bf5f231c8ea3066"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69387b70d910637ab6dc8dc378c8e0b4037cee2c51a9c6f64ce5331b010f5de3"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0fb50b7d899d2a583ec2ac291b8ec2afb10f0e32c4ac290148d3da15927787f8"}, - {file = "pyheck-0.1.5-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:aa8dfd0883212f8495e0bae6eb6ea670c56f9b197b5fe6fb5cae9fd5ec56fb7c"}, - {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b7c07506b9591e27f8241bf7a72bc4d5c4ac30dedb332efb87e402e49029f233"}, - {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:9ee256cafbdab6c5fcca22d0910176d820bf1e1298773e64f4eea79f51218cc7"}, - {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:e9ba36060abc55127c3813de398b4013c05be6118cfae3cfa3d978f7b4c84dea"}, - {file = "pyheck-0.1.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:64201a6d213bec443aeb33f66c60cea61aaf6257e48a19159ac69a5afad4768e"}, - {file = "pyheck-0.1.5-cp37-abi3-win32.whl", hash = "sha256:1501fcfd15f7c05c6bfe38915f5e514ac95fc63e945f7d8b089d30c1b8fdb2c5"}, - {file = "pyheck-0.1.5-cp37-abi3-win_amd64.whl", hash = "sha256:e519f80a0ef87a8f880bfdf239e396e238dcaed34bec1ea7ef526c4873220e82"}, - {file = "pyheck-0.1.5.tar.gz", hash = "sha256:5c9fe372d540c5dbcb76bf062f951d998d0e14c906c842a52f1cd5de208e183a"}, -] - -[[package]] -name = "pymultihash" -version = "0.8.2" -description = "Python implementation of the multihash specification" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pymultihash-0.8.2-py3-none-any.whl", hash = "sha256:f7fa840b24bd6acbd6b073fcd330f10e15619387297babf1dd13ca4dae6e8209"}, - {file = "pymultihash-0.8.2.tar.gz", hash = "sha256:49c75a1ae9ecc6d22d259064d4597b3685da3f0258f4ded632e03a3a79af215b"}, -] - -[package.extras] -blake2 = ["pyblake2"] -sha3 = ["pysha3"] - -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - -[[package]] -name = "pyrsistent" -version = "0.20.0" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, - {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, - {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, - {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, - {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, - {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, - {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, -] - -[[package]] -name = "pytest" -version = "7.2.1" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pytest-7.2.1-py3-none-any.whl", hash = "sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5"}, - {file = "pytest-7.2.1.tar.gz", hash = "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"}, -] - -[package.dependencies] -attrs = ">=19.2.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.21.2" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b"}, - {file = "pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45"}, -] - -[package.dependencies] -pytest = ">=7.0.0" - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] - -[[package]] -name = "pytest-cov" -version = "4.0.0" -description = "Pytest plugin for measuring coverage." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, - {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, -] - -[package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] - -[[package]] -name = "pytest-randomly" -version = "3.12.0" -description = "Pytest plugin to randomly order tests and control random.seed." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pytest-randomly-3.12.0.tar.gz", hash = "sha256:d60c2db71ac319aee0fc6c4110a7597d611a8b94a5590918bfa8583f00caccb2"}, - {file = "pytest_randomly-3.12.0-py3-none-any.whl", hash = "sha256:f4f2e803daf5d1ba036cc22bf4fe9dbbf99389ec56b00e5cba732fb5c1d07fdd"}, -] - -[package.dependencies] -pytest = "*" - -[[package]] -name = "pytest-rerunfailures" -version = "11.0" -description = "pytest plugin to re-run tests to eliminate flaky failures" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pytest-rerunfailures-11.0.tar.gz", hash = "sha256:cee59e4e6f0d73ae63fba099865314ba9b915b719349541110fa012ffb6efb13"}, - {file = "pytest_rerunfailures-11.0-py3-none-any.whl", hash = "sha256:b8c535b6c353de8c4b39258216512c64f288e4d349e86877583a08b2f5ea5441"}, -] - -[package.dependencies] -packaging = ">=17.1" -pytest = ">=5.3" - -[[package]] -name = "pytest-xprocess" -version = "0.18.1" -description = "A pytest plugin for managing processes across test runs." -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "pytest-xprocess-0.18.1.tar.gz", hash = "sha256:fd9f30ed1584b5833bc34494748adf0fb9de3ca7bacc4e88ad71989c21cba266"}, - {file = "pytest_xprocess-0.18.1-py3-none-any.whl", hash = "sha256:6f2aba817d842518d9d9dfb7e9adfe2a6e354a4359f4166bef0822ef4be1c9db"}, -] - -[package.dependencies] -psutil = "*" -pytest = ">=2.8" - -[[package]] -name = "python-baseconv" -version = "1.2.2" -description = "Convert numbers from base 10 integers to base X strings and back again." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "python-baseconv-1.2.2.tar.gz", hash = "sha256:0539f8bd0464013b05ad62e0a1673f0ac9086c76b43ebf9f833053527cd9931b"}, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-dotenv" -version = "0.21.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, - {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "pyunormalize" -version = "16.0.0" -description = "Unicode normalization forms (NFC, NFKC, NFD, NFKD). A library independent of the Python core Unicode database." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "pyunormalize-16.0.0-py3-none-any.whl", hash = "sha256:c647d95e5d1e2ea9a2f448d1d95d8518348df24eab5c3fd32d2b5c3300a49152"}, - {file = "pyunormalize-16.0.0.tar.gz", hash = "sha256:2e1dfbb4a118154ae26f70710426a52a364b926c9191f764601f5a8cb12761f7"}, -] - -[[package]] -name = "pywin32" -version = "308" -description = "Python for Window Extensions" -optional = false -python-versions = "*" -groups = ["main"] -markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" -files = [ - {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, - {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, - {file = "pywin32-308-cp310-cp310-win_arm64.whl", hash = "sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c"}, - {file = "pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a"}, - {file = "pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b"}, - {file = "pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6"}, - {file = "pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897"}, - {file = "pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47"}, - {file = "pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091"}, - {file = "pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed"}, - {file = "pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4"}, - {file = "pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd"}, - {file = "pywin32-308-cp37-cp37m-win32.whl", hash = "sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff"}, - {file = "pywin32-308-cp37-cp37m-win_amd64.whl", hash = "sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6"}, - {file = "pywin32-308-cp38-cp38-win32.whl", hash = "sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0"}, - {file = "pywin32-308-cp38-cp38-win_amd64.whl", hash = "sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de"}, - {file = "pywin32-308-cp39-cp39-win32.whl", hash = "sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341"}, - {file = "pywin32-308-cp39-cp39-win_amd64.whl", hash = "sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "regex" -version = "2024.11.6" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, - {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, - {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, - {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, - {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, - {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, - {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, - {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, - {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, - {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, - {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, - {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, - {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, - {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, -] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -description = "A utility belt for advanced users of python-requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, - {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, -] - -[package.dependencies] -requests = ">=2.0.1,<3.0.0" - -[[package]] -name = "rfc3986" -version = "1.5.0" -description = "Validating URI References per RFC 3986" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, - {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, -] - -[package.dependencies] -idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} - -[package.extras] -idna2008 = ["idna"] - -[[package]] -name = "rich" -version = "13.9.4" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, - {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "rich-click" -version = "1.8.6" -description = "Format click help output nicely with rich" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "rich_click-1.8.6-py3-none-any.whl", hash = "sha256:55fb571bad7d3d69ac43ca45f05b44616fd019616161b1815ff053567b9a8e22"}, - {file = "rich_click-1.8.6.tar.gz", hash = "sha256:8a2448fd80e3d4e16fcb3815bfbc19be9bae75c9bb6aedf637901e45f3555752"}, -] - -[package.dependencies] -click = ">=7" -rich = ">=10.7" -typing_extensions = ">=4" - -[package.extras] -dev = ["mypy", "packaging", "pre-commit", "pytest", "pytest-cov", "rich-codex", "ruff", "types-setuptools"] -docs = ["markdown_include", "mkdocs", "mkdocs-glightbox", "mkdocs-material-extensions", "mkdocs-material[imaging] (>=9.5.18,<9.6.0)", "mkdocs-rss-plugin", "mkdocstrings[python]", "rich-codex"] - -[[package]] -name = "rlp" -version = "3.0.0" -description = "A package for Recursive Length Prefix encoding and decoding" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "rlp-3.0.0-py2.py3-none-any.whl", hash = "sha256:d2a963225b3f26795c5b52310e0871df9824af56823d739511583ef459895a7d"}, - {file = "rlp-3.0.0.tar.gz", hash = "sha256:63b0465d2948cd9f01de449d7adfb92d207c1aef3982f20310f8009be4a507e8"}, -] - -[package.dependencies] -eth-utils = ">=2.0.0,<3" - -[package.extras] -dev = ["Sphinx (>=1.6.5,<2)", "bumpversion (>=0.5.3,<1)", "flake8 (==3.4.1)", "hypothesis (==5.19.0)", "ipython", "pytest (>=6.2.5,<7)", "pytest-watch (>=4.1.0,<5)", "pytest-xdist", "setuptools (>=36.2.0)", "sphinx-rtd-theme (>=0.1.9)", "tox (>=2.9.1,<3)", "twine", "wheel"] -doc = ["Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)"] -lint = ["flake8 (==3.4.1)"] -rust-backend = ["rusty-rlp (>=0.2.1,<0.3)"] -test = ["hypothesis (==5.19.0)", "pytest (>=6.2.5,<7)", "tox (>=2.9.1,<3)"] - -[[package]] -name = "ruff" -version = "0.5.7" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a"}, - {file = "ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be"}, - {file = "ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e"}, - {file = "ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a"}, - {file = "ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3"}, - {file = "ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4"}, - {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, -] - -[[package]] -name = "schema" -version = "0.7.7" -description = "Simple data validation library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "schema-0.7.7-py2.py3-none-any.whl", hash = "sha256:5d976a5b50f36e74e2157b47097b60002bd4d42e65425fcc9c9befadb4255dde"}, - {file = "schema-0.7.7.tar.gz", hash = "sha256:7da553abd2958a19dc2547c388cde53398b39196175a9be59ea1caf5ab0a1807"}, -] - -[[package]] -name = "semver" -version = "2.13.0" -description = "Python helper for Semantic Versioning (http://semver.org/)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4"}, - {file = "semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f"}, -] - -[[package]] -name = "setuptools" -version = "75.8.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "setuptools-75.8.2-py3-none-any.whl", hash = "sha256:558e47c15f1811c1fa7adbd0096669bf76c1d3f433f58324df69f3f5ecac4e8f"}, - {file = "setuptools-75.8.2.tar.gz", hash = "sha256:4880473a969e5f23f2a2be3646b2dfd84af9028716d398e46192f84bc36900d2"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] -core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "solana" -version = "0.30.2" -description = "Solana Python API" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "solana-0.30.2-py3-none-any.whl", hash = "sha256:d7e8295a1f86982ba51e78a65c16ce55f4a9e9caa8938564922a209ddfb2a01f"}, - {file = "solana-0.30.2.tar.gz", hash = "sha256:7b16e76cdd1d3024219679cdb73c20324d6d79e3c9766fe0ca52be79ef5ff691"}, -] - -[package.dependencies] -cachetools = ">=4.2.2,<5.0.0" -construct-typing = ">=0.5.2,<0.6.0" -httpx = ">=0.23.0,<0.24.0" -solders = ">=0.18.0,<0.19.0" -types-cachetools = ">=4.2.4,<5.0.0" -typing-extensions = ">=4.2.0" -websockets = ">=9.0,<12.0" - -[[package]] -name = "solders" -version = "0.18.1" -description = "Python bindings for Solana Rust tools" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "solders-0.18.1-cp37-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:1b20230838626fad26d5bdaf8ebe3db3b660ef9f56cc271feca8970d464ea11f"}, - {file = "solders-0.18.1-cp37-abi3-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3d2503693d0fb0efd37e3f921277327ff664bd04fff551346fad565dd8b9185a"}, - {file = "solders-0.18.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ee08cd1de84463b83551810981c25dcca4aa42ab57b8ba823d62dbab9d202"}, - {file = "solders-0.18.1-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b78482deeed583b473e70314336d26562b5f2f14fa777a83b9406835eb3e988"}, - {file = "solders-0.18.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3da01fcfcfd2154ff41328a3b7a32db655f8aace4ca146a7bf779c6088866daf"}, - {file = "solders-0.18.1-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:0b6bd026bdfce27daacefa405f0e46f44f9e8dd7e60fd36d23278b08a0f40482"}, - {file = "solders-0.18.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:02788caa3b82e846944a37f86dc673b6c9d80108679f44109f6c7acfd98808ec"}, - {file = "solders-0.18.1-cp37-abi3-win_amd64.whl", hash = "sha256:1587231b57a94e29df3945fa2582817cdb1c935c7cc3b446140ae4154912d1e6"}, - {file = "solders-0.18.1.tar.gz", hash = "sha256:1b41c36e331e2323ed4be1253fda2221391956b4a528270acfbf921e2a3f0329"}, -] - -[package.dependencies] -jsonalias = "0.1.1" -typing-extensions = ">=4.2.0" - -[[package]] -name = "sortedcontainers" -version = "2.4.0" -description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] - -[[package]] -name = "sumtypes" -version = "0.1a6" -description = "Algebraic types for Python (notably providing Sum Types, aka Tagged Unions)" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "sumtypes-0.1a6-py2.py3-none-any.whl", hash = "sha256:3e9d71322dd927d25d935072f8be7daec655ea292fd392359a5bb2c1e53dfdc3"}, - {file = "sumtypes-0.1a6.tar.gz", hash = "sha256:1a6ff095e06a1885f340ddab803e0f38e3f9bed81f9090164ca9682e04e96b43"}, -] - -[package.dependencies] -attrs = "*" - -[[package]] -name = "tabulate" -version = "0.9.0" -description = "Pretty-print tabular data" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, - {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, -] - -[package.extras] -widechars = ["wcwidth"] - -[[package]] -name = "tbump" -version = "6.11.0" -description = "Bump software releases" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "tbump-6.11.0-py3-none-any.whl", hash = "sha256:6b181fe6f3ae84ce0b9af8cc2009a8bca41ded34e73f623a7413b9684f1b4526"}, - {file = "tbump-6.11.0.tar.gz", hash = "sha256:385e710eedf0a8a6ff959cf1e9f3cfd17c873617132fc0ec5f629af0c355c870"}, -] - -[package.dependencies] -cli-ui = ">=0.10.3" -docopt = ">=0.6.2,<0.7.0" -schema = ">=0.7.1,<0.8.0" -tomlkit = ">=0.11,<0.12" - -[[package]] -name = "texttable" -version = "1.6.7" -description = "module to create simple ASCII tables" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "texttable-1.6.7-py2.py3-none-any.whl", hash = "sha256:b7b68139aa8a6339d2c320ca8b1dc42d13a7831a346b446cb9eb385f0c76310c"}, - {file = "texttable-1.6.7.tar.gz", hash = "sha256:290348fb67f7746931bcdfd55ac7584ecd4e5b0846ab164333f0794b121760f2"}, -] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - -[[package]] -name = "tomli" -version = "2.2.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_full_version <= \"3.11.0a6\"" -files = [ - {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, - {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, - {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, - {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, - {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, - {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, - {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, - {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, - {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, - {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, -] - -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "tomte" -version = "0.2.17" -description = "A library that wraps many useful tools (linters, analysers, etc) to keep Python code clean, secure, well-documented and optimised." -optional = false -python-versions = "<4,>=3.8" -groups = ["main"] -files = [ - {file = "tomte-0.2.17-py3-none-any.whl", hash = "sha256:477e1e903610b5e2a8cf74a78cf229eacc21aa666e25e7bb872385ef2c013cfe"}, - {file = "tomte-0.2.17.tar.gz", hash = "sha256:ad583dd39f2c398272f7f196471b2ecc8430eb89e07295ec1e682f64dd782831"}, -] - -[package.dependencies] -black = {version = "23.1.0", optional = true, markers = "extra == \"black\""} -click = {version = ">=8.1.0,<9", optional = true, markers = "extra == \"black\" or extra == \"cli\" or extra == \"docs\""} -pytest = {version = "7.2.1", optional = true, markers = "extra == \"tests\""} -pytest-asyncio = {version = ">=0.21.0,<0.22.0", optional = true, markers = "extra == \"tests\""} -pytest-cov = {version = "4.0.0", optional = true, markers = "extra == \"tests\""} -pytest-randomly = {version = "3.12.0", optional = true, markers = "extra == \"tests\""} -pytest-rerunfailures = {version = "11.0", optional = true, markers = "extra == \"tests\""} -requests = {version = ">=2.28.1,<3", optional = true, markers = "extra == \"cli\""} -tox = {version = "3.28.0", optional = true, markers = "extra == \"cli\" or extra == \"tox\""} - -[package.extras] -bandit = ["bandit (==1.7.4)"] -black = ["black (==23.1.0)", "click (>=8.1.0,<9)"] -cli = ["click (>=8.1.0,<9)", "requests (>=2.28.1,<3)", "tox (==3.28.0)"] -darglint = ["darglint (==1.8.1)"] -docs = ["Markdown (==3.3.7)", "Pygments (>=2.16,<3.0)", "bs4 (==0.0.1)", "click (>=8.1.0,<9)", "markdown-include (==0.8.0)", "mkdocs (>=1.5.3,<2.0)", "mkdocs-macros-plugin (==0.7.0)", "mkdocs-material (==9.4.10)", "mkdocs-material-extensions (==1.3)", "mkdocs-redirects (==1.2.0)", "pydoc-markdown (==4.8.2)", "pydocstyle (==6.2.3)", "pymdown-extensions (>=10.2,<11.0)"] -flake8 = ["flake8 (==3.9.2)", "flake8-bugbear (==23.1.14)", "flake8-docstrings (==1.6.0)", "flake8-eradicate (==1.4.0)", "flake8-isort (==6.0.0)", "pydocstyle (==6.2.3)"] -isort = ["isort (==5.11.4)"] -liccheck = ["liccheck (==0.8.3)"] -mypy = ["mypy (==0.991)"] -pylint = ["pylint (==2.13.9)"] -safety = ["safety (==2.4.0b1)"] -tests = ["pytest (==7.2.1)", "pytest-asyncio (>=0.21.0,<0.22.0)", "pytest-cov (==4.0.0)", "pytest-randomly (==3.12.0)", "pytest-rerunfailures (==11.0)"] -tox = ["tox (==3.28.0)"] -vulture = ["vulture (==2.7)"] - -[[package]] -name = "toolz" -version = "0.11.2" -description = "List processing tools and functional utilities" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "toolz-0.11.2-py3-none-any.whl", hash = "sha256:a5700ce83414c64514d82d60bcda8aabfde092d1c1a8663f9200c07fdcc6da8f"}, - {file = "toolz-0.11.2.tar.gz", hash = "sha256:6b312d5e15138552f1bda8a4e66c30e236c831b612b2bf0005f8a1df10a4bc33"}, -] - -[[package]] -name = "tox" -version = "3.28.0" -description = "tox is a generic virtualenv management and test command line tool" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -groups = ["main"] -files = [ - {file = "tox-3.28.0-py2.py3-none-any.whl", hash = "sha256:57b5ab7e8bb3074edc3c0c0b4b192a4f3799d3723b2c5b76f1fa9f2d40316eea"}, - {file = "tox-3.28.0.tar.gz", hash = "sha256:d0d28f3fe6d6d7195c27f8b054c3e99d5451952b54abdae673b71609a581f640"}, -] - -[package.dependencies] -colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""} -filelock = ">=3.0.0" -packaging = ">=14" -pluggy = ">=0.12.0" -py = ">=1.4.17" -six = ">=1.14.0" -tomli = {version = ">=2.0.1", markers = "python_version >= \"3.7\" and python_version < \"3.11\""} -virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" - -[package.extras] -docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] -testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3) ; python_version < \"3.4\"", "psutil (>=5.6.1) ; platform_python_implementation == \"cpython\"", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)"] - -[[package]] -name = "types-cachetools" -version = "4.2.10" -description = "Typing stubs for cachetools" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "types-cachetools-4.2.10.tar.gz", hash = "sha256:b1cb18aaff25d2ad47a060413c660c39fadddb01f72012dd1134584b1fdaada5"}, - {file = "types_cachetools-4.2.10-py3-none-any.whl", hash = "sha256:48301115189d4879d0960baac5a8a2b2d31ce6129b2ce3b915000ed337284898"}, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "unidecode" -version = "1.3.8" -description = "ASCII transliterations of Unicode text" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "Unidecode-1.3.8-py3-none-any.whl", hash = "sha256:d130a61ce6696f8148a3bd8fe779c99adeb4b870584eeb9526584e9aa091fd39"}, - {file = "Unidecode-1.3.8.tar.gz", hash = "sha256:cfdb349d46ed3873ece4586b96aa75258726e2fa8ec21d6f00a591d98806c2f4"}, -] - -[[package]] -name = "urllib3" -version = "2.3.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, - {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "valory-docker-compose" -version = "1.29.3" -description = "Multi-container orchestration for Docker" -optional = false -python-versions = ">=3.4" -groups = ["main"] -files = [ - {file = "valory-docker-compose-1.29.3.tar.gz", hash = "sha256:77469ff7493e0317ccc8d92264323d62eee23c810536184d705b833e0cbb6a03"}, - {file = "valory_docker_compose-1.29.3-py2.py3-none-any.whl", hash = "sha256:7f5d1eceb080d0512e2f5d16b57eaaf9a742b02da0878b71041217ec7cef53fe"}, -] - -[package.dependencies] -colorama = {version = ">=0.4,<1", markers = "sys_platform == \"win32\""} -distro = ">=1.5.0,<2" -docker = {version = ">=5", extras = ["ssh"]} -dockerpty = ">=0.4.1,<1" -docopt = ">=0.6.1,<1" -jsonschema = ">=2.5.1,<5" -python-dotenv = ">=0.13.0,<1" -PyYAML = ">=3.10,<=6.0.1" -requests = ">=2.20.0,<3" -texttable = ">=0.9.0,<2" -websocket-client = ">=0.32.0,<1" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2)"] -tests = ["ddt (>=1.2.2,<2)", "pytest (<6)"] - -[[package]] -name = "varint" -version = "1.0.2" -description = "Simple python varint implementation" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "varint-1.0.2.tar.gz", hash = "sha256:a6ecc02377ac5ee9d65a6a8ad45c9ff1dac8ccee19400a5950fb51d594214ca5"}, -] - -[[package]] -name = "virtualenv" -version = "20.29.2" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"}, - {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<5" - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] - -[[package]] -name = "watchdog" -version = "6.0.0" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, - {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, - {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, - {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, - {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, - {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, - {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, - {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, - {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, - {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, - {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "web3" -version = "6.20.4" -description = "web3.py" -optional = false -python-versions = ">=3.7.2" -groups = ["main"] -files = [ - {file = "web3-6.20.4-py3-none-any.whl", hash = "sha256:a6e1c428a54bf0fd398fbf006d00235898aed794476177ce73f7db177d2ad16c"}, - {file = "web3-6.20.4.tar.gz", hash = "sha256:7f3cdceca369be3eb959ce3905783cd021a0786f40c60b01e40ae2ba538e6e3f"}, -] - -[package.dependencies] -aiohttp = ">=3.7.4.post0" -ckzg = "<2" -eth-abi = ">=4.0.0" -eth-account = ">=0.8.0,<0.13" -eth-hash = {version = ">=0.5.1", extras = ["pycryptodome"]} -eth-typing = ">=3.0.0,<4.2.0 || >4.2.0,<5.0.0" -eth-utils = ">=2.1.0,<5" -hexbytes = ">=0.1.0,<0.4.0" -jsonschema = ">=4.0.0" -lru-dict = ">=1.1.6,<1.3.0" -protobuf = ">=4.21.6" -pyunormalize = ">=15.0.0" -pywin32 = {version = ">=223", markers = "platform_system == \"Windows\""} -requests = ">=2.16.0" -typing-extensions = ">=4.0.1" -websockets = ">=10.0.0,<14.0.0" - -[package.extras] -dev = ["build (>=0.9.0)", "bumpversion", "eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "flaky (>=3.7.0)", "hypothesis (>=3.31.2)", "importlib-metadata (<5.0) ; python_version < \"3.8\"", "ipfshttpclient (==0.8.0a2)", "pre-commit (>=2.21.0)", "py-geth (>=3.14.0,<4)", "pytest (>=7.0.0)", "pytest-asyncio (>=0.21.2,<0.23)", "pytest-mock (>=1.10)", "pytest-watch (>=4.2)", "pytest-xdist (>=1.29)", "setuptools (>=38.6.0)", "sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=3.18.0)", "tqdm (>4.32)", "twine (>=1.13)", "when-changed (>=0.3.0)"] -docs = ["sphinx (>=5.3.0)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=21,<22)"] -ipfs = ["ipfshttpclient (==0.8.0a2)"] -tester = ["eth-tester[py-evm] (>=0.11.0b1,<0.12.0b1) ; python_version > \"3.7\"", "eth-tester[py-evm] (>=0.9.0b1,<0.10.0b1) ; python_version <= \"3.7\"", "py-geth (>=3.14.0,<4)"] - -[[package]] -name = "websocket-client" -version = "0.59.0" -description = "WebSocket client for Python with low level API options" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "websocket-client-0.59.0.tar.gz", hash = "sha256:d376bd60eace9d437ab6d7ee16f4ab4e821c9dae591e1b783c58ebd8aaf80c5c"}, - {file = "websocket_client-0.59.0-py2.py3-none-any.whl", hash = "sha256:2e50d26ca593f70aba7b13a489435ef88b8fc3b5c5643c1ce8808ff9b40f0b32"}, -] - -[package.dependencies] -six = "*" - -[[package]] -name = "websockets" -version = "10.4" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, - {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, - {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, - {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, - {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, - {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, - {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, - {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, - {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, - {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, - {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, - {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, - {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, - {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, - {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, - {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, - {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, - {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, - {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, - {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, - {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, - {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, - {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, - {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, - {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, - {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, - {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, - {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, - {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, - {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, - {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, - {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, - {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, - {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, - {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, - {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, - {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, - {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, - {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, - {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, - {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, - {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, - {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, -] - -[[package]] -name = "werkzeug" -version = "2.0.3" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "Werkzeug-2.0.3-py3-none-any.whl", hash = "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8"}, - {file = "Werkzeug-2.0.3.tar.gz", hash = "sha256:b863f8ff057c522164b6067c9e28b041161b4be5ba4d0daceeaa50a163822d3c"}, -] - -[package.extras] -watchdog = ["watchdog"] - -[[package]] -name = "yarl" -version = "1.18.3" -description = "Yet another URL library" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, - {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, - {file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"}, - {file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"}, - {file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"}, - {file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"}, - {file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"}, - {file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"}, - {file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"}, - {file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"}, - {file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"}, - {file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"}, - {file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"}, - {file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"}, - {file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -propcache = ">=0.2.0" - -[[package]] -name = "zstandard" -version = "0.18.0" -description = "Zstandard bindings for Python" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "zstandard-0.18.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef7e8a200e4c8ac9102ed3c90ed2aa379f6b880f63032200909c1be21951f556"}, - {file = "zstandard-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2dc466207016564805e56d28375f4f533b525ff50d6776946980dff5465566ac"}, - {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a2ee1d4f98447f3e5183ecfce5626f983504a4a0c005fbe92e60fa8e5d547ec"}, - {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d956e2f03c7200d7e61345e0880c292783ec26618d0d921dcad470cb195bbce2"}, - {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ce6f59cba9854fd14da5bfe34217a1501143057313966637b7291d1b0267bd1e"}, - {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7fa67cba473623848b6e88acf8d799b1906178fd883fb3a1da24561c779593b"}, - {file = "zstandard-0.18.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdb44d7284c8c5dd1b66dfb86dda7f4560fa94bfbbc1d2da749ba44831335e32"}, - {file = "zstandard-0.18.0-cp310-cp310-win32.whl", hash = "sha256:63694a376cde0aa8b1971d06ca28e8f8b5f492779cb6ee1cc46bbc3f019a42a5"}, - {file = "zstandard-0.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:702a8324cd90c74d9c8780d02bf55e79da3193c870c9665ad3a11647e3ad1435"}, - {file = "zstandard-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46f679bc5dfd938db4fb058218d9dc4db1336ffaf1ea774ff152ecadabd40805"}, - {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc2a4de9f363b3247d472362a65041fe4c0f59e01a2846b15d13046be866a885"}, - {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd3220d7627fd4d26397211cb3b560ec7cc4a94b75cfce89e847e8ce7fabe32d"}, - {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:39e98cf4773234bd9cebf9f9db730e451dfcfe435e220f8921242afda8321887"}, - {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5228e596eb1554598c872a337bbe4e5afe41cd1f8b1b15f2e35b50d061e35244"}, - {file = "zstandard-0.18.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d4a8fd45746a6c31e729f35196e80b8f1e9987c59f5ccb8859d7c6a6fbeb9c63"}, - {file = "zstandard-0.18.0-cp36-cp36m-win32.whl", hash = "sha256:4cbb85f29a990c2fdbf7bc63246567061a362ddca886d7fae6f780267c0a9e67"}, - {file = "zstandard-0.18.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bfa6c8549fa18e6497a738b7033c49f94a8e2e30c5fbe2d14d0b5aa8bbc1695d"}, - {file = "zstandard-0.18.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e02043297c1832f2666cd2204f381bef43b10d56929e13c42c10c732c6e3b4ed"}, - {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7231543d38d2b7e02ef7cc78ef7ffd86419437e1114ff08709fe25a160e24bd6"}, - {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c86befac87445927488f5c8f205d11566f64c11519db223e9d282b945fa60dab"}, - {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999a4e1768f219826ba3fa2064fab1c86dd72fdd47a42536235478c3bb3ca3e2"}, - {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9df59cd1cf3c62075ee2a4da767089d19d874ac3ad42b04a71a167e91b384722"}, - {file = "zstandard-0.18.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1be31e9e3f7607ee0cdd60915410a5968b205d3e7aa83b7fcf3dd76dbbdb39e0"}, - {file = "zstandard-0.18.0-cp37-cp37m-win32.whl", hash = "sha256:490d11b705b8ae9dc845431bacc8dd1cef2408aede176620a5cd0cd411027936"}, - {file = "zstandard-0.18.0-cp37-cp37m-win_amd64.whl", hash = "sha256:266aba27fa9cc5e9091d3d325ebab1fa260f64e83e42516d5e73947c70216a5b"}, - {file = "zstandard-0.18.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b2260c4e07dd0723eadb586de7718b61acca4083a490dda69c5719d79bc715c"}, - {file = "zstandard-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3af8c2383d02feb6650e9255491ec7d0824f6e6dd2bbe3e521c469c985f31fb1"}, - {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28723a1d2e4df778573b76b321ebe9f3469ac98988104c2af116dd344802c3f8"}, - {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19cac7108ff2c342317fad6dc97604b47a41f403c8f19d0bfc396dfadc3638b8"}, - {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:76725d1ee83a8915100a310bbad5d9c1fc6397410259c94033b8318d548d9990"}, - {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d716a7694ce1fa60b20bc10f35c4a22be446ef7f514c8dbc8f858b61976de2fb"}, - {file = "zstandard-0.18.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:49685bf9a55d1ab34bd8423ea22db836ba43a181ac6b045ac4272093d5cb874e"}, - {file = "zstandard-0.18.0-cp38-cp38-win32.whl", hash = "sha256:1af1268a7dc870eb27515fb8db1f3e6c5a555d2b7bcc476fc3bab8886c7265ab"}, - {file = "zstandard-0.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:1dc2d3809e763055a1a6c1a73f2b677320cc9a5aa1a7c6cfb35aee59bddc42d9"}, - {file = "zstandard-0.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eea18c1e7442f2aa9aff1bb84550dbb6a1f711faf6e48e7319de8f2b2e923c2a"}, - {file = "zstandard-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8677ffc6a6096cccbd892e558471c901fd821aba12b7fbc63833c7346f549224"}, - {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083dc08abf03807af9beeb2b6a91c23ad78add2499f828176a3c7b742c44df02"}, - {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c990063664c08169c84474acecc9251ee035871589025cac47c060ff4ec4bc1a"}, - {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:533db8a6fac6248b2cb2c935e7b92f994efbdeb72e1ffa0b354432e087bb5a3e"}, - {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb3cb8a082d62b8a73af42291569d266b05605e017a3d8a06a0e5c30b5f10f0"}, - {file = "zstandard-0.18.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d6c85ca5162049ede475b7ec98e87f9390501d44a3d6776ddd504e872464ec25"}, - {file = "zstandard-0.18.0-cp39-cp39-win32.whl", hash = "sha256:75479e7c2b3eebf402c59fbe57d21bc400cefa145ca356ee053b0a08908c5784"}, - {file = "zstandard-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:d85bfabad444812133a92fc6fbe463e1d07581dba72f041f07a360e63808b23c"}, - {file = "zstandard-0.18.0.tar.gz", hash = "sha256:0ac0357a0d985b4ff31a854744040d7b5754385d1f98f7145c30e02c6865cb6f"}, -] - -[package.dependencies] -cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""} - -[package.extras] -cffi = ["cffi (>=1.11)"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.10,<3.13" -content-hash = "4bca5d49773631ae3e70b50cba0bc76179f6cede4519e87005aa2b4eb975b139" diff --git a/auto_dev/data/repo/templates/autonomy/pyproject.toml.template b/auto_dev/data/repo/templates/autonomy/pyproject.toml.template deleted file mode 100644 index 2077b21b..00000000 --- a/auto_dev/data/repo/templates/autonomy/pyproject.toml.template +++ /dev/null @@ -1,31 +0,0 @@ -[tool.poetry] -name = "{project_name}" -version = "0.1.0" -description = "" -authors = ["{author}"] -readme = "README.md" -license = "Apache-2.0" -classifiers = [ - 'License :: OSI Approved :: Apache Software License', - 'Natural Language :: English', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', -] -package-mode = false - -[tool.poetry.dependencies] -python = ">=3.10,<3.13" -open-aea-ledger-solana = "==1.65.0" -open-aea-ledger-cosmos = "==1.65.0" -open-aea-ledger-ethereum = "==1.65.0" -open-aea = "==1.65.0" -open-aea-cli-ipfs = "==1.65.0" -open-aea-test-autonomy = "==0.19.7" -open-autonomy = "==0.19.7" -autonomy-dev = {{extras = ["all"], version = ">=0.2.64,<=0.2.153"}} - -[tool.poetry.group.dev.dependencies] - -[build-system] -build-backend = "poetry.core.masonry.api" -requires = ["poetry-core>=1.0.0", "setuptools"] From ba91caf057819a1bac334c81627db361f023f803 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:56:30 +0200 Subject: [PATCH 186/189] fix: write non-empty __init__.py in python repo scaffold --- auto_dev/commands/repo.py | 2 +- auto_dev/data/repo/templates/python/tests/__init__.py.template | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/auto_dev/commands/repo.py b/auto_dev/commands/repo.py index ba941796..4f37ebd5 100644 --- a/auto_dev/commands/repo.py +++ b/auto_dev/commands/repo.py @@ -337,7 +337,7 @@ def scaffold_new_repo(logger, name, type_of_repo, force, auto_approve, install, src_dir = Path(name) src_dir.mkdir(exist_ok=False) logger.debug(f"Scaffolding `{src_dir!s}`") - (src_dir / "__init__.py").touch() + (src_dir / "__init__.py").write_text(f'"""{name.capitalize()} module."""') (src_dir / "main.py").write_text(SAMPLE_PYTHON_MAIN_FILE) (src_dir / "cli.py").write_text(SAMPLE_PYTHON_CLI_FILE.format(project_name=name)) else: diff --git a/auto_dev/data/repo/templates/python/tests/__init__.py.template b/auto_dev/data/repo/templates/python/tests/__init__.py.template index e69de29b..b13d5c88 100644 --- a/auto_dev/data/repo/templates/python/tests/__init__.py.template +++ b/auto_dev/data/repo/templates/python/tests/__init__.py.template @@ -0,0 +1 @@ +"""Tests module""" From 5ca335f1d591aac84414e724d0fb5a491041243f Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:57:21 +0200 Subject: [PATCH 187/189] chore: remove [tool.poetry.dev-dependencies] from python pyproject.toml.template --- auto_dev/data/repo/templates/python/pyproject.toml.template | 2 -- 1 file changed, 2 deletions(-) diff --git a/auto_dev/data/repo/templates/python/pyproject.toml.template b/auto_dev/data/repo/templates/python/pyproject.toml.template index b1eb8a1d..45398d9c 100644 --- a/auto_dev/data/repo/templates/python/pyproject.toml.template +++ b/auto_dev/data/repo/templates/python/pyproject.toml.template @@ -19,8 +19,6 @@ classifiers = [ python = ">=3.10,<3.14" autonomy-dev = {{extras = ["all"], version = ">=0.2.64,<=0.2.153"}} -[tool.poetry.dev-dependencies] - [tool.poetry.extras] dev = ["pre-commit", "virtualenv", "pip", "twine", "toml", "bump2version"] From 7212ace9f2d64074adf0265e2c99250627dafd3a Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:57:52 +0200 Subject: [PATCH 188/189] refactor: test_repo.py --- tests/test_repo.py | 77 +++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/tests/test_repo.py b/tests/test_repo.py index 132086d2..e7b232d1 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -1,69 +1,56 @@ """Tests for the click cli.""" -import subprocess import subprocess from pathlib import Path -import toml -import pytest -from aea.cli.utils.config import get_default_author_from_cli_config - -from auto_dev.utils import change_dir - - -def test_python_repo(cli_runner, test_clean_filesystem): - repo_root = Path(test_clean_filesystem) / "dummy_python" +def _test_repo_scaffold(repo_type, make_commands, cli_runner, test_clean_filesystem): - command = ["adev", "repo", "scaffold", repo_root.name, "-t", "python"] + repo_root = Path(test_clean_filesystem) / "dummy" + command = ["adev", "repo", "scaffold", repo_root.name, "-t", repo_type] runner = cli_runner(command) result = runner.execute() makefile = repo_root / "Makefile" + # Verify the basic repository structure exists assert result, runner.output - assert repo_root.exists() - assert (repo_root / ".git").exists() - assert makefile.exists() + assert repo_root.exists(), f"Repository {repo_root} does not exist." + assert (repo_root / ".git").exists(), f".git directory not found in {repo_root}." + assert makefile.exists(), f"Makefile not found in {repo_root}." + # Run each make command and collect any errors. error_messages = {} - make_commands = "fmt", "lint", "test" - for command in make_commands: - result = subprocess.run( - ["make", command], + for cmd in make_commands: + proc_result = subprocess.run( + ["make", cmd], shell=False, capture_output=True, text=True, check=False, + cwd=repo_root, ) - if not runner.return_code == 0: - error_messages[command] = runner.stderr - assert not error_messages + if proc_result.returncode != 0: + error_messages[cmd] = proc_result.stderr + assert not error_messages, f"Errors encountered in make commands: {error_messages}" -def test_autonomy_repo(cli_runner, test_clean_filesystem): +def test_python_repo(cli_runner, test_clean_filesystem): + """Test scaffolding a Python repository.""" - repo_root = Path(test_clean_filesystem) / "dummy_autonomy" + _test_repo_scaffold( + repo_type="python", + make_commands=("fmt", "lint", "test"), + cli_runner=cli_runner, + test_clean_filesystem=test_clean_filesystem, + ) - command = ["adev", "repo", "scaffold", repo_root.name, "-t", "autonomy"] - runner = cli_runner(command) - result = runner.execute() - makefile = repo_root / "Makefile" - assert result, runner.output - assert repo_root.exists() - assert (repo_root / ".git").exists() - assert makefile.exists() - - error_messages = {} - make_commands = "fmt", "lint", "test", "hashes" - for command in make_commands: - result = subprocess.run( - ["make", command], - shell=False, - capture_output=True, - text=True, - check=False, - ) - if not runner.return_code == 0: - error_messages[command] = runner.stderr - assert not error_messages +def test_autonomy_repo(cli_runner, test_clean_filesystem): + """Test scaffolding an Autonomy repository.""" + + _test_repo_scaffold( + repo_type="autonomy", + make_commands=("fmt", "lint", "test", "hashes"), + cli_runner=cli_runner, + test_clean_filesystem=test_clean_filesystem, + ) From 26da704764d7760071e5bc0a1306b82df9578c84 Mon Sep 17 00:00:00 2001 From: zarathustra Date: Mon, 14 Apr 2025 21:59:12 +0200 Subject: [PATCH 189/189] chore: make fmt lint --- tests/conftest.py | 2 +- tests/test_repo.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e1457acd..5abc5bd5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -75,7 +75,7 @@ def test_filesystem(monkeypatch): @pytest.fixture -def test_clean_filesystem(monkeypatch): +def test_clean_filesystem(): """Fixture for invoking command-line interfaces.""" with isolated_filesystem() as directory: yield directory diff --git a/tests/test_repo.py b/tests/test_repo.py index e7b232d1..a2eab91d 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -5,7 +5,6 @@ def _test_repo_scaffold(repo_type, make_commands, cli_runner, test_clean_filesystem): - repo_root = Path(test_clean_filesystem) / "dummy" command = ["adev", "repo", "scaffold", repo_root.name, "-t", repo_type] runner = cli_runner(command)