@@ -55,30 +55,12 @@ class Foo(Enum):
55
55
def _to_str (cls , v ):
56
56
# "v" corresponds to an enum instance: Example foo or Foo.Test above.
57
57
# "cls" corresponds to the enum type Foo above.
58
- # enum_prefix = f'{_pascal_case_to_upper_snake_case(cls.__name__)}_'
59
- # if v.name.startswith(enum_prefix):
60
- # return v.name
61
- # return f'{enum_prefix}{v.name}'
62
- enum_prefix = f'{ _pascal_case_to_upper_snake_case (cls .__name__ )} _'
63
- if v .name .find (enum_prefix ) == 0 :
64
- return v .name [len (enum_prefix ) :].lower ()
65
58
return v .name
66
59
67
60
@staticmethod
68
61
def _from_str (cls , v ):
69
62
# "v" corresponds to enum string: Example "TEST" above.
70
63
# "cls" corresponds to the enum type Foo above.
71
- # enum_items = {item.name: item for item in cls}
72
- # if v in enum_items:
73
- # return enum_items[v]
74
- #
75
- # # Try with enum prefix. Example: EnvironmentType.JSON -> "ENVIRONMENT_TYPE_JSON"
76
- # enum_prefix = _pascal_case_to_upper_snake_case(cls.__name__)
77
- # if v.startswith(enum_prefix):
78
- # ix_start = len(enum_prefix) + 1
79
- # return enum_items[v[ix_start:]]
80
- #
81
- # return enum_items[f'{enum_prefix}_{v}']
82
64
try :
83
65
return cls [v ]
84
66
except KeyError :
@@ -159,9 +141,22 @@ def _from_str(v):
159
141
160
142
161
143
class TimeDeltaSerializer (ObjectSerializer ):
144
+ # Scaling factors idea from https://github.com/protocolbuffers/protobuf/blob/master/csharp/src/Google.Protobuf/JsonParser.cs
145
+ SUBSECOND_SCALING_FACTORS = [
146
+ 0 ,
147
+ 100_000_000 ,
148
+ 10_000_000 ,
149
+ 1_000_000 ,
150
+ 100_000 ,
151
+ 10_000 ,
152
+ 1_000 ,
153
+ 100 ,
154
+ 10 ,
155
+ 1 ,
156
+ ]
162
157
163
158
def __init__ (self ):
164
- """Time deltas are serialized/deserialized as a string in "mm:ss " format"""
159
+ """Time deltas are serialized/deserialized as a string in "<seconds>.<nanoseconds>s " format. Example: 151.500s """
165
160
ObjectSerializer .__init__ (
166
161
self ,
167
162
lambda cls , t , _ : TimeDeltaSerializer ._to_dict_value (t ),
@@ -170,15 +165,30 @@ def __init__(self):
170
165
171
166
@staticmethod
172
167
def _to_dict_value (delta ):
173
- seconds = int (delta .total_seconds ())
174
- minutes = seconds // 60
175
- seconds -= minutes * 60
176
- return '{}:{:02}' .format (int (minutes ), int (seconds ))
168
+ seconds = delta .seconds
169
+ nanos_str = TimeDeltaSerializer ._nanos_to_str (delta .microseconds * 1000 )
170
+ if nanos_str is None :
171
+ return "{}s" .format (seconds )
172
+ return "{}.{}s" .format (seconds , nanos_str )
173
+
174
+ @staticmethod
175
+ def _nanos_to_str (nanos ):
176
+ if nanos == 0 :
177
+ return None
178
+ if nanos < 0 :
179
+ nanos *= - 1
180
+ if nanos % 1000000 == 0 :
181
+ return "{}" .format (nanos / 1000000 )
182
+ elif nanos % 1000 == 0 :
183
+ return "{}" .format (nanos / 1000 )
184
+ else :
185
+ return "{}" .format (nanos )
177
186
178
187
@staticmethod
179
188
def _from_dict_value (value ):
180
- (minutes , seconds ) = value .split (':' )
181
- return timedelta (minutes = int (minutes ), seconds = int (seconds ))
189
+ (seconds , nanosRaw ) = value .rstrip ('s' ).split ('.' )
190
+ nanos = int (nanosRaw ) * TimeDeltaSerializer .SUBSECOND_SCALING_FACTORS [len (nanosRaw )]
191
+ return timedelta (seconds = int (seconds ), microseconds = int (int (nanos ) / 1000 ))
182
192
183
193
184
194
class FieldMaskSerializer (ObjectSerializer ):
0 commit comments