From 2dd20e307eae755aff7959edf2dfede7b00c9ca8 Mon Sep 17 00:00:00 2001 From: veaceaslav Date: Wed, 31 Jan 2024 22:40:27 +0200 Subject: [PATCH 1/6] fix: broken relative imports for output types generation --- src/betterproto/plugin/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/betterproto/plugin/models.py b/src/betterproto/plugin/models.py index 93b2aa8cf..f0048c830 100644 --- a/src/betterproto/plugin/models.py +++ b/src/betterproto/plugin/models.py @@ -725,6 +725,9 @@ def __post_init__(self) -> None: self.parent.methods.append(self) # Check for imports + if "Optional" in self.py_input_message_type: + self.output_file.typing_imports.add("Optional") + if "Optional" in self.py_output_message_type: self.output_file.typing_imports.add("Optional") From 586519b16d0f0c7cc714665ff4a2884a89c66216 Mon Sep 17 00:00:00 2001 From: Veaceslav Dimitrioglo Date: Sat, 17 Feb 2024 19:25:19 +0200 Subject: [PATCH 2/6] feat: add possibility to generate interfaces for folder containing subfolders --- tests/util.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/util.py b/tests/util.py index 22c4f9012..dfacfe53e 100644 --- a/tests/util.py +++ b/tests/util.py @@ -34,9 +34,15 @@ def get_files(path, suffix: str) -> Generator[str, None, None]: yield os.path.join(r, filename) -def get_directories(path): - for root, directories, files in os.walk(path): - yield from directories +def get_directories(path: Path) -> List[str]: + """ + Get a list of first-level nested directory names in the specified path + + path: The PosixPath object representing the path to scan + for first-level nested directories + returns: A list of first-level nested directory names in the specified path + """ + return [entry.name for entry in Path(path).iterdir() if entry.is_dir()] async def protoc( @@ -79,7 +85,7 @@ async def protoc( "--custom_opt=pydantic_dataclasses", f"--proto_path={path.as_posix()}", f"--custom_out={output_dir.as_posix()}", - *[p.as_posix() for p in path.glob("*.proto")], + *[p.as_posix() for p in path.glob("**/*.proto")] ] else: command = [ @@ -88,7 +94,7 @@ async def protoc( "grpc.tools.protoc", f"--proto_path={path.as_posix()}", f"--{python_out_option}={output_dir.as_posix()}", - *[p.as_posix() for p in path.glob("*.proto")], + *[p.as_posix() for p in path.glob("**/*.proto")] ] proc = await asyncio.create_subprocess_exec( *command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE From 6d015f6ebabee1aa2d76e895d26a2e1fa9285342 Mon Sep 17 00:00:00 2001 From: Veaceslav Dimitrioglo Date: Sat, 17 Feb 2024 19:36:24 +0200 Subject: [PATCH 3/6] test: add cases for service_complex_stucture which covering fixed broken relative imports feature --- .../payloads/messages.proto | 13 +++++++++++++ .../services/service.proto | 11 +++++++++++ .../test_service_complex_structure.py | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 tests/inputs/service_complex_structure/payloads/messages.proto create mode 100644 tests/inputs/service_complex_structure/services/service.proto create mode 100644 tests/inputs/service_complex_structure/test_service_complex_structure.py diff --git a/tests/inputs/service_complex_structure/payloads/messages.proto b/tests/inputs/service_complex_structure/payloads/messages.proto new file mode 100644 index 000000000..42c101724 --- /dev/null +++ b/tests/inputs/service_complex_structure/payloads/messages.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +package service_complex_structure.payloads; + +message Test { + string name = 1; + repeated string comments = 2; + google.protobuf.Timestamp when = 3; + google.protobuf.Duration duration = 4; +} diff --git a/tests/inputs/service_complex_structure/services/service.proto b/tests/inputs/service_complex_structure/services/service.proto new file mode 100644 index 000000000..d0ea30b3f --- /dev/null +++ b/tests/inputs/service_complex_structure/services/service.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "payloads/messages.proto"; + +package service_complex_structure.service; + + +service Test { + rpc DoThing (service_complex_structure.payloads.Test) returns (google.protobuf.Empty); +} diff --git a/tests/inputs/service_complex_structure/test_service_complex_structure.py b/tests/inputs/service_complex_structure/test_service_complex_structure.py new file mode 100644 index 000000000..f8bd7275f --- /dev/null +++ b/tests/inputs/service_complex_structure/test_service_complex_structure.py @@ -0,0 +1,17 @@ +import pytest + + +def test_payloads_import_is_generated(): + try: + from tests.output_betterproto.service_complex_structure.service import _payloads__ + assert hasattr(_payloads__, 'Test') + except ImportError: + pytest.fail("Required import for type annotations is not generated!") + + +def test_payloads_import_is_generated_pydantic(): + try: + from tests.output_betterproto_pydantic.service_complex_structure.service import _payloads__ + assert hasattr(_payloads__, 'Test') + except ImportError: + pytest.fail("Required import for type annotations is not generated in pydantic output!") From 4a2e5ed7f29e68e1cedda69cdedbe852d3a0f38b Mon Sep 17 00:00:00 2001 From: Veaceslav Dimitrioglo Date: Sat, 17 Feb 2024 19:40:39 +0200 Subject: [PATCH 4/6] style: revert comma delete --- tests/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/util.py b/tests/util.py index dfacfe53e..5d88c9096 100644 --- a/tests/util.py +++ b/tests/util.py @@ -85,7 +85,7 @@ async def protoc( "--custom_opt=pydantic_dataclasses", f"--proto_path={path.as_posix()}", f"--custom_out={output_dir.as_posix()}", - *[p.as_posix() for p in path.glob("**/*.proto")] + *[p.as_posix() for p in path.glob("**/*.proto")], ] else: command = [ @@ -94,7 +94,7 @@ async def protoc( "grpc.tools.protoc", f"--proto_path={path.as_posix()}", f"--{python_out_option}={output_dir.as_posix()}", - *[p.as_posix() for p in path.glob("**/*.proto")] + *[p.as_posix() for p in path.glob("**/*.proto")], ] proc = await asyncio.create_subprocess_exec( *command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE From 48f2c891dadfe05e296c8407189edda9a40d2958 Mon Sep 17 00:00:00 2001 From: Veaceslav Dimitrioglo Date: Fri, 23 Feb 2024 10:25:06 +0200 Subject: [PATCH 5/6] style: run pre-commit hooks --- .../test_service_complex_structure.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/inputs/service_complex_structure/test_service_complex_structure.py b/tests/inputs/service_complex_structure/test_service_complex_structure.py index f8bd7275f..c46428e1b 100644 --- a/tests/inputs/service_complex_structure/test_service_complex_structure.py +++ b/tests/inputs/service_complex_structure/test_service_complex_structure.py @@ -3,15 +3,23 @@ def test_payloads_import_is_generated(): try: - from tests.output_betterproto.service_complex_structure.service import _payloads__ - assert hasattr(_payloads__, 'Test') + from tests.output_betterproto.service_complex_structure.service import ( + _payloads__, + ) + + assert hasattr(_payloads__, "Test") except ImportError: pytest.fail("Required import for type annotations is not generated!") def test_payloads_import_is_generated_pydantic(): try: - from tests.output_betterproto_pydantic.service_complex_structure.service import _payloads__ - assert hasattr(_payloads__, 'Test') + from tests.output_betterproto_pydantic.service_complex_structure.service import ( + _payloads__, + ) + + assert hasattr(_payloads__, "Test") except ImportError: - pytest.fail("Required import for type annotations is not generated in pydantic output!") + pytest.fail( + "Required import for type annotations is not generated in pydantic output!" + ) From a6cc44377254ce540e791bbabf2c30808d2a21a6 Mon Sep 17 00:00:00 2001 From: Veaceslav Dimitrioglo <38919057+Dimitrioglo@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:05:50 +0200 Subject: [PATCH 6/6] refactor: get_directories to generator expression Co-authored-by: James Hilton-Balfe --- tests/util.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/util.py b/tests/util.py index 5d88c9096..78a90a903 100644 --- a/tests/util.py +++ b/tests/util.py @@ -34,15 +34,8 @@ def get_files(path, suffix: str) -> Generator[str, None, None]: yield os.path.join(r, filename) -def get_directories(path: Path) -> List[str]: - """ - Get a list of first-level nested directory names in the specified path - - path: The PosixPath object representing the path to scan - for first-level nested directories - returns: A list of first-level nested directory names in the specified path - """ - return [entry.name for entry in Path(path).iterdir() if entry.is_dir()] +def get_directories(path: Path) -> Generator[str, None, None]: + yield from (entry.name for entry in path.iterdir() if entry.is_dir()) async def protoc(