From fc33ade7f8a67fcffe7369489d7c5ed424dacb31 Mon Sep 17 00:00:00 2001 From: Aidan Jensen Date: Mon, 17 Nov 2025 10:13:57 -0800 Subject: [PATCH] Add generate_concrete_servicer_stubs option Signed-off-by: Aidan Jensen --- .gitignore | 2 + CHANGELOG.md | 1 + README.md | 7 + mypy_protobuf/main.py | 28 +- pyproject.toml | 4 +- run_test.sh | 28 +- .../google/protobuf/duration_pb2.pyi | 136 ++++++ .../mypy_protobuf/extensions_pb2.pyi | 54 +++ .../testproto/Capitalized/Capitalized_pb2.pyi | 66 +++ .../testproto/comment_special_chars_pb2.pyi | 82 ++++ .../testproto/dot/com/test_pb2.pyi | 32 ++ .../testproto/grpc/dummy_pb2.pyi | 68 +++ .../testproto/grpc/dummy_pb2_grpc.pyi | 300 ++++++++++++ .../testproto/grpc/import_pb2.pyi | 8 + .../testproto/grpc/import_pb2_grpc.pyi | 158 +++++++ .../testproto/inner/inner_pb2.pyi | 33 ++ .../testproto/nested/nested_pb2.pyi | 96 ++++ .../testproto/nopackage_pb2.pyi | 52 +++ .../testproto/readme_enum_pb2.pyi | 32 ++ .../testproto/reexport_pb2.pyi | 19 + .../testproto/test3_pb2.pyi | 209 +++++++++ .../testproto/test_extensions2_pb2.pyi | 37 ++ .../testproto/test_extensions3_pb2.pyi | 46 ++ .../test_no_generic_services_pb2.pyi | 33 ++ .../generated-concrete/testproto/test_pb2.pyi | 439 ++++++++++++++++++ test/test_concrete.py | 8 + test/test_generated_mypy.py | 2 +- test_negative/negative.py | 8 + test_negative/output.expected.3.10 | 7 +- .../output.expected.3.10.omit_linenos | 3 +- test_negative/output.expected.3.11 | 7 +- .../output.expected.3.11.omit_linenos | 3 +- test_negative/output.expected.3.12 | 7 +- .../output.expected.3.12.omit_linenos | 3 +- test_negative/output.expected.3.13 | 7 +- .../output.expected.3.13.omit_linenos | 3 +- test_negative/output.expected.3.14 | 7 +- .../output.expected.3.14.omit_linenos | 3 +- test_negative/output.expected.3.9 | 7 +- .../output.expected.3.9.omit_linenos | 3 +- 40 files changed, 2013 insertions(+), 35 deletions(-) create mode 100644 test/generated-concrete/google/protobuf/duration_pb2.pyi create mode 100644 test/generated-concrete/mypy_protobuf/extensions_pb2.pyi create mode 100644 test/generated-concrete/testproto/Capitalized/Capitalized_pb2.pyi create mode 100644 test/generated-concrete/testproto/comment_special_chars_pb2.pyi create mode 100644 test/generated-concrete/testproto/dot/com/test_pb2.pyi create mode 100644 test/generated-concrete/testproto/grpc/dummy_pb2.pyi create mode 100644 test/generated-concrete/testproto/grpc/dummy_pb2_grpc.pyi create mode 100644 test/generated-concrete/testproto/grpc/import_pb2.pyi create mode 100644 test/generated-concrete/testproto/grpc/import_pb2_grpc.pyi create mode 100644 test/generated-concrete/testproto/inner/inner_pb2.pyi create mode 100644 test/generated-concrete/testproto/nested/nested_pb2.pyi create mode 100644 test/generated-concrete/testproto/nopackage_pb2.pyi create mode 100644 test/generated-concrete/testproto/readme_enum_pb2.pyi create mode 100644 test/generated-concrete/testproto/reexport_pb2.pyi create mode 100644 test/generated-concrete/testproto/test3_pb2.pyi create mode 100644 test/generated-concrete/testproto/test_extensions2_pb2.pyi create mode 100644 test/generated-concrete/testproto/test_extensions3_pb2.pyi create mode 100644 test/generated-concrete/testproto/test_no_generic_services_pb2.pyi create mode 100644 test/generated-concrete/testproto/test_pb2.pyi create mode 100644 test/test_concrete.py diff --git a/.gitignore b/.gitignore index a0190c29..18a5a134 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ __pycache__/ *.pyc /test/generated/**/*.py !/test/generated/**/__init__.py +/test/generated-concrete/**/*.py +!/test/generated-concrete/**/__init__.py .pytest_cache /build/ /dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md index d119fb2a..840fedb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - With some more work this could be added back in a testing refactor - Protobuf <6.32 still had the edition enums and field options, so it *should* still work. But is untested - Add support for editions (up to 2024) +- Add `generate_concrete_servicer_stubs` option to generate concrete instead of abstract servicer stubs ## 3.7.0 diff --git a/README.md b/README.md index 8af2b886..446f303a 100644 --- a/README.md +++ b/README.md @@ -337,7 +337,14 @@ and insert it into the deprecation warning. This option will instead use a stand ``` protoc --python_out=output/location --mypy_out=use_default_deprecation_warning:output/location +``` + +### `generate_concrete_servicer_stubs` +By default mypy-protobuf will output servicer stubs with abstract methods. To output concrete stubs, set this option + +``` +protoc --python_out=output/location --mypy_grpc_out=generate_concrete_servicer_stubs:output/location ``` ### Output suppression diff --git a/mypy_protobuf/main.py b/mypy_protobuf/main.py index 7dceae32..487f30f5 100644 --- a/mypy_protobuf/main.py +++ b/mypy_protobuf/main.py @@ -151,6 +151,7 @@ def __init__( readable_stubs: bool, relax_strict_optional_primitives: bool, use_default_deprecation_warnings: bool, + generate_concrete_servicer_stubs: bool, grpc: bool, ) -> None: self.fd = fd @@ -158,6 +159,7 @@ def __init__( self.readable_stubs = readable_stubs self.relax_strict_optional_primitives = relax_strict_optional_primitives self.use_default_depreaction_warnings = use_default_deprecation_warnings + self.generate_concrete_servicer_stubs = generate_concrete_servicer_stubs self.grpc = grpc self.lines: List[str] = [] self.indent = "" @@ -689,6 +691,7 @@ def write_services( self._import("google.protobuf.service", "Service"), self._import("abc", "ABCMeta"), ) + # The servicer interface with self._indent(): if self._write_comments(scl): wl("") @@ -850,7 +853,8 @@ def write_grpc_methods(self, service: d.ServiceDescriptorProto, scl_prefix: Sour for i, method in methods: scl = scl_prefix + [d.ServiceDescriptorProto.METHOD_FIELD_NUMBER, i] - wl("@{}", self._import("abc", "abstractmethod")) + if self.generate_concrete_servicer_stubs is False: + wl("@{}", self._import("abc", "abstractmethod")) wl("def {}(", method.name) with self._indent(): wl("self,") @@ -950,11 +954,17 @@ def write_grpc_services( scl + [d.ServiceDescriptorProto.OPTIONS_FIELD_NUMBER] + [d.ServiceOptions.DEPRECATED_FIELD_NUMBER], "This servicer has been marked as deprecated using proto service options.", ) - wl( - "class {}Servicer(metaclass={}):", - service.name, - self._import("abc", "ABCMeta"), - ) + if self.generate_concrete_servicer_stubs is False: + wl( + "class {}Servicer(metaclass={}):", + service.name, + self._import("abc", "ABCMeta"), + ) + else: + wl( + "class {}Servicer:", + service.name, + ) with self._indent(): if self._write_comments(scl): wl("") @@ -1126,6 +1136,7 @@ def generate_mypy_stubs( readable_stubs: bool, relax_strict_optional_primitives: bool, use_default_deprecation_warnings: bool, + generate_concrete_servicer_stubs: bool, ) -> None: for name, fd in descriptors.to_generate.items(): pkg_writer = PkgWriter( @@ -1134,6 +1145,7 @@ def generate_mypy_stubs( readable_stubs, relax_strict_optional_primitives, use_default_deprecation_warnings, + generate_concrete_servicer_stubs, grpc=False, ) @@ -1158,6 +1170,7 @@ def generate_mypy_grpc_stubs( readable_stubs: bool, relax_strict_optional_primitives: bool, use_default_deprecation_warnings: bool, + generate_concrete_servicer_stubs: bool, ) -> None: for name, fd in descriptors.to_generate.items(): pkg_writer = PkgWriter( @@ -1166,6 +1179,7 @@ def generate_mypy_grpc_stubs( readable_stubs, relax_strict_optional_primitives, use_default_deprecation_warnings, + generate_concrete_servicer_stubs, grpc=True, ) pkg_writer.write_grpc_async_hacks() @@ -1222,6 +1236,7 @@ def main() -> None: "readable_stubs" in request.parameter, "relax_strict_optional_primitives" in request.parameter, "use_default_deprecation_warnings" in request.parameter, + "generate_concrete_servicer_stubs" in request.parameter, ) @@ -1235,6 +1250,7 @@ def grpc() -> None: "readable_stubs" in request.parameter, "relax_strict_optional_primitives" in request.parameter, "use_default_deprecation_warnings" in request.parameter, + "generate_concrete_servicer_stubs" in request.parameter, ) diff --git a/pyproject.toml b/pyproject.toml index 10fbce77..ff1a16d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,11 +32,13 @@ include = [ ] exclude = [ "**/*_pb2.py", - "**/*_pb2_grpc.py" + "**/*_pb2_grpc.py", + "test/test_concrete.py" ] executionEnvironments = [ # Due to how upb is typed, we need to disable incompatible variable override checks { root = "test/generated", extraPaths = ["./"], reportIncompatibleVariableOverride = "none" }, + { root = "test/generated-concrete", extraPaths = ["./"], reportIncompatibleVariableOverride = "none" }, { root = "mypy_protobuf/extensions_pb2.pyi", reportIncompatibleVariableOverride = "none" }, ] diff --git a/run_test.sh b/run_test.sh index aac4fe50..f6426ac6 100755 --- a/run_test.sh +++ b/run_test.sh @@ -124,18 +124,26 @@ MYPY_PROTOBUF_VENV=venv_$PY_VER_MYPY_PROTOBUF find proto -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_out=readable_stubs:test/generated find proto -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_out=relax_strict_optional_primitives:test/generated find proto -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_out=use_default_deprecation_warnings:test/generated + find proto -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_out=generate_concrete_servicer_stubs:test/generated # Overwrite w/ run with mypy-protobuf without flags find proto -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_out=test/generated # Generate grpc protos find proto/testproto/grpc -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_grpc_out=test/generated + # Generate with concrete service stubs for testing + find proto -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_out=generate_concrete_servicer_stubs:test/generated-concrete + find proto/testproto/grpc -name "*.proto" -print0 | xargs -0 "$PROTOC" "${PROTOC_ARGS[@]}" --mypy_grpc_out=generate_concrete_servicer_stubs:test/generated-concrete + + if [[ -n $VALIDATE ]] && ! diff <(echo "$SHA_BEFORE") <(find test/generated -name "*.pyi" -print0 | xargs -0 sha1sum); then echo -e "${RED}Some .pyi files did not match. Please commit those files${NC}" exit 1 fi ) +ERRORS=() + for PY_VER in $PY_VER_UNIT_TESTS; do UNIT_TESTS_VENV=venv_$PY_VER PY_VER_MYPY_TARGET=$(echo "$PY_VER" | cut -d. -f1-2) @@ -149,6 +157,10 @@ for PY_VER in $PY_VER_UNIT_TESTS; do # Run mypy on unit tests / generated output ( source "$MYPY_VENV"/bin/activate + # Run concrete mypy + CONCRETE_MODULES=( -m test.test_concrete ) + MYPYPATH=$MYPYPATH:test/generated-concrete mypy ${CUSTOM_TYPESHED_DIR_ARG:+"$CUSTOM_TYPESHED_DIR_ARG"} --python-executable="$UNIT_TESTS_VENV"/bin/python --python-version="$PY_VER_MYPY_TARGET" "${CONCRETE_MODULES[@]}" + export MYPYPATH=$MYPYPATH:test/generated # Run mypy @@ -184,13 +196,13 @@ for PY_VER in $PY_VER_UNIT_TESTS; do call_mypy "$PY_VER" "${NEGATIVE_MODULES[@]}" if ! diff "$MYPY_OUTPUT/mypy_output" "test_negative/output.expected.$PY_VER_MYPY_TARGET" || ! diff "$MYPY_OUTPUT/mypy_output.omit_linenos" "test_negative/output.expected.$PY_VER_MYPY_TARGET.omit_linenos"; then - echo -e "${RED}test_negative/output.expected.$PY_VER_MYPY_TARGET didnt match. Copying over for you. Now rerun${NC}" - # Copy over all the mypy results for the developer. call_mypy "$PY_VER" "${NEGATIVE_MODULES[@]}" cp "$MYPY_OUTPUT/mypy_output" "test_negative/output.expected.$PY_VER_MYPY_TARGET" cp "$MYPY_OUTPUT/mypy_output.omit_linenos" "test_negative/output.expected.$PY_VER_MYPY_TARGET.omit_linenos" - exit 1 + + # Record error instead of echoing and exiting + ERRORS+=("test_negative/output.expected.$PY_VER_MYPY_TARGET didnt match. Copying over for you.") fi ) @@ -200,3 +212,13 @@ for PY_VER in $PY_VER_UNIT_TESTS; do PYTHONPATH=test/generated py.test --ignore=test/generated -v ) done + +# Report all errors at the end +if [ ${#ERRORS[@]} -gt 0 ]; then + echo -e "\n${RED}===============================================${NC}" + for error in "${ERRORS[@]}"; do + echo -e "${RED}$error${NC}" + done + echo -e "${RED}Now rerun${NC}" + exit 1 +fi diff --git a/test/generated-concrete/google/protobuf/duration_pb2.pyi b/test/generated-concrete/google/protobuf/duration_pb2.pyi new file mode 100644 index 00000000..c17deb5c --- /dev/null +++ b/test/generated-concrete/google/protobuf/duration_pb2.pyi @@ -0,0 +1,136 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +Protocol Buffers - Google's data interchange format +Copyright 2008 Google Inc. All rights reserved. +https://developers.google.com/protocol-buffers/ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.internal.well_known_types +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Duration(google.protobuf.message.Message, google.protobuf.internal.well_known_types.Duration): + """A Duration represents a signed, fixed-length span of time represented + as a count of seconds and fractions of seconds at nanosecond + resolution. It is independent of any calendar and concepts like "day" + or "month". It is related to Timestamp in that the difference between + two Timestamp values is a Duration and it can be added or subtracted + from a Timestamp. Range is approximately +-10,000 years. + + # Examples + + Example 1: Compute Duration from two Timestamps in pseudo code. + + Timestamp start = ...; + Timestamp end = ...; + Duration duration = ...; + + duration.seconds = end.seconds - start.seconds; + duration.nanos = end.nanos - start.nanos; + + if (duration.seconds < 0 && duration.nanos > 0) { + duration.seconds += 1; + duration.nanos -= 1000000000; + } else if (duration.seconds > 0 && duration.nanos < 0) { + duration.seconds -= 1; + duration.nanos += 1000000000; + } + + Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. + + Timestamp start = ...; + Duration duration = ...; + Timestamp end = ...; + + end.seconds = start.seconds + duration.seconds; + end.nanos = start.nanos + duration.nanos; + + if (end.nanos < 0) { + end.seconds -= 1; + end.nanos += 1000000000; + } else if (end.nanos >= 1000000000) { + end.seconds += 1; + end.nanos -= 1000000000; + } + + Example 3: Compute Duration from datetime.timedelta in Python. + + td = datetime.timedelta(days=3, minutes=10) + duration = Duration() + duration.FromTimedelta(td) + + # JSON Mapping + + In JSON format, the Duration type is encoded as a string rather than an + object, where the string ends in the suffix "s" (indicating seconds) and + is preceded by the number of seconds, with nanoseconds expressed as + fractional seconds. For example, 3 seconds with 0 nanoseconds should be + encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should + be expressed in JSON format as "3.000000001s", and 3 seconds and 1 + microsecond should be expressed in JSON format as "3.000001s". + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SECONDS_FIELD_NUMBER: builtins.int + NANOS_FIELD_NUMBER: builtins.int + seconds: builtins.int + """Signed seconds of the span of time. Must be from -315,576,000,000 + to +315,576,000,000 inclusive. Note: these bounds are computed from: + 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + """ + nanos: builtins.int + """Signed fractions of a second at nanosecond resolution of the span + of time. Durations less than one second are represented with a 0 + `seconds` field and a positive or negative `nanos` field. For durations + of one second or more, a non-zero value for the `nanos` field must be + of the same sign as the `seconds` field. Must be from -999,999,999 + to +999,999,999 inclusive. + """ + def __init__( + self, + *, + seconds: builtins.int = ..., + nanos: builtins.int = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["nanos", b"nanos", "seconds", b"seconds"]) -> None: ... + +Global___Duration: typing_extensions.TypeAlias = Duration diff --git a/test/generated-concrete/mypy_protobuf/extensions_pb2.pyi b/test/generated-concrete/mypy_protobuf/extensions_pb2.pyi new file mode 100644 index 00000000..bb6165cd --- /dev/null +++ b/test/generated-concrete/mypy_protobuf/extensions_pb2.pyi @@ -0,0 +1,54 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.descriptor_pb2 +import google.protobuf.internal.extension_dict +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class FieldOptions(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CASTTYPE_FIELD_NUMBER: builtins.int + KEYTYPE_FIELD_NUMBER: builtins.int + VALUETYPE_FIELD_NUMBER: builtins.int + casttype: builtins.str + """Tells mypy-protobuf to use a specific newtype rather than the normal type for this field.""" + keytype: builtins.str + """Tells mypy-protobuf to use a specific type for keys; only makes sense on map fields""" + valuetype: builtins.str + """Tells mypy-protobuf to use a specific type for values; only makes sense on map fields""" + def __init__( + self, + *, + casttype: builtins.str = ..., + keytype: builtins.str = ..., + valuetype: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["casttype", b"casttype", "keytype", b"keytype", "valuetype", b"valuetype"]) -> None: ... + +Global___FieldOptions: typing_extensions.TypeAlias = FieldOptions + +OPTIONS_FIELD_NUMBER: builtins.int +CASTTYPE_FIELD_NUMBER: builtins.int +KEYTYPE_FIELD_NUMBER: builtins.int +VALUETYPE_FIELD_NUMBER: builtins.int +options: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, Global___FieldOptions] +"""Custom field options from mypy-protobuf""" +casttype: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, builtins.str] +"""Legacy fields. Prefer to use ones within `options` instead.""" +keytype: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, builtins.str] +valuetype: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, builtins.str] diff --git a/test/generated-concrete/testproto/Capitalized/Capitalized_pb2.pyi b/test/generated-concrete/testproto/Capitalized/Capitalized_pb2.pyi new file mode 100644 index 00000000..828d26f2 --- /dev/null +++ b/test/generated-concrete/testproto/Capitalized/Capitalized_pb2.pyi @@ -0,0 +1,66 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class lower(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_FIELD_NUMBER: builtins.int + a: builtins.int + def __init__( + self, + *, + a: builtins.int = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["a", b"a"]) -> None: ... + +Global___lower: typing_extensions.TypeAlias = lower + +@typing.final +class Upper(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + LOWER_FIELD_NUMBER: builtins.int + @property + def Lower(self) -> Global___lower: ... + def __init__( + self, + *, + Lower: Global___lower | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["Lower", b"Lower"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["Lower", b"Lower"]) -> None: ... + +Global___Upper: typing_extensions.TypeAlias = Upper + +@typing.final +class lower2(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + UPPER_FIELD_NUMBER: builtins.int + @property + def upper(self) -> Global___Upper: ... + def __init__( + self, + *, + upper: Global___Upper | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["upper", b"upper"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["upper", b"upper"]) -> None: ... + +Global___lower2: typing_extensions.TypeAlias = lower2 diff --git a/test/generated-concrete/testproto/comment_special_chars_pb2.pyi b/test/generated-concrete/testproto/comment_special_chars_pb2.pyi new file mode 100644 index 00000000..21823424 --- /dev/null +++ b/test/generated-concrete/testproto/comment_special_chars_pb2.pyi @@ -0,0 +1,82 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Test(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_FIELD_NUMBER: builtins.int + B_FIELD_NUMBER: builtins.int + C_FIELD_NUMBER: builtins.int + D_FIELD_NUMBER: builtins.int + E_FIELD_NUMBER: builtins.int + F_FIELD_NUMBER: builtins.int + G_FIELD_NUMBER: builtins.int + H_FIELD_NUMBER: builtins.int + I_FIELD_NUMBER: builtins.int + J_FIELD_NUMBER: builtins.int + K_FIELD_NUMBER: builtins.int + a: builtins.str + """Ending with " """ + b: builtins.str + """Ending with "" """ + c: builtins.str + """Ending with \"\"\" """ + d: builtins.str + """Ending with \\ """ + e: builtins.str + """Containing bad escape: \\x""" + f: builtins.str + """Containing \"\"\"" quadruple""" + g: builtins.str + """Containing \"\"\""" quintuple""" + h: builtins.str + """Containing \"\"\"\"\"\" sextuple""" + i: builtins.str + """\"\"\" Multiple \"\"\" triples \"\"\" """ + j: builtins.str + """"quotes" can be a problem in comments. + \"\"\"Triple quotes\"\"\" just as well + """ + k: builtins.str + """\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" + " " + " Super Duper comments with surrounding edges! " + " " + " Pay attention to me!!!! " + " " + \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\" + """ + def __init__( + self, + *, + a: builtins.str = ..., + b: builtins.str = ..., + c: builtins.str = ..., + d: builtins.str = ..., + e: builtins.str = ..., + f: builtins.str = ..., + g: builtins.str = ..., + h: builtins.str = ..., + i: builtins.str = ..., + j: builtins.str = ..., + k: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["a", b"a", "b", b"b", "c", b"c", "d", b"d", "e", b"e", "f", b"f", "g", b"g", "h", b"h", "i", b"i", "j", b"j", "k", b"k"]) -> None: ... + +Global___Test: typing_extensions.TypeAlias = Test diff --git a/test/generated-concrete/testproto/dot/com/test_pb2.pyi b/test/generated-concrete/testproto/dot/com/test_pb2.pyi new file mode 100644 index 00000000..bb7e86c1 --- /dev/null +++ b/test/generated-concrete/testproto/dot/com/test_pb2.pyi @@ -0,0 +1,32 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class TestMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FOO_FIELD_NUMBER: builtins.int + foo: builtins.str + def __init__( + self, + *, + foo: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["foo", b"foo"]) -> None: ... + +Global___TestMessage: typing_extensions.TypeAlias = TestMessage diff --git a/test/generated-concrete/testproto/grpc/dummy_pb2.pyi b/test/generated-concrete/testproto/grpc/dummy_pb2.pyi new file mode 100644 index 00000000..ce03f2a5 --- /dev/null +++ b/test/generated-concrete/testproto/grpc/dummy_pb2.pyi @@ -0,0 +1,68 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +https://github.com/vmagamedov/grpclib/blob/master/tests/dummy.proto""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class DummyRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VALUE_FIELD_NUMBER: builtins.int + value: builtins.str + def __init__( + self, + *, + value: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["value", b"value"]) -> None: ... + +Global___DummyRequest: typing_extensions.TypeAlias = DummyRequest + +@typing.final +class DummyReply(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VALUE_FIELD_NUMBER: builtins.int + value: builtins.str + def __init__( + self, + *, + value: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["value", b"value"]) -> None: ... + +Global___DummyReply: typing_extensions.TypeAlias = DummyReply + +@deprecated("""This message has been marked as deprecated using proto message options.""") +@typing.final +class DeprecatedRequest(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + OLD_FIELD_FIELD_NUMBER: builtins.int + old_field: builtins.str + def __init__( + self, + *, + old_field: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["old_field", b"old_field"]) -> None: ... + +Global___DeprecatedRequest: typing_extensions.TypeAlias = DeprecatedRequest diff --git a/test/generated-concrete/testproto/grpc/dummy_pb2_grpc.pyi b/test/generated-concrete/testproto/grpc/dummy_pb2_grpc.pyi new file mode 100644 index 00000000..c9f53c74 --- /dev/null +++ b/test/generated-concrete/testproto/grpc/dummy_pb2_grpc.pyi @@ -0,0 +1,300 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +https://github.com/vmagamedov/grpclib/blob/master/tests/dummy.proto""" + +import abc +import collections.abc +import grpc +import grpc.aio +import sys +import testproto.grpc.dummy_pb2 +import typing + +if sys.version_info >= (3, 13): + import typing as typing_extensions +else: + import typing_extensions + +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated + +_T = typing.TypeVar("_T") + +class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ... + +class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg] + ... + +GRPC_GENERATED_VERSION: str +GRPC_VERSION: str +_DummyServiceUnaryUnaryType = typing_extensions.TypeVar( + '_DummyServiceUnaryUnaryType', + grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + default=grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +) + +_DummyServiceUnaryStreamType = typing_extensions.TypeVar( + '_DummyServiceUnaryStreamType', + grpc.UnaryStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + default=grpc.UnaryStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +) + +_DummyServiceStreamUnaryType = typing_extensions.TypeVar( + '_DummyServiceStreamUnaryType', + grpc.StreamUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.StreamUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + default=grpc.StreamUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +) + +_DummyServiceStreamStreamType = typing_extensions.TypeVar( + '_DummyServiceStreamStreamType', + grpc.StreamStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.StreamStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + default=grpc.StreamStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +) + +class DummyServiceStub(typing.Generic[_DummyServiceUnaryUnaryType, _DummyServiceUnaryStreamType, _DummyServiceStreamUnaryType, _DummyServiceStreamStreamType]): + """DummyService""" + + @typing.overload + def __init__(self: DummyServiceStub[ + grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.UnaryStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.StreamUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.StreamStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + ], channel: grpc.Channel) -> None: ... + + @typing.overload + def __init__(self: DummyServiceStub[ + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.StreamUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.StreamStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + ], channel: grpc.aio.Channel) -> None: ... + + UnaryUnary: _DummyServiceUnaryUnaryType + """UnaryUnary""" + + UnaryStream: _DummyServiceUnaryStreamType + """UnaryStream""" + + StreamUnary: _DummyServiceStreamUnaryType + """StreamUnary""" + + StreamStream: _DummyServiceStreamStreamType + """StreamStream""" + +DummyServiceAsyncStub: typing_extensions.TypeAlias = DummyServiceStub[ + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.StreamUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.StreamStreamMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +] + +class DummyServiceServicer: + """DummyService""" + + def UnaryUnary( + self, + request: testproto.grpc.dummy_pb2.DummyRequest, + context: _ServicerContext, + ) -> typing.Union[testproto.grpc.dummy_pb2.DummyReply, collections.abc.Awaitable[testproto.grpc.dummy_pb2.DummyReply]]: + """UnaryUnary""" + + def UnaryStream( + self, + request: testproto.grpc.dummy_pb2.DummyRequest, + context: _ServicerContext, + ) -> typing.Union[collections.abc.Iterator[testproto.grpc.dummy_pb2.DummyReply], collections.abc.AsyncIterator[testproto.grpc.dummy_pb2.DummyReply]]: + """UnaryStream""" + + def StreamUnary( + self, + request_iterator: _MaybeAsyncIterator[testproto.grpc.dummy_pb2.DummyRequest], + context: _ServicerContext, + ) -> typing.Union[testproto.grpc.dummy_pb2.DummyReply, collections.abc.Awaitable[testproto.grpc.dummy_pb2.DummyReply]]: + """StreamUnary""" + + def StreamStream( + self, + request_iterator: _MaybeAsyncIterator[testproto.grpc.dummy_pb2.DummyRequest], + context: _ServicerContext, + ) -> typing.Union[collections.abc.Iterator[testproto.grpc.dummy_pb2.DummyReply], collections.abc.AsyncIterator[testproto.grpc.dummy_pb2.DummyReply]]: + """StreamStream""" + +def add_DummyServiceServicer_to_server(servicer: DummyServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... + +_DeprecatedServiceDeprecatedMethodType = typing_extensions.TypeVar( + '_DeprecatedServiceDeprecatedMethodType', + grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DeprecatedRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DeprecatedRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + default=grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DeprecatedRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +) + +_DeprecatedServiceDeprecatedMethodNotDeprecatedRequestType = typing_extensions.TypeVar( + '_DeprecatedServiceDeprecatedMethodNotDeprecatedRequestType', + grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + default=grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +) + +@deprecated("""This service is deprecated""") +class DeprecatedServiceStub(typing.Generic[_DeprecatedServiceDeprecatedMethodType, _DeprecatedServiceDeprecatedMethodNotDeprecatedRequestType]): + """Marking the service as deprecated""" + + @typing.overload + def __init__(self: DeprecatedServiceStub[ + grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DeprecatedRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + ], channel: grpc.Channel) -> None: ... + + @typing.overload + def __init__(self: DeprecatedServiceStub[ + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DeprecatedRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + ], channel: grpc.aio.Channel) -> None: ... + + DeprecatedMethod: _DeprecatedServiceDeprecatedMethodType + """DeprecatedMethod""" + + DeprecatedMethodNotDeprecatedRequest: _DeprecatedServiceDeprecatedMethodNotDeprecatedRequestType + """DeprecatedMethodNotDeprecatedRequest""" + +DeprecatedServiceAsyncStub: typing_extensions.TypeAlias = DeprecatedServiceStub[ + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DeprecatedRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.grpc.dummy_pb2.DummyRequest, + testproto.grpc.dummy_pb2.DummyReply, + ], +] + +@deprecated("""This service is deprecated""") +class DeprecatedServiceServicer: + """Marking the service as deprecated""" + + def DeprecatedMethod( + self, + request: testproto.grpc.dummy_pb2.DeprecatedRequest, + context: _ServicerContext, + ) -> typing.Union[testproto.grpc.dummy_pb2.DummyReply, collections.abc.Awaitable[testproto.grpc.dummy_pb2.DummyReply]]: + """DeprecatedMethod""" + + def DeprecatedMethodNotDeprecatedRequest( + self, + request: testproto.grpc.dummy_pb2.DummyRequest, + context: _ServicerContext, + ) -> typing.Union[testproto.grpc.dummy_pb2.DummyReply, collections.abc.Awaitable[testproto.grpc.dummy_pb2.DummyReply]]: + """DeprecatedMethodNotDeprecatedRequest""" + +@deprecated("""This service is deprecated""") +def add_DeprecatedServiceServicer_to_server(servicer: DeprecatedServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... diff --git a/test/generated-concrete/testproto/grpc/import_pb2.pyi b/test/generated-concrete/testproto/grpc/import_pb2.pyi new file mode 100644 index 00000000..dd854e28 --- /dev/null +++ b/test/generated-concrete/testproto/grpc/import_pb2.pyi @@ -0,0 +1,8 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import google.protobuf.descriptor + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor diff --git a/test/generated-concrete/testproto/grpc/import_pb2_grpc.pyi b/test/generated-concrete/testproto/grpc/import_pb2_grpc.pyi new file mode 100644 index 00000000..c4710f1e --- /dev/null +++ b/test/generated-concrete/testproto/grpc/import_pb2_grpc.pyi @@ -0,0 +1,158 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import abc +import collections.abc +import google.protobuf.empty_pb2 +import grpc +import grpc.aio +import sys +import testproto.test_pb2 +import typing + +if sys.version_info >= (3, 13): + import typing as typing_extensions +else: + import typing_extensions + +_T = typing.TypeVar("_T") + +class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ... + +class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg] + ... + +GRPC_GENERATED_VERSION: str +GRPC_VERSION: str +_SimpleServiceUnaryUnaryType = typing_extensions.TypeVar( + '_SimpleServiceUnaryUnaryType', + grpc.UnaryUnaryMultiCallable[ + google.protobuf.empty_pb2.Empty, + testproto.test_pb2.Simple1, + ], + grpc.aio.UnaryUnaryMultiCallable[ + google.protobuf.empty_pb2.Empty, + testproto.test_pb2.Simple1, + ], + default=grpc.UnaryUnaryMultiCallable[ + google.protobuf.empty_pb2.Empty, + testproto.test_pb2.Simple1, + ], +) + +_SimpleServiceUnaryStreamType = typing_extensions.TypeVar( + '_SimpleServiceUnaryStreamType', + grpc.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + default=grpc.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], +) + +_SimpleServiceNoCommentType = typing_extensions.TypeVar( + '_SimpleServiceNoCommentType', + grpc.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + default=grpc.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], +) + +class SimpleServiceStub(typing.Generic[_SimpleServiceUnaryUnaryType, _SimpleServiceUnaryStreamType, _SimpleServiceNoCommentType]): + """SimpleService""" + + @typing.overload + def __init__(self: SimpleServiceStub[ + grpc.UnaryUnaryMultiCallable[ + google.protobuf.empty_pb2.Empty, + testproto.test_pb2.Simple1, + ], + grpc.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + grpc.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + ], channel: grpc.Channel) -> None: ... + + @typing.overload + def __init__(self: SimpleServiceStub[ + grpc.aio.UnaryUnaryMultiCallable[ + google.protobuf.empty_pb2.Empty, + testproto.test_pb2.Simple1, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + ], channel: grpc.aio.Channel) -> None: ... + + UnaryUnary: _SimpleServiceUnaryUnaryType + """UnaryUnary""" + + UnaryStream: _SimpleServiceUnaryStreamType + """UnaryStream""" + + NoComment: _SimpleServiceNoCommentType + +SimpleServiceAsyncStub: typing_extensions.TypeAlias = SimpleServiceStub[ + grpc.aio.UnaryUnaryMultiCallable[ + google.protobuf.empty_pb2.Empty, + testproto.test_pb2.Simple1, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], + grpc.aio.UnaryUnaryMultiCallable[ + testproto.test_pb2.Simple1, + google.protobuf.empty_pb2.Empty, + ], +] + +class SimpleServiceServicer: + """SimpleService""" + + def UnaryUnary( + self, + request: google.protobuf.empty_pb2.Empty, + context: _ServicerContext, + ) -> typing.Union[testproto.test_pb2.Simple1, collections.abc.Awaitable[testproto.test_pb2.Simple1]]: + """UnaryUnary""" + + def UnaryStream( + self, + request: testproto.test_pb2.Simple1, + context: _ServicerContext, + ) -> typing.Union[google.protobuf.empty_pb2.Empty, collections.abc.Awaitable[google.protobuf.empty_pb2.Empty]]: + """UnaryStream""" + + def NoComment( + self, + request: testproto.test_pb2.Simple1, + context: _ServicerContext, + ) -> typing.Union[google.protobuf.empty_pb2.Empty, collections.abc.Awaitable[google.protobuf.empty_pb2.Empty]]: ... + +def add_SimpleServiceServicer_to_server(servicer: SimpleServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ... diff --git a/test/generated-concrete/testproto/inner/inner_pb2.pyi b/test/generated-concrete/testproto/inner/inner_pb2.pyi new file mode 100644 index 00000000..dc705d20 --- /dev/null +++ b/test/generated-concrete/testproto/inner/inner_pb2.pyi @@ -0,0 +1,33 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys +import testproto.test3_pb2 +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Inner(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_FIELD_NUMBER: builtins.int + a: testproto.test3_pb2.OuterEnum.ValueType + def __init__( + self, + *, + a: testproto.test3_pb2.OuterEnum.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["a", b"a"]) -> None: ... + +Global___Inner: typing_extensions.TypeAlias = Inner diff --git a/test/generated-concrete/testproto/nested/nested_pb2.pyi b/test/generated-concrete/testproto/nested/nested_pb2.pyi new file mode 100644 index 00000000..e382df0a --- /dev/null +++ b/test/generated-concrete/testproto/nested/nested_pb2.pyi @@ -0,0 +1,96 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import sys +import testproto.test3_pb2 +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Nested(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_FIELD_NUMBER: builtins.int + a: testproto.test3_pb2.OuterEnum.ValueType + def __init__( + self, + *, + a: testproto.test3_pb2.OuterEnum.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["a", b"a"]) -> None: ... + +Global___Nested: typing_extensions.TypeAlias = Nested + +@typing.final +class AnotherNested(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _NestedEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _NestedEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[AnotherNested._NestedEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + INVALID: AnotherNested._NestedEnum.ValueType # 0 + ONE: AnotherNested._NestedEnum.ValueType # 1 + TWO: AnotherNested._NestedEnum.ValueType # 2 + + class NestedEnum(_NestedEnum, metaclass=_NestedEnumEnumTypeWrapper): ... + INVALID: AnotherNested.NestedEnum.ValueType # 0 + ONE: AnotherNested.NestedEnum.ValueType # 1 + TWO: AnotherNested.NestedEnum.ValueType # 2 + + @typing.final + class NestedMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _NestedEnum2: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _NestedEnum2EnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[AnotherNested.NestedMessage._NestedEnum2.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNDEFINED: AnotherNested.NestedMessage._NestedEnum2.ValueType # 0 + NESTED_ENUM1: AnotherNested.NestedMessage._NestedEnum2.ValueType # 1 + NESTED_ENUM2: AnotherNested.NestedMessage._NestedEnum2.ValueType # 2 + + class NestedEnum2(_NestedEnum2, metaclass=_NestedEnum2EnumTypeWrapper): ... + UNDEFINED: AnotherNested.NestedMessage.NestedEnum2.ValueType # 0 + NESTED_ENUM1: AnotherNested.NestedMessage.NestedEnum2.ValueType # 1 + NESTED_ENUM2: AnotherNested.NestedMessage.NestedEnum2.ValueType # 2 + + S_FIELD_NUMBER: builtins.int + B_FIELD_NUMBER: builtins.int + NE_FIELD_NUMBER: builtins.int + NE2_FIELD_NUMBER: builtins.int + s: builtins.str + b: builtins.bool + ne: Global___AnotherNested.NestedEnum.ValueType + ne2: Global___AnotherNested.NestedMessage.NestedEnum2.ValueType + def __init__( + self, + *, + s: builtins.str = ..., + b: builtins.bool = ..., + ne: Global___AnotherNested.NestedEnum.ValueType = ..., + ne2: Global___AnotherNested.NestedMessage.NestedEnum2.ValueType = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["b", b"b", "ne", b"ne", "ne2", b"ne2", "s", b"s"]) -> None: ... + + def __init__( + self, + ) -> None: ... + +Global___AnotherNested: typing_extensions.TypeAlias = AnotherNested diff --git a/test/generated-concrete/testproto/nopackage_pb2.pyi b/test/generated-concrete/testproto/nopackage_pb2.pyi new file mode 100644 index 00000000..7925439c --- /dev/null +++ b/test/generated-concrete/testproto/nopackage_pb2.pyi @@ -0,0 +1,52 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class NoPackage(google.protobuf.message.Message): + """Intentionally don't set a package - just to make sure we can handle it.""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +Global___NoPackage: typing_extensions.TypeAlias = NoPackage + +@typing.final +class NoPackage2(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + NP_FIELD_NUMBER: builtins.int + NP_REP_FIELD_NUMBER: builtins.int + @property + def np(self) -> Global___NoPackage: ... + @property + def np_rep(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___NoPackage]: ... + def __init__( + self, + *, + np: Global___NoPackage | None = ..., + np_rep: collections.abc.Iterable[Global___NoPackage] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["np", b"np"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["np", b"np", "np_rep", b"np_rep"]) -> None: ... + +Global___NoPackage2: typing_extensions.TypeAlias = NoPackage2 diff --git a/test/generated-concrete/testproto/readme_enum_pb2.pyi b/test/generated-concrete/testproto/readme_enum_pb2.pyi new file mode 100644 index 00000000..be8369c4 --- /dev/null +++ b/test/generated-concrete/testproto/readme_enum_pb2.pyi @@ -0,0 +1,32 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.internal.enum_type_wrapper +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class _MyEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _MyEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_MyEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + HELLO: _MyEnum.ValueType # 0 + WORLD: _MyEnum.ValueType # 1 + +class MyEnum(_MyEnum, metaclass=_MyEnumEnumTypeWrapper): ... + +HELLO: MyEnum.ValueType # 0 +WORLD: MyEnum.ValueType # 1 +Global___MyEnum: typing_extensions.TypeAlias = MyEnum diff --git a/test/generated-concrete/testproto/reexport_pb2.pyi b/test/generated-concrete/testproto/reexport_pb2.pyi new file mode 100644 index 00000000..9702c2bd --- /dev/null +++ b/test/generated-concrete/testproto/reexport_pb2.pyi @@ -0,0 +1,19 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import google.protobuf.descriptor +from google.protobuf.empty_pb2 import ( + Empty as Empty, +) +from testproto.test3_pb2 import ( + BAR3 as BAR3, + FOO3 as FOO3, + OuterEnum as OuterEnum, + OuterMessage3 as OuterMessage3, + SimpleProto3 as SimpleProto3, + UNKNOWN as UNKNOWN, +) + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor diff --git a/test/generated-concrete/testproto/test3_pb2.pyi b/test/generated-concrete/testproto/test3_pb2.pyi new file mode 100644 index 00000000..f239d860 --- /dev/null +++ b/test/generated-concrete/testproto/test3_pb2.pyi @@ -0,0 +1,209 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +package test3""" + +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.message +import sys +import test.test_generated_mypy +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class _OuterEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _OuterEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_OuterEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNKNOWN: _OuterEnum.ValueType # 0 + FOO3: _OuterEnum.ValueType # 1 + BAR3: _OuterEnum.ValueType # 2 + +class OuterEnum(_OuterEnum, metaclass=_OuterEnumEnumTypeWrapper): ... + +UNKNOWN: OuterEnum.ValueType # 0 +FOO3: OuterEnum.ValueType # 1 +BAR3: OuterEnum.ValueType # 2 +Global___OuterEnum: typing_extensions.TypeAlias = OuterEnum + +@typing.final +class OuterMessage3(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_STRING_FIELD_NUMBER: builtins.int + a_string: builtins.str + def __init__( + self, + *, + a_string: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["a_string", b"a_string"]) -> None: ... + +Global___OuterMessage3: typing_extensions.TypeAlias = OuterMessage3 + +@typing.final +class SimpleProto3(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _InnerEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _InnerEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SimpleProto3._InnerEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + INNER1: SimpleProto3._InnerEnum.ValueType # 0 + INNER2: SimpleProto3._InnerEnum.ValueType # 1 + + class InnerEnum(_InnerEnum, metaclass=_InnerEnumEnumTypeWrapper): ... + INNER1: SimpleProto3.InnerEnum.ValueType # 0 + INNER2: SimpleProto3.InnerEnum.ValueType # 1 + + @typing.final + class MapScalarEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.int + value: builtins.str + def __init__( + self, + *, + key: builtins.int = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ... + + @typing.final + class MapMessageEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.int + @property + def value(self) -> Global___OuterMessage3: ... + def __init__( + self, + *, + key: builtins.int = ..., + value: Global___OuterMessage3 | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ... + + @typing.final + class EmailByUidEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.int + value: builtins.str + def __init__( + self, + *, + key: builtins.int = ..., + value: builtins.str = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ... + + A_STRING_FIELD_NUMBER: builtins.int + A_REPEATED_STRING_FIELD_NUMBER: builtins.int + A_OUTER_ENUM_FIELD_NUMBER: builtins.int + OUTER_MESSAGE_FIELD_NUMBER: builtins.int + INNER_ENUM_FIELD_NUMBER: builtins.int + A_ONEOF_1_FIELD_NUMBER: builtins.int + A_ONEOF_2_FIELD_NUMBER: builtins.int + OUTER_MESSAGE_IN_ONEOF_FIELD_NUMBER: builtins.int + OUTER_ENUM_IN_ONEOF_FIELD_NUMBER: builtins.int + INNER_ENUM_IN_ONEOF_FIELD_NUMBER: builtins.int + B_ONEOF_1_FIELD_NUMBER: builtins.int + B_ONEOF_2_FIELD_NUMBER: builtins.int + BOOL_FIELD_NUMBER: builtins.int + OUTERENUM_FIELD_NUMBER: builtins.int + OUTERMESSAGE3_FIELD_NUMBER: builtins.int + MAP_SCALAR_FIELD_NUMBER: builtins.int + MAP_MESSAGE_FIELD_NUMBER: builtins.int + AN_OPTIONAL_STRING_FIELD_NUMBER: builtins.int + USER_ID_FIELD_NUMBER: builtins.int + EMAIL_FIELD_NUMBER: builtins.int + EMAIL_BY_UID_FIELD_NUMBER: builtins.int + a_string: builtins.str + a_outer_enum: Global___OuterEnum.ValueType + inner_enum: Global___SimpleProto3.InnerEnum.ValueType + a_oneof_1: builtins.str + a_oneof_2: builtins.str + outer_enum_in_oneof: Global___OuterEnum.ValueType + inner_enum_in_oneof: Global___SimpleProto3.InnerEnum.ValueType + b_oneof_1: builtins.str + b_oneof_2: builtins.str + OuterEnum: Global___OuterEnum.ValueType + """Test having fieldname match messagename""" + an_optional_string: builtins.str + user_id: test.test_generated_mypy.UserId + email: test.test_generated_mypy.Email + @property + def a_repeated_string(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + @property + def outer_message(self) -> Global___OuterMessage3: ... + @property + def outer_message_in_oneof(self) -> Global___OuterMessage3: ... + @property + def bool(self) -> Global___OuterMessage3: ... + @property + def OuterMessage3(self) -> Global___OuterMessage3: ... + @property + def map_scalar(self) -> google.protobuf.internal.containers.ScalarMap[builtins.int, builtins.str]: + """Test generation of map""" + + @property + def map_message(self) -> google.protobuf.internal.containers.MessageMap[builtins.int, Global___OuterMessage3]: ... + @property + def email_by_uid(self) -> google.protobuf.internal.containers.ScalarMap[test.test_generated_mypy.UserId, test.test_generated_mypy.Email]: ... + def __init__( + self, + *, + a_string: builtins.str = ..., + a_repeated_string: collections.abc.Iterable[builtins.str] | None = ..., + a_outer_enum: Global___OuterEnum.ValueType = ..., + outer_message: Global___OuterMessage3 | None = ..., + inner_enum: Global___SimpleProto3.InnerEnum.ValueType = ..., + a_oneof_1: builtins.str = ..., + a_oneof_2: builtins.str = ..., + outer_message_in_oneof: Global___OuterMessage3 | None = ..., + outer_enum_in_oneof: Global___OuterEnum.ValueType = ..., + inner_enum_in_oneof: Global___SimpleProto3.InnerEnum.ValueType = ..., + b_oneof_1: builtins.str = ..., + b_oneof_2: builtins.str = ..., + bool: Global___OuterMessage3 | None = ..., + OuterEnum: Global___OuterEnum.ValueType = ..., + OuterMessage3: Global___OuterMessage3 | None = ..., + map_scalar: collections.abc.Mapping[builtins.int, builtins.str] | None = ..., + map_message: collections.abc.Mapping[builtins.int, Global___OuterMessage3] | None = ..., + an_optional_string: builtins.str | None = ..., + user_id: test.test_generated_mypy.UserId = ..., + email: test.test_generated_mypy.Email = ..., + email_by_uid: collections.abc.Mapping[test.test_generated_mypy.UserId, test.test_generated_mypy.Email] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["OuterMessage3", b"OuterMessage3", "_an_optional_string", b"_an_optional_string", "a_oneof", b"a_oneof", "a_oneof_1", b"a_oneof_1", "a_oneof_2", b"a_oneof_2", "an_optional_string", b"an_optional_string", "b_oneof", b"b_oneof", "b_oneof_1", b"b_oneof_1", "b_oneof_2", b"b_oneof_2", "bool", b"bool", "inner_enum_in_oneof", b"inner_enum_in_oneof", "outer_enum_in_oneof", b"outer_enum_in_oneof", "outer_message", b"outer_message", "outer_message_in_oneof", b"outer_message_in_oneof"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["OuterEnum", b"OuterEnum", "OuterMessage3", b"OuterMessage3", "_an_optional_string", b"_an_optional_string", "a_oneof", b"a_oneof", "a_oneof_1", b"a_oneof_1", "a_oneof_2", b"a_oneof_2", "a_outer_enum", b"a_outer_enum", "a_repeated_string", b"a_repeated_string", "a_string", b"a_string", "an_optional_string", b"an_optional_string", "b_oneof", b"b_oneof", "b_oneof_1", b"b_oneof_1", "b_oneof_2", b"b_oneof_2", "bool", b"bool", "email", b"email", "email_by_uid", b"email_by_uid", "inner_enum", b"inner_enum", "inner_enum_in_oneof", b"inner_enum_in_oneof", "map_message", b"map_message", "map_scalar", b"map_scalar", "outer_enum_in_oneof", b"outer_enum_in_oneof", "outer_message", b"outer_message", "outer_message_in_oneof", b"outer_message_in_oneof", "user_id", b"user_id"]) -> None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["_an_optional_string", b"_an_optional_string"]) -> typing.Literal["an_optional_string"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["a_oneof", b"a_oneof"]) -> typing.Literal["a_oneof_1", "a_oneof_2", "outer_message_in_oneof", "outer_enum_in_oneof", "inner_enum_in_oneof"] | None: ... + @typing.overload + def WhichOneof(self, oneof_group: typing.Literal["b_oneof", b"b_oneof"]) -> typing.Literal["b_oneof_1", "b_oneof_2"] | None: ... + +Global___SimpleProto3: typing_extensions.TypeAlias = SimpleProto3 diff --git a/test/generated-concrete/testproto/test_extensions2_pb2.pyi b/test/generated-concrete/testproto/test_extensions2_pb2.pyi new file mode 100644 index 00000000..b8e9f652 --- /dev/null +++ b/test/generated-concrete/testproto/test_extensions2_pb2.pyi @@ -0,0 +1,37 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.internal.extension_dict +import google.protobuf.message +import sys +import testproto.test_pb2 +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class SeparateFileExtension(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FLAG_FIELD_NUMBER: builtins.int + flag: builtins.bool + EXT_FIELD_NUMBER: builtins.int + ext: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[testproto.test_pb2.Simple2, Global___SeparateFileExtension] + def __init__( + self, + *, + flag: builtins.bool | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["flag", b"flag"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["flag", b"flag"]) -> None: ... + +Global___SeparateFileExtension: typing_extensions.TypeAlias = SeparateFileExtension diff --git a/test/generated-concrete/testproto/test_extensions3_pb2.pyi b/test/generated-concrete/testproto/test_extensions3_pb2.pyi new file mode 100644 index 00000000..f2292855 --- /dev/null +++ b/test/generated-concrete/testproto/test_extensions3_pb2.pyi @@ -0,0 +1,46 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.descriptor_pb2 +import google.protobuf.internal.containers +import google.protobuf.internal.extension_dict +import google.protobuf.message +import sys +import testproto.test3_pb2 +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class MessageOptionsTestMsg(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + +Global___MessageOptionsTestMsg: typing_extensions.TypeAlias = MessageOptionsTestMsg + +TEST_FIELD_EXTENSION_FIELD_NUMBER: builtins.int +SCALAR_OPTION_FIELD_NUMBER: builtins.int +REPEATED_SCALAR_OPTION_FIELD_NUMBER: builtins.int +ENUM_OPTION_FIELD_NUMBER: builtins.int +REPEATED_ENUM_OPTION_FIELD_NUMBER: builtins.int +MSG_OPTION_FIELD_NUMBER: builtins.int +REPEATED_MSG_OPTION_FIELD_NUMBER: builtins.int +test_field_extension: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.FieldOptions, builtins.str] +scalar_option: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, builtins.str] +repeated_scalar_option: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]] +enum_option: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, testproto.test3_pb2.OuterEnum.ValueType] +repeated_enum_option: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, google.protobuf.internal.containers.RepeatedScalarFieldContainer[testproto.test3_pb2.OuterEnum.ValueType]] +msg_option: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, testproto.test3_pb2.OuterMessage3] +repeated_msg_option: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[google.protobuf.descriptor_pb2.MessageOptions, google.protobuf.internal.containers.RepeatedCompositeFieldContainer[testproto.test3_pb2.OuterMessage3]] diff --git a/test/generated-concrete/testproto/test_no_generic_services_pb2.pyi b/test/generated-concrete/testproto/test_no_generic_services_pb2.pyi new file mode 100644 index 00000000..3a350109 --- /dev/null +++ b/test/generated-concrete/testproto/test_no_generic_services_pb2.pyi @@ -0,0 +1,33 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +""" + +import builtins +import google.protobuf.descriptor +import google.protobuf.message +import sys +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +@typing.final +class Simple3(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_STRING_FIELD_NUMBER: builtins.int + a_string: builtins.str + def __init__( + self, + *, + a_string: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["a_string", b"a_string"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["a_string", b"a_string"]) -> None: ... + +Global___Simple3: typing_extensions.TypeAlias = Simple3 diff --git a/test/generated-concrete/testproto/test_pb2.pyi b/test/generated-concrete/testproto/test_pb2.pyi new file mode 100644 index 00000000..3058335b --- /dev/null +++ b/test/generated-concrete/testproto/test_pb2.pyi @@ -0,0 +1,439 @@ +""" +@generated by mypy-protobuf. Do not edit manually! +isort:skip_file +Proto 2 test file.""" + +import builtins +import collections.abc +import google.protobuf.descriptor +import google.protobuf.internal.containers +import google.protobuf.internal.enum_type_wrapper +import google.protobuf.internal.extension_dict +import google.protobuf.message +import sys +import test.test_generated_mypy +import testproto.inner.inner_pb2 +import testproto.nested.nested_pb2 +import testproto.nopackage_pb2 +import testproto.test3_pb2 +import typing + +if sys.version_info >= (3, 10): + import typing as typing_extensions +else: + import typing_extensions + +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated + +DESCRIPTOR: google.protobuf.descriptor.FileDescriptor + +class _OuterEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _OuterEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_OuterEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + FOO: _OuterEnum.ValueType # 1 + """FOO""" + BAR: _OuterEnum.ValueType # 2 + """BAR""" + +class OuterEnum(_OuterEnum, metaclass=_OuterEnumEnumTypeWrapper): + """Outer Enum""" + +FOO: OuterEnum.ValueType # 1 +"""FOO""" +BAR: OuterEnum.ValueType # 2 +"""BAR""" +Global___OuterEnum: typing_extensions.TypeAlias = OuterEnum + +class _NamingConflicts: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _NamingConflictsEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_NamingConflicts.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + +class NamingConflicts(_NamingConflicts, metaclass=_NamingConflictsEnumTypeWrapper): + """Naming conflicts!""" + +Name: NamingConflicts.ValueType # 1 +Value: NamingConflicts.ValueType # 2 +keys: NamingConflicts.ValueType # 3 +values: NamingConflicts.ValueType # 4 +items: NamingConflicts.ValueType # 5 +"""See https://github.com/protocolbuffers/protobuf/issues/8803 +proto itself generates broken code when DESCRIPTOR is there +DESCRIPTOR = 8; +""" +Global___NamingConflicts: typing_extensions.TypeAlias = NamingConflicts + +class _DeprecatedEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + +class _DeprecatedEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_DeprecatedEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + DEPRECATED_ONE: _DeprecatedEnum.ValueType # 1 + DEPRECATED_TWO: _DeprecatedEnum.ValueType # 2 + +@deprecated("""This enum is deprecated\n2 lines of comments\n"Quotes in comments"\nand 'single quotes'\nTrailing comment""") +class DeprecatedEnum(_DeprecatedEnum, metaclass=_DeprecatedEnumEnumTypeWrapper): ... + +DEPRECATED_ONE: DeprecatedEnum.ValueType # 1 +DEPRECATED_TWO: DeprecatedEnum.ValueType # 2 +Global___DeprecatedEnum: typing_extensions.TypeAlias = DeprecatedEnum + +@typing.final +class Simple1(google.protobuf.message.Message): + """Message with one of everything""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _InnerEnum: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _InnerEnumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Simple1._InnerEnum.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + INNER1: Simple1._InnerEnum.ValueType # 1 + """INNER1""" + INNER2: Simple1._InnerEnum.ValueType # 2 + """INNER2""" + + class InnerEnum(_InnerEnum, metaclass=_InnerEnumEnumTypeWrapper): + """Inner Enum""" + + INNER1: Simple1.InnerEnum.ValueType # 1 + """INNER1""" + INNER2: Simple1.InnerEnum.ValueType # 2 + """INNER2""" + + @typing.final + class InnerMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + def __init__( + self, + ) -> None: ... + + @typing.final + class EmailByUidEntry(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + KEY_FIELD_NUMBER: builtins.int + VALUE_FIELD_NUMBER: builtins.int + key: builtins.int + value: builtins.str + def __init__( + self, + *, + key: builtins.int | None = ..., + value: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ... + + A_STRING_FIELD_NUMBER: builtins.int + A_REPEATED_STRING_FIELD_NUMBER: builtins.int + A_BOOLEAN_FIELD_NUMBER: builtins.int + A_UINT32_FIELD_NUMBER: builtins.int + A_ENUM_FIELD_NUMBER: builtins.int + A_EXTERNAL_ENUM_FIELD_NUMBER: builtins.int + A_INNER_FIELD_NUMBER: builtins.int + A_NESTED_FIELD_NUMBER: builtins.int + INNER_ENUM_FIELD_NUMBER: builtins.int + REP_INNER_ENUM_FIELD_NUMBER: builtins.int + INNER_MESSAGE_FIELD_NUMBER: builtins.int + REP_INNER_MESSAGE_FIELD_NUMBER: builtins.int + NO_PACKAGE_FIELD_NUMBER: builtins.int + NESTED_ENUM_FIELD_NUMBER: builtins.int + NESTED_MESSAGE_FIELD_NUMBER: builtins.int + A_ONEOF_1_FIELD_NUMBER: builtins.int + A_ONEOF_2_FIELD_NUMBER: builtins.int + OUTER_MESSAGE_IN_ONEOF_FIELD_NUMBER: builtins.int + OUTER_ENUM_IN_ONEOF_FIELD_NUMBER: builtins.int + INNER_ENUM_IN_ONEOF_FIELD_NUMBER: builtins.int + USER_ID_FIELD_NUMBER: builtins.int + EMAIL_FIELD_NUMBER: builtins.int + EMAIL_BY_UID_FIELD_NUMBER: builtins.int + a_string: builtins.str + a_boolean: builtins.bool + a_uint32: builtins.int + a_enum: Global___OuterEnum.ValueType + a_external_enum: testproto.test3_pb2.OuterEnum.ValueType + inner_enum: Global___Simple1.InnerEnum.ValueType + nested_enum: testproto.nested.nested_pb2.AnotherNested.NestedEnum.ValueType + a_oneof_1: builtins.str + a_oneof_2: builtins.str + outer_enum_in_oneof: Global___OuterEnum.ValueType + inner_enum_in_oneof: Global___Simple1.InnerEnum.ValueType + user_id: test.test_generated_mypy.UserId + email: test.test_generated_mypy.Email + @property + def a_repeated_string(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + @property + def a_inner(self) -> testproto.inner.inner_pb2.Inner: ... + @property + def a_nested(self) -> testproto.nested.nested_pb2.Nested: ... + @property + def rep_inner_enum(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[Global___Simple1.InnerEnum.ValueType]: ... + @property + def inner_message(self) -> Global___Simple1.InnerMessage: ... + @property + def rep_inner_message(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[Global___Simple1.InnerMessage]: ... + @property + def no_package(self) -> testproto.nopackage_pb2.NoPackage: ... + @property + def nested_message(self) -> testproto.nested.nested_pb2.AnotherNested.NestedMessage: ... + @property + def outer_message_in_oneof(self) -> Global___Simple2: ... + @property + def email_by_uid(self) -> google.protobuf.internal.containers.ScalarMap[test.test_generated_mypy.UserId, test.test_generated_mypy.Email]: ... + def __init__( + self, + *, + a_string: builtins.str | None = ..., + a_repeated_string: collections.abc.Iterable[builtins.str] | None = ..., + a_boolean: builtins.bool | None = ..., + a_uint32: builtins.int | None = ..., + a_enum: Global___OuterEnum.ValueType | None = ..., + a_external_enum: testproto.test3_pb2.OuterEnum.ValueType | None = ..., + a_inner: testproto.inner.inner_pb2.Inner | None = ..., + a_nested: testproto.nested.nested_pb2.Nested | None = ..., + inner_enum: Global___Simple1.InnerEnum.ValueType | None = ..., + rep_inner_enum: collections.abc.Iterable[Global___Simple1.InnerEnum.ValueType] | None = ..., + inner_message: Global___Simple1.InnerMessage | None = ..., + rep_inner_message: collections.abc.Iterable[Global___Simple1.InnerMessage] | None = ..., + no_package: testproto.nopackage_pb2.NoPackage | None = ..., + nested_enum: testproto.nested.nested_pb2.AnotherNested.NestedEnum.ValueType | None = ..., + nested_message: testproto.nested.nested_pb2.AnotherNested.NestedMessage | None = ..., + a_oneof_1: builtins.str | None = ..., + a_oneof_2: builtins.str | None = ..., + outer_message_in_oneof: Global___Simple2 | None = ..., + outer_enum_in_oneof: Global___OuterEnum.ValueType | None = ..., + inner_enum_in_oneof: Global___Simple1.InnerEnum.ValueType | None = ..., + user_id: test.test_generated_mypy.UserId | None = ..., + email: test.test_generated_mypy.Email | None = ..., + email_by_uid: collections.abc.Mapping[test.test_generated_mypy.UserId, test.test_generated_mypy.Email] | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["a_boolean", b"a_boolean", "a_enum", b"a_enum", "a_external_enum", b"a_external_enum", "a_inner", b"a_inner", "a_nested", b"a_nested", "a_oneof", b"a_oneof", "a_oneof_1", b"a_oneof_1", "a_oneof_2", b"a_oneof_2", "a_string", b"a_string", "a_uint32", b"a_uint32", "email", b"email", "inner_enum", b"inner_enum", "inner_enum_in_oneof", b"inner_enum_in_oneof", "inner_message", b"inner_message", "nested_enum", b"nested_enum", "nested_message", b"nested_message", "no_package", b"no_package", "outer_enum_in_oneof", b"outer_enum_in_oneof", "outer_message_in_oneof", b"outer_message_in_oneof", "user_id", b"user_id"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["a_boolean", b"a_boolean", "a_enum", b"a_enum", "a_external_enum", b"a_external_enum", "a_inner", b"a_inner", "a_nested", b"a_nested", "a_oneof", b"a_oneof", "a_oneof_1", b"a_oneof_1", "a_oneof_2", b"a_oneof_2", "a_repeated_string", b"a_repeated_string", "a_string", b"a_string", "a_uint32", b"a_uint32", "email", b"email", "email_by_uid", b"email_by_uid", "inner_enum", b"inner_enum", "inner_enum_in_oneof", b"inner_enum_in_oneof", "inner_message", b"inner_message", "nested_enum", b"nested_enum", "nested_message", b"nested_message", "no_package", b"no_package", "outer_enum_in_oneof", b"outer_enum_in_oneof", "outer_message_in_oneof", b"outer_message_in_oneof", "rep_inner_enum", b"rep_inner_enum", "rep_inner_message", b"rep_inner_message", "user_id", b"user_id"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["a_oneof", b"a_oneof"]) -> typing.Literal["a_oneof_1", "a_oneof_2", "outer_message_in_oneof", "outer_enum_in_oneof", "inner_enum_in_oneof"] | None: ... + +Global___Simple1: typing_extensions.TypeAlias = Simple1 + +@typing.final +class Simple2(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_STRING_FIELD_NUMBER: builtins.int + a_string: builtins.str + def __init__( + self, + *, + a_string: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["a_string", b"a_string"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["a_string", b"a_string"]) -> None: ... + +Global___Simple2: typing_extensions.TypeAlias = Simple2 + +@typing.final +class Extensions1(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + EXT1_STRING_FIELD_NUMBER: builtins.int + ext1_string: builtins.str + EXT_FIELD_NUMBER: builtins.int + ext: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[Global___Simple1, Global___Extensions1] + """ext""" + def __init__( + self, + *, + ext1_string: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["ext1_string", b"ext1_string"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["ext1_string", b"ext1_string"]) -> None: ... + +Global___Extensions1: typing_extensions.TypeAlias = Extensions1 + +@typing.final +class Extensions2(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FLAG_FIELD_NUMBER: builtins.int + flag: builtins.bool + FOO_FIELD_NUMBER: builtins.int + foo: google.protobuf.internal.extension_dict._ExtensionFieldDescriptor[Global___Simple1, Global___Extensions2] + """foo""" + def __init__( + self, + *, + flag: builtins.bool | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["flag", b"flag"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["flag", b"flag"]) -> None: ... + +Global___Extensions2: typing_extensions.TypeAlias = Extensions2 + +@typing.final +class _r_None(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + VALID_FIELD_NUMBER: builtins.int + valid: builtins.int + def __init__( + self, + *, + valid: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["valid", b"valid"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["valid", b"valid"]) -> None: ... + +Global____r_None: typing_extensions.TypeAlias = _r_None + +@typing.final +class PythonReservedKeywords(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _finally: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _finallyEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PythonReservedKeywords._finally.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + valid_in_finally: PythonReservedKeywords._finally.ValueType # 2 + + class _r_finally(_finally, metaclass=_finallyEnumTypeWrapper): ... + valid_in_finally: PythonReservedKeywords._r_finally.ValueType # 2 + + @typing.final + class _r_lambda(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + CONTINUE_FIELD_NUMBER: builtins.int + VALID_FIELD_NUMBER: builtins.int + valid: builtins.int + def __init__( + self, + *, + valid: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["continue", b"continue", "valid", b"valid"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["continue", b"continue", "valid", b"valid"]) -> None: ... + + FROM_FIELD_NUMBER: builtins.int + IN_FIELD_NUMBER: builtins.int + IS_FIELD_NUMBER: builtins.int + FOR_FIELD_NUMBER: builtins.int + TRY_FIELD_NUMBER: builtins.int + DEF_FIELD_NUMBER: builtins.int + NONLOCAL_FIELD_NUMBER: builtins.int + WHILE_FIELD_NUMBER: builtins.int + AND_FIELD_NUMBER: builtins.int + DEL_FIELD_NUMBER: builtins.int + GLOBAL_FIELD_NUMBER: builtins.int + NOT_FIELD_NUMBER: builtins.int + WITH_FIELD_NUMBER: builtins.int + AS_FIELD_NUMBER: builtins.int + ELIF_FIELD_NUMBER: builtins.int + IF_FIELD_NUMBER: builtins.int + OR_FIELD_NUMBER: builtins.int + YIELD_FIELD_NUMBER: builtins.int + ASSERT_FIELD_NUMBER: builtins.int + ELSE_FIELD_NUMBER: builtins.int + IMPORT_FIELD_NUMBER: builtins.int + PASS_FIELD_NUMBER: builtins.int + BREAK_FIELD_NUMBER: builtins.int + EXCEPT_FIELD_NUMBER: builtins.int + RAISE_FIELD_NUMBER: builtins.int + FALSE_FIELD_NUMBER: builtins.int + TRUE_FIELD_NUMBER: builtins.int + CLASS_FIELD_NUMBER: builtins.int + NONE_FIELD_NUMBER: builtins.int + VALID_FIELD_NUMBER: builtins.int + valid: Global___PythonReservedKeywords._r_finally.ValueType + @property + def none(self) -> Global____r_None: + """Test unreserved identifiers w/ reserved message names""" + + def __init__( + self, + *, + none: Global____r_None | None = ..., + valid: Global___PythonReservedKeywords._r_finally.ValueType | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["False", b"False", "True", b"True", "and", b"and", "as", b"as", "assert", b"assert", "break", b"break", "class", b"class", "def", b"def", "del", b"del", "elif", b"elif", "else", b"else", "except", b"except", "for", b"for", "from", b"from", "global", b"global", "if", b"if", "import", b"import", "in", b"in", "is", b"is", "none", b"none", "nonlocal", b"nonlocal", "not", b"not", "or", b"or", "pass", b"pass", "raise", b"raise", "try", b"try", "valid", b"valid", "while", b"while", "with", b"with", "yield", b"yield"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["False", b"False", "True", b"True", "and", b"and", "as", b"as", "assert", b"assert", "break", b"break", "class", b"class", "def", b"def", "del", b"del", "elif", b"elif", "else", b"else", "except", b"except", "for", b"for", "from", b"from", "global", b"global", "if", b"if", "import", b"import", "in", b"in", "is", b"is", "none", b"none", "nonlocal", b"nonlocal", "not", b"not", "or", b"or", "pass", b"pass", "raise", b"raise", "try", b"try", "valid", b"valid", "while", b"while", "with", b"with", "yield", b"yield"]) -> None: ... + +Global___PythonReservedKeywords: typing_extensions.TypeAlias = PythonReservedKeywords + +@typing.final +class PythonReservedKeywordsSmall(google.protobuf.message.Message): + """Do one with just one arg - to make sure it's syntactically correct""" + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + FROM_FIELD_NUMBER: builtins.int + def __init__( + self, + ) -> None: ... + def HasField(self, field_name: typing.Literal["from", b"from"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["from", b"from"]) -> None: ... + +Global___PythonReservedKeywordsSmall: typing_extensions.TypeAlias = PythonReservedKeywordsSmall + +@typing.final +class SelfField(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + SELF_FIELD_NUMBER: builtins.int + self: builtins.int + """Field self -> must generate an __init__ method w/ different name""" + def __init__( + self_, # pyright: ignore[reportSelfClsParameterName] + *, + self: builtins.int | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["self", b"self"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["self", b"self"]) -> None: ... + +Global___SelfField: typing_extensions.TypeAlias = SelfField + +@deprecated("""This message is deprecated""") +@typing.final +class DeprecatedMessage(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_STRING_FIELD_NUMBER: builtins.int + a_string: builtins.str + def __init__( + self, + *, + a_string: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["a_string", b"a_string"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["a_string", b"a_string"]) -> None: ... + +Global___DeprecatedMessage: typing_extensions.TypeAlias = DeprecatedMessage + +@deprecated("""This message has been marked as deprecated using proto message options.""") +@typing.final +class DeprecatedMessageBadComment(google.protobuf.message.Message): + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + A_STRING_FIELD_NUMBER: builtins.int + a_string: builtins.str + def __init__( + self, + *, + a_string: builtins.str | None = ..., + ) -> None: ... + def HasField(self, field_name: typing.Literal["a_string", b"a_string"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["a_string", b"a_string"]) -> None: ... + +Global___DeprecatedMessageBadComment: typing_extensions.TypeAlias = DeprecatedMessageBadComment diff --git a/test/test_concrete.py b/test/test_concrete.py new file mode 100644 index 00000000..87582847 --- /dev/null +++ b/test/test_concrete.py @@ -0,0 +1,8 @@ +from testproto.grpc.dummy_pb2_grpc import DummyServiceServicer + + +class IncompleteServicer(DummyServiceServicer): + pass + + +incomplete = IncompleteServicer() diff --git a/test/test_generated_mypy.py b/test/test_generated_mypy.py index 936a35b7..a552b5f7 100644 --- a/test/test_generated_mypy.py +++ b/test/test_generated_mypy.py @@ -121,7 +121,7 @@ def grab_expectations(filename: str, marker: str) -> Generator[Tuple[str, int], assert errors_39 == expected_errors_39 # Some sanity checks to make sure we don't mess this up. Please update as necessary. - assert len(errors_39) == 83 + assert len(errors_39) == 84 def test_func() -> None: diff --git a/test_negative/negative.py b/test_negative/negative.py index 8ac0104c..0b5decd1 100644 --- a/test_negative/negative.py +++ b/test_negative/negative.py @@ -295,6 +295,7 @@ def StreamUnary( # E:3.8 class DeprecatedServicer(DeprecatedServiceServicer): + def DeprecatedMethod( self, request: DeprecatedRequest, @@ -334,3 +335,10 @@ def DeprecatedMethodNotDeprecatedRequest( ed.HasField("explicit_singular") # Should be generated ed.HasField("message_field") # Should be generated ed.HasField("default_singular") # Should be generated + + +class IncompleteServicer(DummyServiceServicer): + pass + + +incomplete = IncompleteServicer() # E:3.8 diff --git a/test_negative/output.expected.3.10 b/test_negative/output.expected.3.10 index 44947438..54a6d183 100644 --- a/test_negative/output.expected.3.10 +++ b/test_negative/output.expected.3.10 @@ -125,6 +125,7 @@ test_negative/negative.py:289: error: Return type "Iterator[DummyReply]" of "Str test_negative/negative.py:291: error: Argument 1 of "StreamUnary" is incompatible with supertype "DummyServiceServicer"; supertype defines the argument type as "_MaybeAsyncIterator[DummyRequest]" [override] test_negative/negative.py:291: note: This violates the Liskov substitution principle test_negative/negative.py:291: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides -test_negative/negative.py:330: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] -test_negative/negative.py:332: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py:331: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] +test_negative/negative.py:333: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] +test_negative/negative.py:344: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.10.omit_linenos b/test_negative/output.expected.3.10.omit_linenos index c3e3f667..c173e23a 100644 --- a/test_negative/output.expected.3.10.omit_linenos +++ b/test_negative/output.expected.3.10.omit_linenos @@ -127,4 +127,5 @@ test_negative/negative.py: note: This violates the Liskov substitution principle test_negative/negative.py: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides test_negative/negative.py: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] test_negative/negative.py: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.11 b/test_negative/output.expected.3.11 index 44947438..54a6d183 100644 --- a/test_negative/output.expected.3.11 +++ b/test_negative/output.expected.3.11 @@ -125,6 +125,7 @@ test_negative/negative.py:289: error: Return type "Iterator[DummyReply]" of "Str test_negative/negative.py:291: error: Argument 1 of "StreamUnary" is incompatible with supertype "DummyServiceServicer"; supertype defines the argument type as "_MaybeAsyncIterator[DummyRequest]" [override] test_negative/negative.py:291: note: This violates the Liskov substitution principle test_negative/negative.py:291: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides -test_negative/negative.py:330: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] -test_negative/negative.py:332: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py:331: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] +test_negative/negative.py:333: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] +test_negative/negative.py:344: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.11.omit_linenos b/test_negative/output.expected.3.11.omit_linenos index c3e3f667..c173e23a 100644 --- a/test_negative/output.expected.3.11.omit_linenos +++ b/test_negative/output.expected.3.11.omit_linenos @@ -127,4 +127,5 @@ test_negative/negative.py: note: This violates the Liskov substitution principle test_negative/negative.py: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides test_negative/negative.py: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] test_negative/negative.py: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.12 b/test_negative/output.expected.3.12 index 44947438..54a6d183 100644 --- a/test_negative/output.expected.3.12 +++ b/test_negative/output.expected.3.12 @@ -125,6 +125,7 @@ test_negative/negative.py:289: error: Return type "Iterator[DummyReply]" of "Str test_negative/negative.py:291: error: Argument 1 of "StreamUnary" is incompatible with supertype "DummyServiceServicer"; supertype defines the argument type as "_MaybeAsyncIterator[DummyRequest]" [override] test_negative/negative.py:291: note: This violates the Liskov substitution principle test_negative/negative.py:291: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides -test_negative/negative.py:330: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] -test_negative/negative.py:332: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py:331: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] +test_negative/negative.py:333: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] +test_negative/negative.py:344: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.12.omit_linenos b/test_negative/output.expected.3.12.omit_linenos index c3e3f667..c173e23a 100644 --- a/test_negative/output.expected.3.12.omit_linenos +++ b/test_negative/output.expected.3.12.omit_linenos @@ -127,4 +127,5 @@ test_negative/negative.py: note: This violates the Liskov substitution principle test_negative/negative.py: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides test_negative/negative.py: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] test_negative/negative.py: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.13 b/test_negative/output.expected.3.13 index 44947438..54a6d183 100644 --- a/test_negative/output.expected.3.13 +++ b/test_negative/output.expected.3.13 @@ -125,6 +125,7 @@ test_negative/negative.py:289: error: Return type "Iterator[DummyReply]" of "Str test_negative/negative.py:291: error: Argument 1 of "StreamUnary" is incompatible with supertype "DummyServiceServicer"; supertype defines the argument type as "_MaybeAsyncIterator[DummyRequest]" [override] test_negative/negative.py:291: note: This violates the Liskov substitution principle test_negative/negative.py:291: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides -test_negative/negative.py:330: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] -test_negative/negative.py:332: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py:331: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] +test_negative/negative.py:333: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] +test_negative/negative.py:344: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.13.omit_linenos b/test_negative/output.expected.3.13.omit_linenos index c3e3f667..c173e23a 100644 --- a/test_negative/output.expected.3.13.omit_linenos +++ b/test_negative/output.expected.3.13.omit_linenos @@ -127,4 +127,5 @@ test_negative/negative.py: note: This violates the Liskov substitution principle test_negative/negative.py: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides test_negative/negative.py: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] test_negative/negative.py: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.14 b/test_negative/output.expected.3.14 index 44947438..54a6d183 100644 --- a/test_negative/output.expected.3.14 +++ b/test_negative/output.expected.3.14 @@ -125,6 +125,7 @@ test_negative/negative.py:289: error: Return type "Iterator[DummyReply]" of "Str test_negative/negative.py:291: error: Argument 1 of "StreamUnary" is incompatible with supertype "DummyServiceServicer"; supertype defines the argument type as "_MaybeAsyncIterator[DummyRequest]" [override] test_negative/negative.py:291: note: This violates the Liskov substitution principle test_negative/negative.py:291: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides -test_negative/negative.py:330: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] -test_negative/negative.py:332: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py:331: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] +test_negative/negative.py:333: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] +test_negative/negative.py:344: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.14.omit_linenos b/test_negative/output.expected.3.14.omit_linenos index c3e3f667..c173e23a 100644 --- a/test_negative/output.expected.3.14.omit_linenos +++ b/test_negative/output.expected.3.14.omit_linenos @@ -127,4 +127,5 @@ test_negative/negative.py: note: This violates the Liskov substitution principle test_negative/negative.py: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides test_negative/negative.py: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] test_negative/negative.py: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.9 b/test_negative/output.expected.3.9 index d2dfd12e..54d8212b 100644 --- a/test_negative/output.expected.3.9 +++ b/test_negative/output.expected.3.9 @@ -125,6 +125,7 @@ test_negative/negative.py:289: error: Return type "Iterator[DummyReply]" of "Str test_negative/negative.py:291: error: Argument 1 of "StreamUnary" is incompatible with supertype "DummyServiceServicer"; supertype defines the argument type as "_MaybeAsyncIterator[DummyRequest]" [override] test_negative/negative.py:291: note: This violates the Liskov substitution principle test_negative/negative.py:291: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides -test_negative/negative.py:330: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] -test_negative/negative.py:332: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py:331: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] +test_negative/negative.py:333: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] +test_negative/negative.py:344: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files) diff --git a/test_negative/output.expected.3.9.omit_linenos b/test_negative/output.expected.3.9.omit_linenos index 44bc962c..d1a55335 100644 --- a/test_negative/output.expected.3.9.omit_linenos +++ b/test_negative/output.expected.3.9.omit_linenos @@ -127,4 +127,5 @@ test_negative/negative.py: note: This violates the Liskov substitution principle test_negative/negative.py: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides test_negative/negative.py: error: Argument "implicit_singular" to "Editions2024Test" has incompatible type "None"; expected "str" [arg-type] test_negative/negative.py: error: Argument 1 to "HasField" of "Editions2024Test" has incompatible type "Literal['implicit_singular']"; expected "Literal['default_singular', b'default_singular', 'explicit_singular', b'explicit_singular', 'legacy', b'legacy', 'message_field', b'message_field']" [arg-type] -Found 82 errors in 1 file (checked 4 source files) +test_negative/negative.py: error: Cannot instantiate abstract class "IncompleteServicer" with abstract attributes "StreamStream", "StreamUnary", "UnaryStream" and "UnaryUnary" [abstract] +Found 83 errors in 1 file (checked 4 source files)