Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/betterproto/plugin/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
13 changes: 13 additions & 0 deletions tests/inputs/service_complex_structure/payloads/messages.proto
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions tests/inputs/service_complex_structure/services/service.proto
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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!"
)
16 changes: 11 additions & 5 deletions tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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 = [
Expand All @@ -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
Expand Down