Skip to content
This repository was archived by the owner on Jun 9, 2025. It is now read-only.

Commit a2c2b13

Browse files
committed
Wrap timestamp and duration
1 parent bec468f commit a2c2b13

File tree

5 files changed

+37
-3
lines changed

5 files changed

+37
-3
lines changed

src/betterproto2_compiler/compile/importing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def get_type_reference(
8080
Return a Python type name for a proto type reference. Adds the import if
8181
necessary. Unwraps well known type if required.
8282
"""
83-
if unwrap:
83+
if unwrap: # TODO don't hardcode
8484
if source_type == ".google.protobuf.Duration":
8585
return "datetime.timedelta"
8686

src/betterproto2_compiler/known_types/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@
1010
# to the template file: they will automatically be removed if not necessary.
1111
KNOWN_METHODS: dict[tuple[str, str], list[Callable]] = {
1212
("google.protobuf", "Any"): [Any.pack, Any.unpack, Any.to_dict],
13-
("google.protobuf", "Timestamp"): [Timestamp.from_datetime, Timestamp.to_datetime, Timestamp.timestamp_to_json],
13+
("google.protobuf", "Timestamp"): [
14+
Timestamp.from_datetime,
15+
Timestamp.to_datetime,
16+
Timestamp.timestamp_to_json,
17+
Timestamp.from_dict,
18+
Timestamp.to_wrapped,
19+
],
1420
("google.protobuf", "Duration"): [Duration.from_timedelta, Duration.to_timedelta, Duration.delta_to_json],
1521
("google.protobuf", "BoolValue"): [BoolValue.from_wrapped, BoolValue.to_wrapped],
1622
("google.protobuf", "StringValue"): [StringValue.from_wrapped, StringValue.to_wrapped],
@@ -20,4 +26,6 @@
2026
WRAPPED_TYPES: dict[tuple[str, str], str] = {
2127
("google.protobuf", "BoolValue"): "bool",
2228
("google.protobuf", "StringValue"): "str",
29+
("google.protobuf", "Timestamp"): "datetime.datetime",
30+
("google.protobuf", "Duration"): "datetime.timedelta",
2331
}

src/betterproto2_compiler/known_types/timestamp.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import datetime
22

3+
import dateutil.parser
4+
35
from betterproto2_compiler.lib.google.protobuf import Timestamp as VanillaTimestamp
46

57

@@ -43,3 +45,16 @@ def timestamp_to_json(dt: datetime.datetime) -> str:
4345
return f"{result}.{int(nanos // 1e3):06d}Z"
4446
# Serialize 9 fractional digits.
4547
return f"{result}.{nanos:09d}"
48+
49+
# TODO typing
50+
@classmethod
51+
def from_dict(cls, value):
52+
if isinstance(value, str):
53+
dt = dateutil.parser.isoparse(value)
54+
dt = dt.astimezone(datetime.timezone.utc)
55+
return Timestamp.from_datetime(dt)
56+
57+
return super().from_dict(value)
58+
59+
def to_wrapped(self) -> datetime.datetime:
60+
return self.to_datetime()

src/betterproto2_compiler/plugin/models.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,13 +317,23 @@ def get_field_string(self) -> str:
317317
def betterproto_field_args(self) -> list[str]:
318318
args = []
319319

320-
if self.proto_obj.type == FieldDescriptorProtoType.TYPE_MESSAGE:
320+
if self.field_type == FieldDescriptorProtoType.TYPE_MESSAGE:
321321
type_package, type_name = parse_source_type_name(self.proto_obj.type_name, self.output_file.parent_request)
322322

323323
if (type_package, type_name) in WRAPPED_TYPES:
324+
unwrap_type = get_type_reference(
325+
package=self.output_file.package,
326+
imports=self.output_file.imports_end,
327+
source_type=self.proto_obj.type_name,
328+
request=self.output_file.parent_request,
329+
settings=self.output_file.settings,
330+
unwrap=False,
331+
)
332+
324333
# Without the lambda function, the type is evaluated right away, which fails since the corresponding
325334
# import is placed at the end of the file to avoid circular imports.
326335
args.append(f"wrap=lambda: {self.py_type}")
336+
args.append(f"unwrap=lambda: {unwrap_type}")
327337

328338
if self.optional:
329339
args.append("optional=True")

src/betterproto2_compiler/templates/header.py.j2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ __all__ = (
2020

2121
import builtins
2222
import datetime
23+
import dateutil.parser
2324
import warnings
2425
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
2526
import typing

0 commit comments

Comments
 (0)