|
1 | 1 | #!/usr/bin/env python
|
2 | 2 |
|
3 | 3 | import itertools
|
4 |
| -import json |
5 | 4 | import os.path
|
6 |
| -import re |
7 | 5 | import sys
|
8 | 6 | import textwrap
|
9 |
| -from typing import Any, List, Tuple |
| 7 | +from collections import defaultdict |
| 8 | +from typing import Dict, List, Optional, Type |
10 | 9 |
|
11 | 10 | try:
|
12 | 11 | import black
|
|
24 | 23 | DescriptorProto,
|
25 | 24 | EnumDescriptorProto,
|
26 | 25 | FieldDescriptorProto,
|
27 |
| - FileDescriptorProto, |
28 |
| - ServiceDescriptorProto, |
29 | 26 | )
|
30 | 27 |
|
31 | 28 | from betterproto.casing import safe_snake_case
|
32 | 29 |
|
| 30 | +import google.protobuf.wrappers_pb2 as google_wrappers |
33 | 31 |
|
34 |
| -WRAPPER_TYPES = { |
35 |
| - "google.protobuf.DoubleValue": "float", |
36 |
| - "google.protobuf.FloatValue": "float", |
37 |
| - "google.protobuf.Int64Value": "int", |
38 |
| - "google.protobuf.UInt64Value": "int", |
39 |
| - "google.protobuf.Int32Value": "int", |
40 |
| - "google.protobuf.UInt32Value": "int", |
41 |
| - "google.protobuf.BoolValue": "bool", |
42 |
| - "google.protobuf.StringValue": "str", |
43 |
| - "google.protobuf.BytesValue": "bytes", |
44 |
| -} |
| 32 | +WRAPPER_TYPES: Dict[str, Optional[Type]] = defaultdict(lambda: None, { |
| 33 | + 'google.protobuf.DoubleValue': google_wrappers.DoubleValue, |
| 34 | + 'google.protobuf.FloatValue': google_wrappers.FloatValue, |
| 35 | + 'google.protobuf.Int64Value': google_wrappers.Int64Value, |
| 36 | + 'google.protobuf.UInt64Value': google_wrappers.UInt64Value, |
| 37 | + 'google.protobuf.Int32Value': google_wrappers.Int32Value, |
| 38 | + 'google.protobuf.UInt32Value': google_wrappers.UInt32Value, |
| 39 | + 'google.protobuf.BoolValue': google_wrappers.BoolValue, |
| 40 | + 'google.protobuf.StringValue': google_wrappers.StringValue, |
| 41 | + 'google.protobuf.BytesValue': google_wrappers.BytesValue, |
| 42 | +}) |
45 | 43 |
|
46 | 44 |
|
47 |
| -def get_ref_type(package: str, imports: set, type_name: str) -> str: |
| 45 | +def get_ref_type(package: str, imports: set, type_name: str, unwrap: bool = True) -> str: |
48 | 46 | """
|
49 | 47 | Return a Python type name for a proto type reference. Adds the import if
|
50 |
| - necessary. |
| 48 | + necessary. Unwraps well known type if required. |
51 | 49 | """
|
52 | 50 | # If the package name is a blank string, then this should still work
|
53 | 51 | # because by convention packages are lowercase and message/enum types are
|
54 | 52 | # pascal-cased. May require refactoring in the future.
|
55 | 53 | type_name = type_name.lstrip(".")
|
56 | 54 |
|
57 |
| - if type_name in WRAPPER_TYPES: |
58 |
| - return f"Optional[{WRAPPER_TYPES[type_name]}]" |
| 55 | + # Check if type is wrapper. |
| 56 | + wrapper_class = WRAPPER_TYPES[type_name] |
59 | 57 |
|
60 |
| - if type_name == "google.protobuf.Duration": |
61 |
| - return "timedelta" |
| 58 | + if unwrap: |
| 59 | + if wrapper_class: |
| 60 | + wrapped_type = type(wrapper_class().value) |
| 61 | + return f"Optional[{wrapped_type.__name__}]" |
62 | 62 |
|
63 |
| - if type_name == "google.protobuf.Timestamp": |
64 |
| - return "datetime" |
| 63 | + if type_name == "google.protobuf.Duration": |
| 64 | + return "timedelta" |
| 65 | + |
| 66 | + if type_name == "google.protobuf.Timestamp": |
| 67 | + return "datetime" |
| 68 | + elif wrapper_class: |
| 69 | + imports.add(f"from {wrapper_class.__module__} import {wrapper_class.__name__}") |
| 70 | + return f"{wrapper_class.__name__}" |
65 | 71 |
|
66 | 72 | if type_name.startswith(package):
|
67 | 73 | parts = type_name.lstrip(package).lstrip(".").split(".")
|
@@ -379,7 +385,7 @@ def generate_code(request, response):
|
379 | 385 | ).strip('"'),
|
380 | 386 | "input_message": input_message,
|
381 | 387 | "output": get_ref_type(
|
382 |
| - package, output["imports"], method.output_type |
| 388 | + package, output["imports"], method.output_type, unwrap=False |
383 | 389 | ).strip('"'),
|
384 | 390 | "client_streaming": method.client_streaming,
|
385 | 391 | "server_streaming": method.server_streaming,
|
|
0 commit comments