betterproto2-compiler 0.2.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- betterproto2_compiler/__init__.py +0 -0
- betterproto2_compiler/casing.py +140 -0
- betterproto2_compiler/compile/__init__.py +0 -0
- betterproto2_compiler/compile/importing.py +180 -0
- betterproto2_compiler/compile/naming.py +21 -0
- betterproto2_compiler/known_types/__init__.py +14 -0
- betterproto2_compiler/known_types/any.py +36 -0
- betterproto2_compiler/known_types/duration.py +25 -0
- betterproto2_compiler/known_types/timestamp.py +45 -0
- betterproto2_compiler/lib/__init__.py +0 -0
- betterproto2_compiler/lib/google/__init__.py +0 -0
- betterproto2_compiler/lib/google/protobuf/__init__.py +3338 -0
- betterproto2_compiler/lib/google/protobuf/compiler/__init__.py +235 -0
- betterproto2_compiler/lib/message_pool.py +3 -0
- betterproto2_compiler/plugin/__init__.py +3 -0
- betterproto2_compiler/plugin/__main__.py +3 -0
- betterproto2_compiler/plugin/compiler.py +70 -0
- betterproto2_compiler/plugin/main.py +47 -0
- betterproto2_compiler/plugin/models.py +643 -0
- betterproto2_compiler/plugin/module_validation.py +156 -0
- betterproto2_compiler/plugin/parser.py +272 -0
- betterproto2_compiler/plugin/plugin.bat +2 -0
- betterproto2_compiler/plugin/typing_compiler.py +163 -0
- betterproto2_compiler/py.typed +0 -0
- betterproto2_compiler/settings.py +9 -0
- betterproto2_compiler/templates/header.py.j2 +59 -0
- betterproto2_compiler/templates/template.py.j2 +258 -0
- betterproto2_compiler-0.2.0.dist-info/LICENSE.md +22 -0
- betterproto2_compiler-0.2.0.dist-info/METADATA +35 -0
- betterproto2_compiler-0.2.0.dist-info/RECORD +32 -0
- betterproto2_compiler-0.2.0.dist-info/WHEEL +4 -0
- betterproto2_compiler-0.2.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,258 @@
|
|
1
|
+
{% for _, enum in output_file.enums|dictsort(by="key") %}
|
2
|
+
class {{ enum.py_name }}(betterproto2.Enum):
|
3
|
+
{% if enum.comment %}
|
4
|
+
"""
|
5
|
+
{{ enum.comment | indent(4) }}
|
6
|
+
"""
|
7
|
+
{% endif %}
|
8
|
+
|
9
|
+
{% for entry in enum.entries %}
|
10
|
+
{{ entry.name }} = {{ entry.value }}
|
11
|
+
{% if entry.comment %}
|
12
|
+
"""
|
13
|
+
{{ entry.comment | indent(4) }}
|
14
|
+
"""
|
15
|
+
{% endif %}
|
16
|
+
|
17
|
+
{% endfor %}
|
18
|
+
|
19
|
+
{% if output_file.settings.pydantic_dataclasses %}
|
20
|
+
@classmethod
|
21
|
+
def __get_pydantic_core_schema__(cls, _source_type, _handler):
|
22
|
+
from pydantic_core import core_schema
|
23
|
+
|
24
|
+
return core_schema.int_schema(ge=0)
|
25
|
+
{% endif %}
|
26
|
+
|
27
|
+
{% endfor %}
|
28
|
+
{% for _, message in output_file.messages|dictsort(by="key") %}
|
29
|
+
{% if output_file.settings.pydantic_dataclasses %}
|
30
|
+
@dataclass(eq=False, repr=False, config={"extra": "forbid"})
|
31
|
+
{% else %}
|
32
|
+
@dataclass(eq=False, repr=False)
|
33
|
+
{% endif %}
|
34
|
+
class {{ message.py_name }}(betterproto2.Message):
|
35
|
+
{% if message.comment or message.oneofs %}
|
36
|
+
"""
|
37
|
+
{{ message.comment | indent(4) }}
|
38
|
+
{% if message.oneofs %}
|
39
|
+
|
40
|
+
Oneofs:
|
41
|
+
{% for oneof in message.oneofs %}
|
42
|
+
- {{ oneof.name }}: {{ oneof.comment | indent(12) }}
|
43
|
+
{% endfor %}
|
44
|
+
{% endif %}
|
45
|
+
"""
|
46
|
+
{% endif %}
|
47
|
+
|
48
|
+
{% for field in message.fields %}
|
49
|
+
{{ field.get_field_string() }}
|
50
|
+
{% if field.comment %}
|
51
|
+
"""
|
52
|
+
{{ field.comment | indent(4) }}
|
53
|
+
"""
|
54
|
+
{% endif %}
|
55
|
+
|
56
|
+
{% endfor %}
|
57
|
+
|
58
|
+
{% if not message.fields %}
|
59
|
+
pass
|
60
|
+
{% endif %}
|
61
|
+
|
62
|
+
{% if message.deprecated or message.has_deprecated_fields %}
|
63
|
+
def __post_init__(self) -> None:
|
64
|
+
{% if message.deprecated %}
|
65
|
+
warnings.warn("{{ message.py_name }} is deprecated", DeprecationWarning)
|
66
|
+
{% endif %}
|
67
|
+
super().__post_init__()
|
68
|
+
{% for field in message.deprecated_fields %}
|
69
|
+
if self.is_set("{{ field }}"):
|
70
|
+
warnings.warn("{{ message.py_name }}.{{ field }} is deprecated", DeprecationWarning)
|
71
|
+
{% endfor %}
|
72
|
+
{% endif %}
|
73
|
+
|
74
|
+
{% if output_file.settings.pydantic_dataclasses and message.has_oneof_fields %}
|
75
|
+
@model_validator(mode='after')
|
76
|
+
def check_oneof(cls, values):
|
77
|
+
return cls._validate_field_groups(values)
|
78
|
+
|
79
|
+
{% endif %}
|
80
|
+
{% for method_source in message.custom_methods %}
|
81
|
+
{{ method_source }}
|
82
|
+
{% endfor %}
|
83
|
+
|
84
|
+
default_message_pool.register_message("{{ output_file.package }}", "{{ message.proto_name }}", {{ message.py_name }})
|
85
|
+
|
86
|
+
|
87
|
+
{% endfor %}
|
88
|
+
{% for _, service in output_file.services|dictsort(by="key") %}
|
89
|
+
class {{ service.py_name }}Stub(betterproto2.ServiceStub):
|
90
|
+
{% if service.comment %}
|
91
|
+
"""
|
92
|
+
{{ service.comment | indent(4) }}
|
93
|
+
"""
|
94
|
+
{% elif not service.methods %}
|
95
|
+
pass
|
96
|
+
{% endif %}
|
97
|
+
|
98
|
+
{% for method in service.methods %}
|
99
|
+
async def {{ method.py_name }}(self
|
100
|
+
{%- if not method.client_streaming -%}
|
101
|
+
, {{ method.py_input_message_param }}:
|
102
|
+
{%- if method.is_input_msg_empty -%}
|
103
|
+
"{{ output_file.settings.typing_compiler.optional(method.py_input_message_type) }}" = None
|
104
|
+
{%- else -%}
|
105
|
+
"{{ method.py_input_message_type }}"
|
106
|
+
{%- endif -%}
|
107
|
+
{%- else -%}
|
108
|
+
{# Client streaming: need a request iterator instead #}
|
109
|
+
, {{ method.py_input_message_param }}_iterator: "{{ output_file.settings.typing_compiler.union(output_file.settings.typing_compiler.async_iterable(method.py_input_message_type), output_file.settings.typing_compiler.iterable(method.py_input_message_type)) }}"
|
110
|
+
{%- endif -%}
|
111
|
+
,
|
112
|
+
*
|
113
|
+
, timeout: {{ output_file.settings.typing_compiler.optional("float") }} = None
|
114
|
+
, deadline: "{{ output_file.settings.typing_compiler.optional("Deadline") }}" = None
|
115
|
+
, metadata: "{{ output_file.settings.typing_compiler.optional("MetadataLike") }}" = None
|
116
|
+
) -> "{% if method.server_streaming %}{{ output_file.settings.typing_compiler.async_iterator(method.py_output_message_type ) }}{% else %}{{ method.py_output_message_type }}{% endif %}":
|
117
|
+
{% if method.comment %}
|
118
|
+
"""
|
119
|
+
{{ method.comment | indent(8) }}
|
120
|
+
"""
|
121
|
+
{% endif %}
|
122
|
+
|
123
|
+
{% if method.deprecated %}
|
124
|
+
warnings.warn("{{ service.py_name }}.{{ method.py_name }} is deprecated", DeprecationWarning)
|
125
|
+
{% endif %}
|
126
|
+
|
127
|
+
{% if method.server_streaming %}
|
128
|
+
{% if method.client_streaming %}
|
129
|
+
async for response in self._stream_stream(
|
130
|
+
"{{ method.route }}",
|
131
|
+
{{ method.py_input_message_param }}_iterator,
|
132
|
+
{{ method.py_input_message_type }},
|
133
|
+
{{ method.py_output_message_type }},
|
134
|
+
timeout=timeout,
|
135
|
+
deadline=deadline,
|
136
|
+
metadata=metadata,
|
137
|
+
):
|
138
|
+
yield response
|
139
|
+
{% else %}{# i.e. not client streaming #}
|
140
|
+
{% if method.is_input_msg_empty %}
|
141
|
+
if {{ method.py_input_message_param }} is None:
|
142
|
+
{{ method.py_input_message_param }} = {{ method.py_input_message_type }}()
|
143
|
+
|
144
|
+
{% endif %}
|
145
|
+
async for response in self._unary_stream(
|
146
|
+
"{{ method.route }}",
|
147
|
+
{{ method.py_input_message_param }},
|
148
|
+
{{ method.py_output_message_type }},
|
149
|
+
timeout=timeout,
|
150
|
+
deadline=deadline,
|
151
|
+
metadata=metadata,
|
152
|
+
):
|
153
|
+
yield response
|
154
|
+
|
155
|
+
{% endif %}{# if client streaming #}
|
156
|
+
{% else %}{# i.e. not server streaming #}
|
157
|
+
{% if method.client_streaming %}
|
158
|
+
return await self._stream_unary(
|
159
|
+
"{{ method.route }}",
|
160
|
+
{{ method.py_input_message_param }}_iterator,
|
161
|
+
{{ method.py_input_message_type }},
|
162
|
+
{{ method.py_output_message_type }},
|
163
|
+
timeout=timeout,
|
164
|
+
deadline=deadline,
|
165
|
+
metadata=metadata,
|
166
|
+
)
|
167
|
+
{% else %}{# i.e. not client streaming #}
|
168
|
+
{% if method.is_input_msg_empty %}
|
169
|
+
if {{ method.py_input_message_param }} is None:
|
170
|
+
{{ method.py_input_message_param }} = {{ method.py_input_message_type }}()
|
171
|
+
|
172
|
+
{% endif %}
|
173
|
+
return await self._unary_unary(
|
174
|
+
"{{ method.route }}",
|
175
|
+
{{ method.py_input_message_param }},
|
176
|
+
{{ method.py_output_message_type }},
|
177
|
+
timeout=timeout,
|
178
|
+
deadline=deadline,
|
179
|
+
metadata=metadata,
|
180
|
+
)
|
181
|
+
{% endif %}{# client streaming #}
|
182
|
+
{% endif %}
|
183
|
+
|
184
|
+
{% endfor %}
|
185
|
+
{% endfor %}
|
186
|
+
|
187
|
+
{% for i in output_file.imports_end %}
|
188
|
+
{{ i }}
|
189
|
+
{% endfor %}
|
190
|
+
|
191
|
+
{% for _, service in output_file.services|dictsort(by="key") %}
|
192
|
+
class {{ service.py_name }}Base(ServiceBase):
|
193
|
+
{% if service.comment %}
|
194
|
+
"""
|
195
|
+
{{ service.comment | indent(4) }}
|
196
|
+
"""
|
197
|
+
{% endif %}
|
198
|
+
|
199
|
+
{% for method in service.methods %}
|
200
|
+
async def {{ method.py_name }}(self
|
201
|
+
{%- if not method.client_streaming -%}
|
202
|
+
, {{ method.py_input_message_param }}: "{{ method.py_input_message_type }}"
|
203
|
+
{%- else -%}
|
204
|
+
{# Client streaming: need a request iterator instead #}
|
205
|
+
, {{ method.py_input_message_param }}_iterator: {{ output_file.settings.typing_compiler.async_iterator(method.py_input_message_type) }}
|
206
|
+
{%- endif -%}
|
207
|
+
) -> {% if method.server_streaming %}{{ output_file.settings.typing_compiler.async_iterator(method.py_output_message_type) }}{% else %}"{{ method.py_output_message_type }}"{% endif %}:
|
208
|
+
{% if method.comment %}
|
209
|
+
"""
|
210
|
+
{{ method.comment | indent(8) }}
|
211
|
+
"""
|
212
|
+
{% endif %}
|
213
|
+
|
214
|
+
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
215
|
+
|
216
|
+
{% endfor %}
|
217
|
+
|
218
|
+
{% for method in service.methods %}
|
219
|
+
async def __rpc_{{ method.py_name }}(self, stream: "grpclib.server.Stream[{{ method.py_input_message_type }}, {{ method.py_output_message_type }}]") -> None:
|
220
|
+
{% if not method.client_streaming %}
|
221
|
+
request = await stream.recv_message()
|
222
|
+
{% else %}
|
223
|
+
request = stream.__aiter__()
|
224
|
+
{% endif %}
|
225
|
+
{% if not method.server_streaming %}
|
226
|
+
response = await self.{{ method.py_name }}(request)
|
227
|
+
await stream.send_message(response)
|
228
|
+
{% else %}
|
229
|
+
await self._call_rpc_handler_server_stream(
|
230
|
+
self.{{ method.py_name }},
|
231
|
+
stream,
|
232
|
+
request,
|
233
|
+
)
|
234
|
+
{% endif %}
|
235
|
+
|
236
|
+
{% endfor %}
|
237
|
+
|
238
|
+
def __mapping__(self) -> {{ output_file.settings.typing_compiler.dict("str", "grpclib.const.Handler") }}:
|
239
|
+
return {
|
240
|
+
{% for method in service.methods %}
|
241
|
+
"{{ method.route }}": grpclib.const.Handler(
|
242
|
+
self.__rpc_{{ method.py_name }},
|
243
|
+
{% if not method.client_streaming and not method.server_streaming %}
|
244
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
245
|
+
{% elif not method.client_streaming and method.server_streaming %}
|
246
|
+
grpclib.const.Cardinality.UNARY_STREAM,
|
247
|
+
{% elif method.client_streaming and not method.server_streaming %}
|
248
|
+
grpclib.const.Cardinality.STREAM_UNARY,
|
249
|
+
{% else %}
|
250
|
+
grpclib.const.Cardinality.STREAM_STREAM,
|
251
|
+
{% endif %}
|
252
|
+
{{ method.py_input_message_type }},
|
253
|
+
{{ method.py_output_message_type }},
|
254
|
+
),
|
255
|
+
{% endfor %}
|
256
|
+
}
|
257
|
+
|
258
|
+
{% endfor %}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Daniel G. Taylor
|
4
|
+
Copyright (c) 2024 The betterproto contributors
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
SOFTWARE.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: betterproto2_compiler
|
3
|
+
Version: 0.2.0
|
4
|
+
Summary: Compiler for betterproto2
|
5
|
+
License: MIT
|
6
|
+
Keywords: protobuf,gRPC,compiler
|
7
|
+
Author: Adrien Vannson
|
8
|
+
Author-email: adrien.vannson@protonmail.com
|
9
|
+
Requires-Python: >=3.10,<4.0
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Requires-Dist: betterproto2 (>=0.2.1,<0.3.0)
|
17
|
+
Requires-Dist: grpclib (>=0.4.1,<0.5.0)
|
18
|
+
Requires-Dist: jinja2 (>=3.0.3)
|
19
|
+
Requires-Dist: ruff (>=0.7.4,<0.8.0)
|
20
|
+
Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
|
21
|
+
Project-URL: Repository, https://github.com/betterproto/python-betterproto2-compiler
|
22
|
+
Description-Content-Type: text/markdown
|
23
|
+
|
24
|
+
# Betterproto2 compiler
|
25
|
+
|
26
|
+
![](https://github.com/betterproto/python-betterproto2-compiler/actions/workflows/ci.yml/badge.svg)
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
## License
|
31
|
+
|
32
|
+
Copyright © 2019 Daniel G. Taylor
|
33
|
+
|
34
|
+
Copyright © 2024 The betterproto contributors
|
35
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
betterproto2_compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
betterproto2_compiler/casing.py,sha256=bMdI4W0hfYh6kV-DQIqFEjSfGYEqUtPciAzP64z5HLQ,3587
|
3
|
+
betterproto2_compiler/compile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
betterproto2_compiler/compile/importing.py,sha256=9S9cgbahqo_MuLcc60NrwIg2vJiaSfy7iiaRPNhjhGY,6958
|
5
|
+
betterproto2_compiler/compile/naming.py,sha256=zf0VOmNojzyv33upOGelGxjZTEDE8JULEEED5_3inHg,562
|
6
|
+
betterproto2_compiler/known_types/__init__.py,sha256=Exqo-3ubDuik0TZDTw5ZPqf-dVb2uPJTZxMG7X58E6U,780
|
7
|
+
betterproto2_compiler/known_types/any.py,sha256=QnfSKTXzazZwmsxaFu8_SYNmLww1D2mFdmi29_8Nzb4,1432
|
8
|
+
betterproto2_compiler/known_types/duration.py,sha256=jy9GPnQTT9qhi12pQDG_ptdFAdm2gYkq3NH75zUTDOU,895
|
9
|
+
betterproto2_compiler/known_types/timestamp.py,sha256=lw7kQPYJn76Q2wR4l3nCshj7VZ3s8h_xRcvrGIno4z0,2155
|
10
|
+
betterproto2_compiler/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
+
betterproto2_compiler/lib/google/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
betterproto2_compiler/lib/google/protobuf/__init__.py,sha256=ajfzhKfLLdrg1eESD9LR18chGNDI2EerRtjLTUnWxKY,109428
|
13
|
+
betterproto2_compiler/lib/google/protobuf/compiler/__init__.py,sha256=bWYhEcL4nz0_4H6FTCmN3F419FQWXkY49LGE2hJJ6jM,8906
|
14
|
+
betterproto2_compiler/lib/message_pool.py,sha256=4-cRhhiM6bmfpUJZ8qxc8LEyqHBHpLCcotjbyZxl7JM,71
|
15
|
+
betterproto2_compiler/plugin/__init__.py,sha256=L3pW0b4CvkM5x53x_sYt1kYiSFPO0_vaeH6EQPq9FAM,43
|
16
|
+
betterproto2_compiler/plugin/__main__.py,sha256=vBQ82334kX06ImDbFlPFgiBRiLIinwNk3z8Khs6hd74,31
|
17
|
+
betterproto2_compiler/plugin/compiler.py,sha256=3sPbCtdzjAGftVvoGe5dvxE8uTzJ78hABA-_f-1rEUo,2471
|
18
|
+
betterproto2_compiler/plugin/main.py,sha256=gI2fSWc9U-fn6MOlkLg7iResr2YsXbdOge6SzNWxBAo,1302
|
19
|
+
betterproto2_compiler/plugin/models.py,sha256=TNe96ANhRHRgz3GqGqUXmtSskaRM_T_JDrqW0nCjpBA,21755
|
20
|
+
betterproto2_compiler/plugin/module_validation.py,sha256=JnP8dSN83eJJVDP_UPJsHzq7E7Md3lah0PnKXDbFW5Q,4808
|
21
|
+
betterproto2_compiler/plugin/parser.py,sha256=tBw9eq8KZc5GWSVo3t3P88YiTBgL4Byc8cJnIP1K6kY,9958
|
22
|
+
betterproto2_compiler/plugin/plugin.bat,sha256=lfLT1WguAXqyerLLsRL6BfHA0RqUE6QG79v-1BYVSpI,48
|
23
|
+
betterproto2_compiler/plugin/typing_compiler.py,sha256=IK6m4ggHXK7HL98Ed_WjvQ_yeWfIpf_fIBZ9SA8UcyM,4873
|
24
|
+
betterproto2_compiler/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
+
betterproto2_compiler/settings.py,sha256=d7XTRMywahR9PcOgaycPXLkHgJMSYDffuSO874yyrh0,182
|
26
|
+
betterproto2_compiler/templates/header.py.j2,sha256=wYBR4yer77dTGM9e1RijuID-mI4GHrmk66OjdVvmBxc,1734
|
27
|
+
betterproto2_compiler/templates/template.py.j2,sha256=theRmdVVan3dtVuHLlScuirRRLv6ePb15Rr9e_fHaWU,9238
|
28
|
+
betterproto2_compiler-0.2.0.dist-info/LICENSE.md,sha256=Pgl2pReU-2yw2miGeQ55UFlyzqAZ_EpYVyZ2nWjwRv4,1121
|
29
|
+
betterproto2_compiler-0.2.0.dist-info/METADATA,sha256=ct3SrwUF43Ye01wvXDBUPAjlVgYmVC6YL24OXr8d-fE,1099
|
30
|
+
betterproto2_compiler-0.2.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
31
|
+
betterproto2_compiler-0.2.0.dist-info/entry_points.txt,sha256=re3Qg8lLljbVobeeKH2f1FVQZ114wfZkGv3zCZTD8Ok,84
|
32
|
+
betterproto2_compiler-0.2.0.dist-info/RECORD,,
|