@typespec/http-client-python 0.31.1 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/emitter/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +20 -169
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/lib.d.ts +6 -0
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +29 -0
- package/dist/emitter/lib.js.map +1 -1
- package/dist/emitter/node-runner.browser.d.ts +12 -0
- package/dist/emitter/node-runner.browser.d.ts.map +1 -0
- package/dist/emitter/node-runner.browser.js +16 -0
- package/dist/emitter/node-runner.browser.js.map +1 -0
- package/dist/emitter/node-runner.d.ts +12 -0
- package/dist/emitter/node-runner.d.ts.map +1 -0
- package/dist/emitter/node-runner.js +180 -0
- package/dist/emitter/node-runner.js.map +1 -0
- package/dist/emitter/pyodide-loader.browser.d.ts +12 -0
- package/dist/emitter/pyodide-loader.browser.d.ts.map +1 -0
- package/dist/emitter/pyodide-loader.browser.js +33 -0
- package/dist/emitter/pyodide-loader.browser.js.map +1 -0
- package/dist/emitter/pyodide-loader.d.ts +3 -0
- package/dist/emitter/pyodide-loader.d.ts.map +1 -0
- package/dist/emitter/pyodide-loader.js +6 -0
- package/dist/emitter/pyodide-loader.js.map +1 -0
- package/dist/emitter/types.d.ts.map +1 -1
- package/dist/emitter/types.js +7 -0
- package/dist/emitter/types.js.map +1 -1
- package/emitter/src/emitter.ts +18 -189
- package/emitter/src/lib.ts +36 -0
- package/emitter/src/node-runner.browser.ts +33 -0
- package/emitter/src/node-runner.ts +220 -0
- package/emitter/src/pyodide-loader.browser.ts +49 -0
- package/emitter/src/pyodide-loader.ts +6 -0
- package/emitter/src/types.ts +7 -0
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/setup/__pycache__/package_manager.cpython-311.pyc +0 -0
- package/eng/scripts/setup/__pycache__/venvtools.cpython-311.pyc +0 -0
- package/generator/build/lib/pygen/__init__.py +1 -0
- package/generator/build/lib/pygen/codegen/models/primitive_types.py +15 -1
- package/generator/build/lib/pygen/codegen/models/utils.py +20 -5
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +9 -2
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +32 -2
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +34 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +30 -2
- package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +109 -0
- package/generator/build/lib/pygen/preprocess/__init__.py +168 -52
- package/generator/build/lib/pygen/utils.py +38 -4
- package/generator/component-detection-pip-report.json +2 -2
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/__init__.py +1 -0
- package/generator/pygen/codegen/models/primitive_types.py +15 -1
- package/generator/pygen/codegen/models/utils.py +20 -5
- package/generator/pygen/codegen/serializers/builder_serializer.py +9 -2
- package/generator/pygen/codegen/serializers/general_serializer.py +32 -2
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +34 -1
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +30 -2
- package/generator/pygen/codegen/templates/serialization.py.jinja2 +109 -0
- package/generator/pygen/preprocess/__init__.py +168 -52
- package/generator/pygen/utils.py +38 -4
- package/package.json +12 -8
|
Binary file
|
|
Binary file
|
|
@@ -522,8 +522,22 @@ class DateType(PrimitiveType):
|
|
|
522
522
|
|
|
523
523
|
|
|
524
524
|
class DurationType(PrimitiveType):
|
|
525
|
+
def __init__(self, yaml_data: dict[str, Any], code_model: "CodeModel") -> None:
|
|
526
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
527
|
+
# ``seconds`` and ``milliseconds`` encodings serialize a timedelta to a numeric
|
|
528
|
+
# wire value. ``encode`` is set to a combined format token (e.g.
|
|
529
|
+
# ``duration-seconds-int``) so that serialization/deserialization can convert
|
|
530
|
+
# between ``datetime.timedelta`` and the numeric wire type. ISO8601 (the default)
|
|
531
|
+
# leaves ``encode`` unset and keeps the legacy ISO 8601 string behavior.
|
|
532
|
+
self.encode: Optional[str] = None
|
|
533
|
+
encode = yaml_data.get("encode")
|
|
534
|
+
if encode in ("seconds", "milliseconds"):
|
|
535
|
+
wire_type = yaml_data.get("wireType") or {}
|
|
536
|
+
wire = "int" if wire_type.get("type") == "integer" else "float"
|
|
537
|
+
self.encode = f"duration-{encode}-{wire}"
|
|
538
|
+
|
|
525
539
|
def serialization_type(self, **kwargs: Any) -> str:
|
|
526
|
-
return "duration"
|
|
540
|
+
return self.encode or "duration"
|
|
527
541
|
|
|
528
542
|
def docstring_type(self, **kwargs: Any) -> str:
|
|
529
543
|
return "~" + self.type_annotation()
|
|
@@ -7,14 +7,25 @@ from typing import TypeVar
|
|
|
7
7
|
|
|
8
8
|
from enum import Enum
|
|
9
9
|
|
|
10
|
+
from ...utils import description_ends_with_code_block
|
|
11
|
+
|
|
10
12
|
T = TypeVar("T")
|
|
11
13
|
OrderedSet = dict[T, None]
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
def add_to_description(description: str, entry: str) -> str:
|
|
15
|
-
if description:
|
|
16
|
-
return
|
|
17
|
-
|
|
17
|
+
if not description:
|
|
18
|
+
return entry
|
|
19
|
+
if not entry:
|
|
20
|
+
return description
|
|
21
|
+
# When the description ends with a code block, prepend the entry (e.g. "Required.") so
|
|
22
|
+
# it appears before the prose instead of after the block. Appending inline (e.g.
|
|
23
|
+
# "]. Required.") would land it inside the rendered literal block and break Sphinx, and a
|
|
24
|
+
# trailing paragraph reads awkwardly. The code block stays at the very end where it renders
|
|
25
|
+
# cleanly. (Code-block descriptions only ever carry a single annotation in practice.)
|
|
26
|
+
if description_ends_with_code_block(description):
|
|
27
|
+
return f"{entry} {description.lstrip()}"
|
|
28
|
+
return f"{description} {entry}"
|
|
18
29
|
|
|
19
30
|
|
|
20
31
|
def add_to_pylint_disable(curr_str: str, entry: str) -> str:
|
|
@@ -34,6 +45,10 @@ class NamespaceType(str, Enum):
|
|
|
34
45
|
|
|
35
46
|
LOCALS_LENGTH_LIMIT = 25
|
|
36
47
|
|
|
37
|
-
REQUEST_BUILDER_BODY_VARIABLES_LENGTH =
|
|
48
|
+
REQUEST_BUILDER_BODY_VARIABLES_LENGTH = (
|
|
49
|
+
6 # how many body variables are present in a request builder
|
|
50
|
+
)
|
|
38
51
|
|
|
39
|
-
OPERATION_BODY_VARIABLES_LENGTH =
|
|
52
|
+
OPERATION_BODY_VARIABLES_LENGTH = (
|
|
53
|
+
14 # how many body variables are present in an operation
|
|
54
|
+
)
|
|
@@ -931,7 +931,8 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
931
931
|
if builder.parameters.has_body and builder.parameters.body_parameter.flattened:
|
|
932
932
|
# serialize flattened body before passing to request builder as well
|
|
933
933
|
retval.extend(_serialize_flattened_body(builder.parameters.body_parameter))
|
|
934
|
-
if is_json_model_type(builder.parameters):
|
|
934
|
+
if is_json_model_type(builder.parameters) and not is_paging:
|
|
935
|
+
# For paging, we put the json model body outside `prepare_request`
|
|
935
936
|
retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters))
|
|
936
937
|
if builder.has_form_data_body:
|
|
937
938
|
retval.extend(self._create_body_parameter(builder))
|
|
@@ -1369,7 +1370,13 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
|
|
|
1369
1370
|
return retval
|
|
1370
1371
|
|
|
1371
1372
|
def _prepare_request_callback(self, builder: PagingOperationType) -> list[str]:
|
|
1372
|
-
retval =
|
|
1373
|
+
retval: list[str] = []
|
|
1374
|
+
# The json model body must be constructed before `_initialize_overloads`
|
|
1375
|
+
# serializes it into the request content, and outside `prepare_request` so
|
|
1376
|
+
# the closure doesn't treat `body` as an unbound local.
|
|
1377
|
+
if is_json_model_type(builder.parameters):
|
|
1378
|
+
retval.extend(_serialize_json_model_body(builder.parameters.body_parameter, builder.parameters.parameters))
|
|
1379
|
+
retval.extend(self._initialize_overloads(builder))
|
|
1373
1380
|
if builder.has_continuation_token:
|
|
1374
1381
|
retval.append(f"def prepare_request({builder.next_variable_name}=None):")
|
|
1375
1382
|
retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])
|
|
@@ -66,7 +66,26 @@ class GeneralSerializer(BaseSerializer):
|
|
|
66
66
|
if dep_version > default_version:
|
|
67
67
|
version_map[dep_name] = str(dep_version)
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
# Project-level pyproject.toml fields that may be preserved across regeneration
|
|
70
|
+
# via the "keep-pyproject-fields" option.
|
|
71
|
+
KEEPABLE_PROJECT_FIELDS = ("authors", "description", "classifiers", "urls")
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def _parse_keep_pyproject_fields(value: Any) -> tuple[str, ...]:
|
|
75
|
+
# The "keep-pyproject-fields" option may be a comma-separated string (e.g.
|
|
76
|
+
# "authors,description") or an already-parsed sequence of field names.
|
|
77
|
+
if not value:
|
|
78
|
+
return ()
|
|
79
|
+
if isinstance(value, str):
|
|
80
|
+
return tuple(field.strip() for field in value.split(",") if field.strip())
|
|
81
|
+
return tuple(value)
|
|
82
|
+
|
|
83
|
+
def external_lib_version_map(
|
|
84
|
+
self,
|
|
85
|
+
file_content: str,
|
|
86
|
+
additional_version_map: dict[str, str],
|
|
87
|
+
keep_pyproject_fields: tuple[str, ...] = (),
|
|
88
|
+
) -> dict:
|
|
70
89
|
# Load the pyproject.toml file if it exists and extract fields to keep.
|
|
71
90
|
result: dict = {"KEEP_FIELDS": {}}
|
|
72
91
|
try:
|
|
@@ -85,6 +104,14 @@ class GeneralSerializer(BaseSerializer):
|
|
|
85
104
|
|
|
86
105
|
# Process dependencies
|
|
87
106
|
if "project" in loaded_pyproject_toml:
|
|
107
|
+
project = loaded_pyproject_toml["project"]
|
|
108
|
+
|
|
109
|
+
# Keep manually customized project fields the emitter would otherwise overwrite.
|
|
110
|
+
# Only the fields explicitly listed in the "keep-pyproject-fields" option are preserved.
|
|
111
|
+
for field in keep_pyproject_fields:
|
|
112
|
+
if field in self.KEEPABLE_PROJECT_FIELDS and field in project:
|
|
113
|
+
result["KEEP_FIELDS"][f"project.{field}"] = project[field]
|
|
114
|
+
|
|
88
115
|
# Handle main dependencies
|
|
89
116
|
if "dependencies" in loaded_pyproject_toml["project"]:
|
|
90
117
|
kept_deps = []
|
|
@@ -127,7 +154,10 @@ class GeneralSerializer(BaseSerializer):
|
|
|
127
154
|
|
|
128
155
|
# Add fields to keep from an existing pyproject.toml
|
|
129
156
|
if template_name == "pyproject.toml.jinja2":
|
|
130
|
-
|
|
157
|
+
keep_pyproject_fields = self._parse_keep_pyproject_fields(
|
|
158
|
+
self.code_model.options.get("keep-pyproject-fields")
|
|
159
|
+
)
|
|
160
|
+
params = self.external_lib_version_map(file_content, additional_version_map, keep_pyproject_fields)
|
|
131
161
|
else:
|
|
132
162
|
params = {}
|
|
133
163
|
|
|
@@ -112,6 +112,29 @@ def _serialize_bytes(o, format: typing.Optional[str] = None) -> str:
|
|
|
112
112
|
return encoded
|
|
113
113
|
|
|
114
114
|
|
|
115
|
+
def _serialize_duration(td: timedelta, format: typing.Optional[str] = None):
|
|
116
|
+
"""Serialize a timedelta to its wire representation.
|
|
117
|
+
|
|
118
|
+
For the ``seconds``/``milliseconds`` encodings the value is converted to a
|
|
119
|
+
numeric value, otherwise it falls back to an ISO 8601 duration string.
|
|
120
|
+
|
|
121
|
+
:param timedelta td: The timedelta to serialize.
|
|
122
|
+
:param str format: The duration encoding format.
|
|
123
|
+
:rtype: int or float or str
|
|
124
|
+
:return: serialized duration
|
|
125
|
+
"""
|
|
126
|
+
seconds = td.total_seconds()
|
|
127
|
+
if format == "duration-seconds-int":
|
|
128
|
+
return int(seconds)
|
|
129
|
+
if format == "duration-seconds-float":
|
|
130
|
+
return seconds
|
|
131
|
+
if format == "duration-milliseconds-int":
|
|
132
|
+
return int(seconds * 1000)
|
|
133
|
+
if format == "duration-milliseconds-float":
|
|
134
|
+
return seconds * 1000
|
|
135
|
+
return _timedelta_as_isostr(td)
|
|
136
|
+
|
|
137
|
+
|
|
115
138
|
def _serialize_datetime(o, format: typing.Optional[str] = None):
|
|
116
139
|
if hasattr(o, "year") and hasattr(o, "hour"):
|
|
117
140
|
if format == "rfc7231":
|
|
@@ -307,6 +330,12 @@ def _deserialize_duration(attr):
|
|
|
307
330
|
return isodate.parse_duration(attr)
|
|
308
331
|
|
|
309
332
|
|
|
333
|
+
def _deserialize_duration_numeric(attr, unit):
|
|
334
|
+
if isinstance(attr, timedelta):
|
|
335
|
+
return attr
|
|
336
|
+
return timedelta(**{unit: float(attr)})
|
|
337
|
+
|
|
338
|
+
|
|
310
339
|
def _deserialize_decimal(attr):
|
|
311
340
|
if isinstance(attr, decimal.Decimal):
|
|
312
341
|
return attr
|
|
@@ -336,6 +365,10 @@ _DESERIALIZE_MAPPING_WITHFORMAT = {
|
|
|
336
365
|
"unix-timestamp": _deserialize_datetime_unix_timestamp,
|
|
337
366
|
"base64": _deserialize_bytes,
|
|
338
367
|
"base64url": _deserialize_bytes_base64,
|
|
368
|
+
"duration-seconds-int": functools.partial(_deserialize_duration_numeric, unit="seconds"),
|
|
369
|
+
"duration-seconds-float": functools.partial(_deserialize_duration_numeric, unit="seconds"),
|
|
370
|
+
"duration-milliseconds-int": functools.partial(_deserialize_duration_numeric, unit="milliseconds"),
|
|
371
|
+
"duration-milliseconds-float": functools.partial(_deserialize_duration_numeric, unit="milliseconds"),
|
|
339
372
|
}
|
|
340
373
|
|
|
341
374
|
|
|
@@ -576,7 +609,7 @@ def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-m
|
|
|
576
609
|
pass
|
|
577
610
|
# Last, try datetime.timedelta
|
|
578
611
|
try:
|
|
579
|
-
return
|
|
612
|
+
return _serialize_duration(o, format)
|
|
580
613
|
except AttributeError:
|
|
581
614
|
# This will be raised when it hits value.total_seconds in the method above
|
|
582
615
|
pass
|
package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2
CHANGED
|
@@ -11,15 +11,32 @@ build-backend = "setuptools.build_meta"
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "{{ options.get('package-name')|lower }}"
|
|
13
13
|
{% if options.get('package-mode') %}
|
|
14
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.authors') %}
|
|
15
|
+
authors = [
|
|
16
|
+
{% for author in KEEP_FIELDS.get('project.authors') %}
|
|
17
|
+
{ {% for key, val in author.items() %}{{ key }} = {{ val|tojson }}{% if not loop.last %}, {% endif %}{% endfor %} },
|
|
18
|
+
{% endfor %}
|
|
19
|
+
]
|
|
20
|
+
{% else %}
|
|
14
21
|
authors = [
|
|
15
22
|
{ name = "{{ code_model.company_name }}"{% if code_model.is_azure_flavor %}, email = "azpysdkhelp@microsoft.com"{% endif %} },
|
|
16
23
|
]
|
|
17
|
-
{%
|
|
24
|
+
{% endif %}
|
|
25
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.description') %}
|
|
26
|
+
description = {{ KEEP_FIELDS.get('project.description')|tojson }}
|
|
27
|
+
{% elif options.get("azure-arm") %}
|
|
18
28
|
description = "Microsoft Azure {{ options.get('package-pprint-name') }} Client Library for Python"
|
|
19
29
|
{% else %}
|
|
20
30
|
description = "{{ code_model.company_name }} {% if code_model.is_azure_flavor and not options.get('package-pprint-name').startswith('Azure ') %}Azure {% endif %}{{ options.get('package-pprint-name') }} Client Library for Python"
|
|
21
31
|
{% endif %}
|
|
22
32
|
license = "MIT"
|
|
33
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.classifiers') %}
|
|
34
|
+
classifiers = [
|
|
35
|
+
{% for classifier in KEEP_FIELDS.get('project.classifiers') %}
|
|
36
|
+
{{ classifier|tojson }},
|
|
37
|
+
{% endfor %}
|
|
38
|
+
]
|
|
39
|
+
{% else %}
|
|
23
40
|
classifiers = [
|
|
24
41
|
"Development Status :: {{ dev_status }}",
|
|
25
42
|
"Programming Language :: Python",
|
|
@@ -29,10 +46,15 @@ classifiers = [
|
|
|
29
46
|
"Programming Language :: Python :: 3.{{ version }}",
|
|
30
47
|
{% endfor %}
|
|
31
48
|
]
|
|
49
|
+
{% endif %}
|
|
32
50
|
requires-python = ">={{ MIN_PYTHON_VERSION }}"
|
|
33
51
|
{% else %}
|
|
52
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.description') %}
|
|
53
|
+
description = {{ KEEP_FIELDS.get('project.description')|tojson }}
|
|
54
|
+
{% else %}
|
|
34
55
|
description = "{{ options.get('package-name') }}"
|
|
35
56
|
{% endif %}
|
|
57
|
+
{% endif %}
|
|
36
58
|
{% if code_model.is_azure_flavor %}
|
|
37
59
|
keywords = ["azure", "azure sdk"]
|
|
38
60
|
{% endif %}
|
|
@@ -77,7 +99,13 @@ version = "{{ options.get("package-version", "unknown") }}"
|
|
|
77
99
|
]
|
|
78
100
|
{% endfor %}
|
|
79
101
|
{% endif %}
|
|
80
|
-
{% if
|
|
102
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.urls') %}
|
|
103
|
+
|
|
104
|
+
[project.urls]
|
|
105
|
+
{% for key, val in KEEP_FIELDS.get('project.urls').items() %}
|
|
106
|
+
{{ key }} = {{ val|tojson }}
|
|
107
|
+
{% endfor %}
|
|
108
|
+
{% elif code_model.is_azure_flavor %}
|
|
81
109
|
|
|
82
110
|
[project.urls]
|
|
83
111
|
repository = "https://github.com/Azure/azure-sdk-for-python"
|
|
@@ -516,6 +516,10 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
516
516
|
"rfc-1123": Serializer.serialize_rfc,
|
|
517
517
|
"unix-time": Serializer.serialize_unix,
|
|
518
518
|
"duration": Serializer.serialize_duration,
|
|
519
|
+
"duration-seconds-int": Serializer.serialize_duration_seconds_int,
|
|
520
|
+
"duration-seconds-float": Serializer.serialize_duration_seconds_float,
|
|
521
|
+
"duration-milliseconds-int": Serializer.serialize_duration_milliseconds_int,
|
|
522
|
+
"duration-milliseconds-float": Serializer.serialize_duration_milliseconds_float,
|
|
519
523
|
"date": Serializer.serialize_date,
|
|
520
524
|
"time": Serializer.serialize_time,
|
|
521
525
|
"decimal": Serializer.serialize_decimal,
|
|
@@ -1105,6 +1109,61 @@ class Serializer: # pylint: disable=too-many-public-methods
|
|
|
1105
1109
|
attr = isodate.parse_duration(attr)
|
|
1106
1110
|
return isodate.duration_isoformat(attr)
|
|
1107
1111
|
|
|
1112
|
+
@staticmethod
|
|
1113
|
+
def _serialize_duration_numeric(attr, scale, as_int):
|
|
1114
|
+
"""Serialize a TimeDelta into a numeric value scaled to the wire unit.
|
|
1115
|
+
|
|
1116
|
+
:param TimeDelta attr: Object to be serialized.
|
|
1117
|
+
:param int scale: Multiplier applied to total seconds (1 for seconds, 1000 for milliseconds).
|
|
1118
|
+
:param bool as_int: Whether to truncate the result to an int.
|
|
1119
|
+
:rtype: int or float
|
|
1120
|
+
:return: serialized duration
|
|
1121
|
+
"""
|
|
1122
|
+
if isinstance(attr, str):
|
|
1123
|
+
attr = isodate.parse_duration(attr)
|
|
1124
|
+
value = attr.total_seconds() * scale if isinstance(attr, datetime.timedelta) else attr
|
|
1125
|
+
return int(value) if as_int else float(value)
|
|
1126
|
+
|
|
1127
|
+
@staticmethod
|
|
1128
|
+
def serialize_duration_seconds_int(attr, **kwargs): # pylint: disable=unused-argument
|
|
1129
|
+
"""Serialize TimeDelta object into an integer number of seconds.
|
|
1130
|
+
|
|
1131
|
+
:param TimeDelta attr: Object to be serialized.
|
|
1132
|
+
:rtype: int
|
|
1133
|
+
:return: serialized duration
|
|
1134
|
+
"""
|
|
1135
|
+
return Serializer._serialize_duration_numeric(attr, 1, True)
|
|
1136
|
+
|
|
1137
|
+
@staticmethod
|
|
1138
|
+
def serialize_duration_seconds_float(attr, **kwargs): # pylint: disable=unused-argument
|
|
1139
|
+
"""Serialize TimeDelta object into a floating point number of seconds.
|
|
1140
|
+
|
|
1141
|
+
:param TimeDelta attr: Object to be serialized.
|
|
1142
|
+
:rtype: float
|
|
1143
|
+
:return: serialized duration
|
|
1144
|
+
"""
|
|
1145
|
+
return Serializer._serialize_duration_numeric(attr, 1, False)
|
|
1146
|
+
|
|
1147
|
+
@staticmethod
|
|
1148
|
+
def serialize_duration_milliseconds_int(attr, **kwargs): # pylint: disable=unused-argument
|
|
1149
|
+
"""Serialize TimeDelta object into an integer number of milliseconds.
|
|
1150
|
+
|
|
1151
|
+
:param TimeDelta attr: Object to be serialized.
|
|
1152
|
+
:rtype: int
|
|
1153
|
+
:return: serialized duration
|
|
1154
|
+
"""
|
|
1155
|
+
return Serializer._serialize_duration_numeric(attr, 1000, True)
|
|
1156
|
+
|
|
1157
|
+
@staticmethod
|
|
1158
|
+
def serialize_duration_milliseconds_float(attr, **kwargs): # pylint: disable=unused-argument
|
|
1159
|
+
"""Serialize TimeDelta object into a floating point number of milliseconds.
|
|
1160
|
+
|
|
1161
|
+
:param TimeDelta attr: Object to be serialized.
|
|
1162
|
+
:rtype: float
|
|
1163
|
+
:return: serialized duration
|
|
1164
|
+
"""
|
|
1165
|
+
return Serializer._serialize_duration_numeric(attr, 1000, False)
|
|
1166
|
+
|
|
1108
1167
|
@staticmethod
|
|
1109
1168
|
def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument
|
|
1110
1169
|
"""Serialize Datetime object into RFC-1123 formatted string.
|
|
@@ -1377,6 +1436,10 @@ class Deserializer:
|
|
|
1377
1436
|
"rfc-1123": Deserializer.deserialize_rfc,
|
|
1378
1437
|
"unix-time": Deserializer.deserialize_unix,
|
|
1379
1438
|
"duration": Deserializer.deserialize_duration,
|
|
1439
|
+
"duration-seconds-int": Deserializer.deserialize_duration_seconds,
|
|
1440
|
+
"duration-seconds-float": Deserializer.deserialize_duration_seconds,
|
|
1441
|
+
"duration-milliseconds-int": Deserializer.deserialize_duration_milliseconds,
|
|
1442
|
+
"duration-milliseconds-float": Deserializer.deserialize_duration_milliseconds,
|
|
1380
1443
|
"date": Deserializer.deserialize_date,
|
|
1381
1444
|
"time": Deserializer.deserialize_time,
|
|
1382
1445
|
"decimal": Deserializer.deserialize_decimal,
|
|
@@ -1389,6 +1452,10 @@ class Deserializer:
|
|
|
1389
1452
|
}
|
|
1390
1453
|
self.deserialize_expected_types = {
|
|
1391
1454
|
"duration": (isodate.Duration, datetime.timedelta),
|
|
1455
|
+
"duration-seconds-int": (isodate.Duration, datetime.timedelta),
|
|
1456
|
+
"duration-seconds-float": (isodate.Duration, datetime.timedelta),
|
|
1457
|
+
"duration-milliseconds-int": (isodate.Duration, datetime.timedelta),
|
|
1458
|
+
"duration-milliseconds-float": (isodate.Duration, datetime.timedelta),
|
|
1392
1459
|
"iso-8601": (datetime.datetime),
|
|
1393
1460
|
}
|
|
1394
1461
|
self.dependencies: dict[str, type] = dict(classes) if classes else {}
|
|
@@ -1950,6 +2017,48 @@ class Deserializer:
|
|
|
1950
2017
|
raise DeserializationError(msg) from err
|
|
1951
2018
|
return duration
|
|
1952
2019
|
|
|
2020
|
+
@staticmethod
|
|
2021
|
+
def _deserialize_duration_numeric(attr, unit):
|
|
2022
|
+
"""Deserialize a numeric duration value into a TimeDelta object.
|
|
2023
|
+
|
|
2024
|
+
:param float attr: response value to be deserialized.
|
|
2025
|
+
:param str unit: The wire unit, used as the ``timedelta`` keyword
|
|
2026
|
+
(``"seconds"`` or ``"milliseconds"``).
|
|
2027
|
+
:return: Deserialized duration
|
|
2028
|
+
:rtype: TimeDelta
|
|
2029
|
+
:raises DeserializationError: if value is invalid.
|
|
2030
|
+
"""
|
|
2031
|
+
if isinstance(attr, ET.Element):
|
|
2032
|
+
attr = attr.text
|
|
2033
|
+
try:
|
|
2034
|
+
duration = datetime.timedelta(**{unit: float(attr)}) # type: ignore
|
|
2035
|
+
except (ValueError, OverflowError, TypeError) as err:
|
|
2036
|
+
msg = "Cannot deserialize duration object."
|
|
2037
|
+
raise DeserializationError(msg) from err
|
|
2038
|
+
return duration
|
|
2039
|
+
|
|
2040
|
+
@staticmethod
|
|
2041
|
+
def deserialize_duration_seconds(attr):
|
|
2042
|
+
"""Deserialize a numeric number of seconds into a TimeDelta object.
|
|
2043
|
+
|
|
2044
|
+
:param float attr: response value to be deserialized.
|
|
2045
|
+
:return: Deserialized duration
|
|
2046
|
+
:rtype: TimeDelta
|
|
2047
|
+
:raises DeserializationError: if value is invalid.
|
|
2048
|
+
"""
|
|
2049
|
+
return Deserializer._deserialize_duration_numeric(attr, "seconds")
|
|
2050
|
+
|
|
2051
|
+
@staticmethod
|
|
2052
|
+
def deserialize_duration_milliseconds(attr):
|
|
2053
|
+
"""Deserialize a numeric number of milliseconds into a TimeDelta object.
|
|
2054
|
+
|
|
2055
|
+
:param float attr: response value to be deserialized.
|
|
2056
|
+
:return: Deserialized duration
|
|
2057
|
+
:rtype: TimeDelta
|
|
2058
|
+
:raises DeserializationError: if value is invalid.
|
|
2059
|
+
"""
|
|
2060
|
+
return Deserializer._deserialize_duration_numeric(attr, "milliseconds")
|
|
2061
|
+
|
|
1953
2062
|
@staticmethod
|
|
1954
2063
|
def deserialize_date(attr):
|
|
1955
2064
|
"""Deserialize ISO-8601 formatted string into Date object.
|