@autorest/python 6.37.2 → 6.38.1
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/autorest/__init__.py +13 -0
- package/autorest/codegen.py +1 -0
- package/generator/build/lib/pygen/__init__.py +32 -2
- package/generator/build/lib/pygen/codegen/models/code_model.py +32 -0
- package/generator/build/lib/pygen/codegen/models/enum_type.py +4 -1
- package/generator/build/lib/pygen/codegen/models/model_type.py +4 -1
- package/generator/build/lib/pygen/codegen/models/operation.py +3 -4
- package/generator/build/lib/pygen/codegen/models/paging_operation.py +1 -1
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +85 -74
- package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +7 -6
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +86 -13
- package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +5 -4
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +109 -0
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/__init__.py +32 -2
- package/generator/pygen/codegen/models/code_model.py +32 -0
- package/generator/pygen/codegen/models/enum_type.py +4 -1
- package/generator/pygen/codegen/models/model_type.py +4 -1
- package/generator/pygen/codegen/models/operation.py +3 -4
- package/generator/pygen/codegen/models/paging_operation.py +1 -1
- package/generator/pygen/codegen/serializers/__init__.py +85 -74
- package/generator/pygen/codegen/serializers/builder_serializer.py +7 -6
- package/generator/pygen/codegen/serializers/general_serializer.py +86 -13
- package/generator/pygen/codegen/templates/model_base.py.jinja2 +5 -4
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +109 -0
- package/generator/pygen.egg-info/SOURCES.txt +1 -0
- package/package.json +2 -2
- package/scripts/__pycache__/venvtools.cpython-310.pyc +0 -0
|
@@ -1032,7 +1032,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1032
1032
|
is_operation_file=True, skip_quote=True, serialize_namespace=self.serialize_namespace
|
|
1033
1033
|
)
|
|
1034
1034
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1035
|
-
retval.append(f" error = _failsafe_deserialize({type_annotation}, response
|
|
1035
|
+
retval.append(f" error = _failsafe_deserialize({type_annotation}, response)")
|
|
1036
1036
|
else:
|
|
1037
1037
|
retval.append(
|
|
1038
1038
|
f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
|
|
@@ -1068,10 +1068,10 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1068
1068
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1069
1069
|
if xml_serializable(str(e.default_content_type)):
|
|
1070
1070
|
retval.append(
|
|
1071
|
-
f" error = _failsafe_deserialize_xml({type_annotation},
|
|
1071
|
+
f" error = _failsafe_deserialize_xml({type_annotation}, response)"
|
|
1072
1072
|
)
|
|
1073
1073
|
else:
|
|
1074
|
-
retval.append(f" error = _failsafe_deserialize({type_annotation},
|
|
1074
|
+
retval.append(f" error = _failsafe_deserialize({type_annotation}, response)")
|
|
1075
1075
|
else:
|
|
1076
1076
|
retval.append(
|
|
1077
1077
|
f" error = self._deserialize.failsafe_deserialize({type_annotation}, "
|
|
@@ -1079,18 +1079,19 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
|
|
|
1079
1079
|
)
|
|
1080
1080
|
condition = "elif"
|
|
1081
1081
|
# default error handling
|
|
1082
|
-
|
|
1082
|
+
default_error_deserialization = builder.default_error_deserialization(self.serialize_namespace)
|
|
1083
|
+
if default_error_deserialization and self.code_model.options["models-mode"]:
|
|
1083
1084
|
error_model = ", model=error"
|
|
1084
1085
|
indent = " " if builder.non_default_errors else " "
|
|
1085
1086
|
if builder.non_default_errors:
|
|
1086
1087
|
retval.append(" else:")
|
|
1087
1088
|
if self.code_model.options["models-mode"] == "dpg":
|
|
1088
1089
|
retval.append(
|
|
1089
|
-
f"{indent}error = _failsafe_deserialize({
|
|
1090
|
+
f"{indent}error = _failsafe_deserialize({default_error_deserialization}, response)"
|
|
1090
1091
|
)
|
|
1091
1092
|
else:
|
|
1092
1093
|
retval.append(
|
|
1093
|
-
f"{indent}error = self._deserialize.failsafe_deserialize({
|
|
1094
|
+
f"{indent}error = self._deserialize.failsafe_deserialize({default_error_deserialization}, "
|
|
1094
1095
|
"pipeline_response)"
|
|
1095
1096
|
)
|
|
1096
1097
|
retval.append(
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
6
|
import json
|
|
7
|
-
from typing import Any, List
|
|
7
|
+
from typing import Any, List, TYPE_CHECKING
|
|
8
|
+
import re
|
|
9
|
+
import tomli as tomllib
|
|
10
|
+
from packaging.version import parse as parse_version
|
|
8
11
|
from .import_serializer import FileImportSerializer, TypingSection
|
|
9
12
|
from ..models.imports import MsrestImportType, FileImport
|
|
10
13
|
from ..models import (
|
|
@@ -16,6 +19,9 @@ from ..models.utils import NamespaceType
|
|
|
16
19
|
from .client_serializer import ClientSerializer, ConfigSerializer
|
|
17
20
|
from .base_serializer import BaseSerializer
|
|
18
21
|
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
19
25
|
VERSION_MAP = {
|
|
20
26
|
"msrest": "0.7.1",
|
|
21
27
|
"isodate": "0.6.1",
|
|
@@ -42,8 +48,73 @@ class GeneralSerializer(BaseSerializer):
|
|
|
42
48
|
params.update({"options": self.code_model.options})
|
|
43
49
|
return template.render(code_model=self.code_model, **params)
|
|
44
50
|
|
|
45
|
-
def
|
|
51
|
+
def _extract_min_dependency(self, s):
|
|
52
|
+
# Extract the minimum version from a dependency string.
|
|
53
|
+
#
|
|
54
|
+
# Handles formats like:
|
|
55
|
+
# - >=1.2.3
|
|
56
|
+
# - >=0.1.0b1 (beta versions)
|
|
57
|
+
# - >=1.2.3rc2 (release candidates)
|
|
58
|
+
#
|
|
59
|
+
# Returns the parsed version if found, otherwise version "0".
|
|
60
|
+
m = re.search(r"[>=]=?([\d.]+(?:[a-z]+\d+)?)", s)
|
|
61
|
+
return parse_version(m.group(1)) if m else parse_version("0")
|
|
62
|
+
|
|
63
|
+
def _keep_pyproject_fields(self, file_path: "Path") -> dict:
|
|
64
|
+
# Load the pyproject.toml file if it exists and extract fields to keep.
|
|
65
|
+
result: dict = {"KEEP_FIELDS": {}}
|
|
66
|
+
try:
|
|
67
|
+
with open(file_path, "rb") as f:
|
|
68
|
+
loaded_pyproject_toml = tomllib.load(f)
|
|
69
|
+
except Exception: # pylint: disable=broad-except
|
|
70
|
+
# If parsing the pyproject.toml fails, we assume the it does not exist or is incorrectly formatted.
|
|
71
|
+
return result
|
|
72
|
+
|
|
73
|
+
# Keep azure-sdk-build configuration
|
|
74
|
+
if "tool" in loaded_pyproject_toml and "azure-sdk-build" in loaded_pyproject_toml["tool"]:
|
|
75
|
+
result["KEEP_FIELDS"]["tool.azure-sdk-build"] = loaded_pyproject_toml["tool"]["azure-sdk-build"]
|
|
76
|
+
|
|
77
|
+
# Process dependencies
|
|
78
|
+
if "project" in loaded_pyproject_toml:
|
|
79
|
+
# Handle main dependencies
|
|
80
|
+
if "dependencies" in loaded_pyproject_toml["project"]:
|
|
81
|
+
kept_deps = []
|
|
82
|
+
for dep in loaded_pyproject_toml["project"]["dependencies"]:
|
|
83
|
+
dep_name = re.split(r"[<>=\[]", dep)[0].strip()
|
|
84
|
+
|
|
85
|
+
# Check if dependency is one we track in VERSION_MAP
|
|
86
|
+
if dep_name in VERSION_MAP:
|
|
87
|
+
# For tracked dependencies, check if the version is higher than our default
|
|
88
|
+
default_version = parse_version(VERSION_MAP[dep_name])
|
|
89
|
+
dep_version = self._extract_min_dependency(dep)
|
|
90
|
+
# If the version is higher than the default, update VERSION_MAP
|
|
91
|
+
# with higher min dependency version
|
|
92
|
+
if dep_version > default_version:
|
|
93
|
+
VERSION_MAP[dep_name] = str(dep_version)
|
|
94
|
+
else:
|
|
95
|
+
# Keep non-default dependencies
|
|
96
|
+
kept_deps.append(dep)
|
|
97
|
+
|
|
98
|
+
if kept_deps:
|
|
99
|
+
result["KEEP_FIELDS"]["project.dependencies"] = kept_deps
|
|
100
|
+
|
|
101
|
+
# Keep optional dependencies
|
|
102
|
+
if "optional-dependencies" in loaded_pyproject_toml["project"]:
|
|
103
|
+
result["KEEP_FIELDS"]["project.optional-dependencies"] = loaded_pyproject_toml["project"][
|
|
104
|
+
"optional-dependencies"
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
return result
|
|
108
|
+
|
|
109
|
+
def serialize_package_file(self, template_name: str, file_path: "Path", **kwargs: Any) -> str:
|
|
46
110
|
template = self.env.get_template(template_name)
|
|
111
|
+
|
|
112
|
+
# Add fields to keep from an existing pyproject.toml
|
|
113
|
+
if template_name == "pyproject.toml.jinja2":
|
|
114
|
+
params = self._keep_pyproject_fields(file_path)
|
|
115
|
+
else:
|
|
116
|
+
params = {}
|
|
117
|
+
|
|
47
118
|
package_parts = (
|
|
48
119
|
self.code_model.namespace.split(".")[:-1]
|
|
49
120
|
if self.code_model.is_tsp
|
|
@@ -57,17 +128,19 @@ class GeneralSerializer(BaseSerializer):
|
|
|
57
128
|
dev_status = "4 - Beta"
|
|
58
129
|
else:
|
|
59
130
|
dev_status = "5 - Production/Stable"
|
|
60
|
-
params
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
131
|
+
params.update(
|
|
132
|
+
{
|
|
133
|
+
"code_model": self.code_model,
|
|
134
|
+
"dev_status": dev_status,
|
|
135
|
+
"token_credential": token_credential,
|
|
136
|
+
"pkgutil_names": [".".join(package_parts[: i + 1]) for i in range(len(package_parts))],
|
|
137
|
+
"init_names": ["/".join(package_parts[: i + 1]) + "/__init__.py" for i in range(len(package_parts))],
|
|
138
|
+
"client_name": self.code_model.clients[0].name if self.code_model.clients else "",
|
|
139
|
+
"VERSION_MAP": VERSION_MAP,
|
|
140
|
+
"MIN_PYTHON_VERSION": MIN_PYTHON_VERSION,
|
|
141
|
+
"MAX_PYTHON_VERSION": MAX_PYTHON_VERSION,
|
|
142
|
+
}
|
|
143
|
+
)
|
|
71
144
|
params.update({"options": self.code_model.options})
|
|
72
145
|
params.update(kwargs)
|
|
73
146
|
return template.render(file_import=FileImport(self.code_model), **params)
|
|
@@ -25,6 +25,7 @@ from {{ code_model.core_library }}.exceptions import DeserializationError
|
|
|
25
25
|
from {{ code_model.core_library }}{{ "" if code_model.is_azure_flavor else ".utils" }} import CaseInsensitiveEnumMeta
|
|
26
26
|
from {{ code_model.core_library }}.{{ "" if code_model.is_azure_flavor else "runtime." }}pipeline import PipelineResponse
|
|
27
27
|
from {{ code_model.core_library }}.serialization import _Null
|
|
28
|
+
from {{ code_model.core_library }}.rest import HttpResponse
|
|
28
29
|
|
|
29
30
|
_LOGGER = logging.getLogger(__name__)
|
|
30
31
|
|
|
@@ -935,13 +936,13 @@ def _deserialize(
|
|
|
935
936
|
|
|
936
937
|
def _failsafe_deserialize(
|
|
937
938
|
deserializer: typing.Any,
|
|
938
|
-
|
|
939
|
+
response: HttpResponse,
|
|
939
940
|
module: typing.Optional[str] = None,
|
|
940
941
|
rf: typing.Optional["_RestField"] = None,
|
|
941
942
|
format: typing.Optional[str] = None,
|
|
942
943
|
) -> typing.Any:
|
|
943
944
|
try:
|
|
944
|
-
return _deserialize(deserializer,
|
|
945
|
+
return _deserialize(deserializer, response.json(), module, rf, format)
|
|
945
946
|
except DeserializationError:
|
|
946
947
|
_LOGGER.warning(
|
|
947
948
|
"Ran into a deserialization error. Ignoring since this is failsafe deserialization",
|
|
@@ -952,10 +953,10 @@ def _failsafe_deserialize(
|
|
|
952
953
|
|
|
953
954
|
def _failsafe_deserialize_xml(
|
|
954
955
|
deserializer: typing.Any,
|
|
955
|
-
|
|
956
|
+
response: HttpResponse,
|
|
956
957
|
) -> typing.Any:
|
|
957
958
|
try:
|
|
958
|
-
return _deserialize_xml(deserializer,
|
|
959
|
+
return _deserialize_xml(deserializer, response.text())
|
|
959
960
|
except DeserializationError:
|
|
960
961
|
_LOGGER.warning(
|
|
961
962
|
"Ran into a deserialization error. Ignoring since this is failsafe deserialization",
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{% set min_version = MIN_PYTHON_VERSION.split('.')[1] | int %}
|
|
2
|
+
{% set max_version = MAX_PYTHON_VERSION.split('.')[1] | int %}
|
|
3
|
+
{% if code_model.license_header %}
|
|
4
|
+
{{ code_model.license_header }}
|
|
5
|
+
{% endif %}
|
|
6
|
+
|
|
7
|
+
[build-system]
|
|
8
|
+
requires = ["setuptools>=77.0.3", "wheel"]
|
|
9
|
+
build-backend = "setuptools.build_meta"
|
|
10
|
+
|
|
11
|
+
[project]
|
|
12
|
+
name = "{{ options.get('package-name')|lower }}"
|
|
13
|
+
{% if options.get('package-mode') %}
|
|
14
|
+
authors = [
|
|
15
|
+
{ name = "{{ code_model.company_name }}"{% if code_model.is_azure_flavor %}, email = "azpysdkhelp@microsoft.com"{% endif %} },
|
|
16
|
+
]
|
|
17
|
+
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"
|
|
18
|
+
license = "MIT"
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: {{ dev_status }}",
|
|
21
|
+
"Programming Language :: Python",
|
|
22
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
{% for version in range(min_version, max_version + 1) %}
|
|
25
|
+
"Programming Language :: Python :: 3.{{ version }}",
|
|
26
|
+
{% endfor %}
|
|
27
|
+
]
|
|
28
|
+
requires-python = ">={{ MIN_PYTHON_VERSION }}"
|
|
29
|
+
{% else %}
|
|
30
|
+
description = "{{ options.get('package-name') }}"
|
|
31
|
+
{% endif %}
|
|
32
|
+
{% if code_model.is_azure_flavor %}
|
|
33
|
+
keywords = ["azure", "azure sdk"]
|
|
34
|
+
{% endif %}
|
|
35
|
+
|
|
36
|
+
dependencies = [
|
|
37
|
+
{% if code_model.is_legacy %}
|
|
38
|
+
"msrest>={{ VERSION_MAP['msrest'] }}",
|
|
39
|
+
{% else %}
|
|
40
|
+
"isodate>={{ VERSION_MAP['isodate'] }}",
|
|
41
|
+
{% endif %}
|
|
42
|
+
{% if options.get('azure_arm') %}
|
|
43
|
+
"azure-mgmt-core>={{ VERSION_MAP['azure-mgmt-core'] }}",
|
|
44
|
+
{% elif code_model.is_azure_flavor %}
|
|
45
|
+
"azure-core>={{ VERSION_MAP['azure-core'] }}",
|
|
46
|
+
{% else %}
|
|
47
|
+
"corehttp[requests]>={{ VERSION_MAP['corehttp'] }}",
|
|
48
|
+
{% endif %}
|
|
49
|
+
"typing-extensions>={{ VERSION_MAP['typing-extensions'] }}",
|
|
50
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.dependencies') %}
|
|
51
|
+
{% for dep in KEEP_FIELDS.get('project.dependencies') %}
|
|
52
|
+
"{{ dep }}",
|
|
53
|
+
{% endfor %}
|
|
54
|
+
{% endif %}
|
|
55
|
+
]
|
|
56
|
+
dynamic = [
|
|
57
|
+
{% if options.get('package-mode') %}"version", {% endif %}"readme"
|
|
58
|
+
]
|
|
59
|
+
{% if not options.get('package-mode') %}
|
|
60
|
+
version = "{{ options.get("package-version", "unknown") }}"
|
|
61
|
+
{% endif %}
|
|
62
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('project.optional-dependencies') %}
|
|
63
|
+
|
|
64
|
+
[project.optional-dependencies]
|
|
65
|
+
{% for key, val in KEEP_FIELDS.get('project.optional-dependencies').items() %}
|
|
66
|
+
{{ key }} = [
|
|
67
|
+
{% for dep in val %}
|
|
68
|
+
"{{ dep }}",
|
|
69
|
+
{% endfor %}
|
|
70
|
+
]
|
|
71
|
+
{% endfor %}
|
|
72
|
+
{% endif %}
|
|
73
|
+
{% if code_model.is_azure_flavor %}
|
|
74
|
+
|
|
75
|
+
[project.urls]
|
|
76
|
+
repository = "https://github.com/Azure/azure-sdk-for-python/tree/main/sdk"
|
|
77
|
+
{% endif %}
|
|
78
|
+
|
|
79
|
+
[tool.setuptools.dynamic]
|
|
80
|
+
{% if options.get('package-mode') %}
|
|
81
|
+
{% if code_model.is_tsp %}
|
|
82
|
+
version = {attr = "{{ code_model.namespace|lower }}._version.VERSION"}
|
|
83
|
+
{% else %}
|
|
84
|
+
version = {attr = "{{ options.get('package-name')|lower|replace('-', '.') }}._version.VERSION"}
|
|
85
|
+
{% endif %}
|
|
86
|
+
{% endif %}
|
|
87
|
+
readme = {file = ["README.md"], content-type = "text/markdown"}
|
|
88
|
+
{% if options.get('package-mode') %}
|
|
89
|
+
|
|
90
|
+
[tool.setuptools.packages.find]
|
|
91
|
+
exclude = [
|
|
92
|
+
"tests*",
|
|
93
|
+
"samples*",
|
|
94
|
+
"doc*",
|
|
95
|
+
{% for pkgutil_name in pkgutil_names %}
|
|
96
|
+
"{{ pkgutil_name }}",
|
|
97
|
+
{% endfor %}
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[tool.setuptools.package-data]
|
|
101
|
+
pytyped = ["py.typed"]
|
|
102
|
+
{% endif %}
|
|
103
|
+
{% if KEEP_FIELDS and KEEP_FIELDS.get('tool.azure-sdk-build') %}
|
|
104
|
+
|
|
105
|
+
[tool.azure-sdk-build]
|
|
106
|
+
{% for key, val in KEEP_FIELDS.get('tool.azure-sdk-build').items() %}
|
|
107
|
+
{{ key }} = {{ val|tojson }}
|
|
108
|
+
{% endfor %}
|
|
109
|
+
{% endif %}
|
|
Binary file
|
|
@@ -25,10 +25,10 @@ class OptionsDict(MutableMapping):
|
|
|
25
25
|
"azure-arm": False,
|
|
26
26
|
"basic-setup-py": False,
|
|
27
27
|
"client-side-validation": False,
|
|
28
|
-
"emit-cross-language-definition-file": False,
|
|
29
28
|
"flavor": "azure", # need to default to azure in shared code so we don't break swagger generation
|
|
30
29
|
"from-typespec": False,
|
|
31
30
|
"generate-sample": False,
|
|
31
|
+
"keep-setup-py": False,
|
|
32
32
|
"generate-test": False,
|
|
33
33
|
"head-as-boolean": True,
|
|
34
34
|
"keep-version-file": False,
|
|
@@ -39,13 +39,14 @@ class OptionsDict(MutableMapping):
|
|
|
39
39
|
"polymorphic-examples": 5,
|
|
40
40
|
"validate-versioning": True,
|
|
41
41
|
"version-tolerant": True,
|
|
42
|
+
"generation-subdir": None, # subdirectory to generate the code in
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
def __init__(self, options: Optional[Dict[str, Any]] = None) -> None:
|
|
45
46
|
self._data = options.copy() if options else {}
|
|
46
47
|
self._validate_combinations()
|
|
47
48
|
|
|
48
|
-
def __getitem__(self, key: str) -> Any:
|
|
49
|
+
def __getitem__(self, key: str) -> Any: # pylint: disable=too-many-return-statements
|
|
49
50
|
if key == "head-as-boolean" and self.get("azure-arm"):
|
|
50
51
|
# override to always true if azure-arm is set
|
|
51
52
|
return True
|
|
@@ -60,6 +61,18 @@ class OptionsDict(MutableMapping):
|
|
|
60
61
|
if key == "package-mode" and self._data.get("packaging-files-dir"):
|
|
61
62
|
# if packaging-files-dir is set, use it as package-mode
|
|
62
63
|
return self._data["packaging-files-dir"]
|
|
64
|
+
if key == "generation-subdir":
|
|
65
|
+
data = self._data.get("generation-subdir")
|
|
66
|
+
if data:
|
|
67
|
+
# Remove leading dot or ./ from generation-subdir
|
|
68
|
+
if data.startswith("./"):
|
|
69
|
+
data = data[2:]
|
|
70
|
+
elif data.startswith("."):
|
|
71
|
+
data = data[1:]
|
|
72
|
+
# Remove trailing slashes
|
|
73
|
+
if data.endswith("/") or data.endswith("\\"):
|
|
74
|
+
data = data[:-1]
|
|
75
|
+
return data
|
|
63
76
|
return self._get_default(key)
|
|
64
77
|
|
|
65
78
|
def __setitem__(self, key: str, value: Any) -> None:
|
|
@@ -106,6 +119,8 @@ class OptionsDict(MutableMapping):
|
|
|
106
119
|
models_mode_default = "dpg"
|
|
107
120
|
# switch to falsy value for easier code writing
|
|
108
121
|
return models_mode_default
|
|
122
|
+
if key == "emit-cross-language-definition-file":
|
|
123
|
+
return self.get("flavor") == "azure"
|
|
109
124
|
return self.DEFAULTS[key]
|
|
110
125
|
|
|
111
126
|
def _validate_combinations(self) -> None:
|
|
@@ -134,6 +149,10 @@ class OptionsDict(MutableMapping):
|
|
|
134
149
|
"We are working on creating a new multiapi SDK for version tolerant and it is not available yet."
|
|
135
150
|
)
|
|
136
151
|
|
|
152
|
+
# If multiapi, do not generate default pyproject.toml
|
|
153
|
+
if self.get("multiapi"):
|
|
154
|
+
self["keep-setup-py"] = True
|
|
155
|
+
|
|
137
156
|
if self.get("client-side-validation") and self.get("version-tolerant"):
|
|
138
157
|
raise ValueError("Can not generate version tolerant with --client-side-validation. ")
|
|
139
158
|
|
|
@@ -210,6 +229,9 @@ class ReaderAndWriter:
|
|
|
210
229
|
_LOGGER.warning("Loading python.json file. This behavior will be depreacted")
|
|
211
230
|
self.options.update(python_json)
|
|
212
231
|
|
|
232
|
+
def get_output_folder(self) -> Path:
|
|
233
|
+
return self.output_folder
|
|
234
|
+
|
|
213
235
|
def read_file(self, path: Union[str, Path]) -> str:
|
|
214
236
|
"""Directly reading from disk"""
|
|
215
237
|
# make path relative to output folder
|
|
@@ -227,6 +249,14 @@ class ReaderAndWriter:
|
|
|
227
249
|
with open(self.output_folder / Path(filename), "w", encoding="utf-8") as fd:
|
|
228
250
|
fd.write(file_content)
|
|
229
251
|
|
|
252
|
+
def remove_file(self, filename: Union[str, Path]) -> None:
|
|
253
|
+
try:
|
|
254
|
+
file_path = self.output_folder / Path(filename)
|
|
255
|
+
if file_path.is_file():
|
|
256
|
+
file_path.unlink()
|
|
257
|
+
except FileNotFoundError:
|
|
258
|
+
pass
|
|
259
|
+
|
|
230
260
|
def list_file(self) -> List[str]:
|
|
231
261
|
return [str(f.relative_to(self.output_folder)) for f in self.output_folder.glob("**/*") if f.is_file()]
|
|
232
262
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
from pathlib import Path
|
|
6
7
|
from typing import List, Dict, Any, Set, Union, Literal, Optional, cast
|
|
7
8
|
|
|
8
9
|
from .base import BaseType
|
|
@@ -452,3 +453,34 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
452
453
|
return self.yaml_data.get("licenseInfo", {}).get("company", "")
|
|
453
454
|
# typespec azure case without custom license and swagger case
|
|
454
455
|
return "Microsoft Corporation"
|
|
456
|
+
|
|
457
|
+
def get_root_dir(self) -> Path:
|
|
458
|
+
if self.options["no-namespace-folders"]:
|
|
459
|
+
# when output folder contains parts different from the namespace, we fall back to current folder directly.
|
|
460
|
+
return Path(".")
|
|
461
|
+
return Path(*self.namespace.split("."))
|
|
462
|
+
|
|
463
|
+
def get_generation_dir(self, namespace: str) -> Path:
|
|
464
|
+
"""The directory to generate the code in.
|
|
465
|
+
|
|
466
|
+
If 'generation-subdir' is specified, it will be used as a subdirectory.
|
|
467
|
+
"""
|
|
468
|
+
root_dir = self.get_root_dir()
|
|
469
|
+
retval = self._get_relative_generation_dir(root_dir, namespace)
|
|
470
|
+
return retval
|
|
471
|
+
|
|
472
|
+
def _get_relative_generation_dir(self, root_dir: Path, namespace: str) -> Path:
|
|
473
|
+
if self.options["no-namespace-folders"]:
|
|
474
|
+
return Path(".")
|
|
475
|
+
if self.options.get("generation-subdir"):
|
|
476
|
+
# For the main namespace, return root_dir + generation-subdir
|
|
477
|
+
if namespace in ("", self.namespace):
|
|
478
|
+
return root_dir / self.options["generation-subdir"]
|
|
479
|
+
|
|
480
|
+
# For subnamespaces, extract the subnamespace part and append it to generation-subdir
|
|
481
|
+
if namespace.startswith(self.namespace + "."):
|
|
482
|
+
subnamespace_parts = namespace[len(self.namespace) + 1 :].split(".")
|
|
483
|
+
return root_dir / self.options["generation-subdir"] / Path(*subnamespace_parts)
|
|
484
|
+
|
|
485
|
+
# No generation-subdir specified, use the namespace path directly
|
|
486
|
+
return Path(*namespace.split("."))
|
|
@@ -52,7 +52,10 @@ class EnumValue(BaseType):
|
|
|
52
52
|
"""The python type used for RST syntax input and type annotation."""
|
|
53
53
|
|
|
54
54
|
type_annotation = self.value_type.type_annotation(**kwargs)
|
|
55
|
-
|
|
55
|
+
client_namespace = self.enum_type.client_namespace
|
|
56
|
+
if self.code_model.options.get("generation-subdir"):
|
|
57
|
+
client_namespace += f".{self.code_model.options['generation-subdir']}"
|
|
58
|
+
enum_type_annotation = f"{client_namespace}.models.{self.name}"
|
|
56
59
|
return f"{type_annotation} or ~{enum_type_annotation}"
|
|
57
60
|
|
|
58
61
|
def get_json_template_representation(
|
|
@@ -292,7 +292,10 @@ class GeneratedModelType(ModelType):
|
|
|
292
292
|
|
|
293
293
|
def docstring_type(self, **kwargs: Any) -> str:
|
|
294
294
|
type_annotation = self.type_annotation(need_model_alias=False, skip_quote=True, **kwargs)
|
|
295
|
-
|
|
295
|
+
client_namespace = self.client_namespace
|
|
296
|
+
if self.code_model.options.get("generation-subdir"):
|
|
297
|
+
client_namespace += f".{self.code_model.options['generation-subdir']}"
|
|
298
|
+
return f"~{client_namespace}.models.{type_annotation}"
|
|
296
299
|
|
|
297
300
|
def docstring_text(self, **kwargs: Any) -> str:
|
|
298
301
|
return self.name
|
|
@@ -194,14 +194,13 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
194
194
|
def any_response_has_headers(self) -> bool:
|
|
195
195
|
return any(response.headers for response in self.responses)
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
def default_error_deserialization(self) -> Optional[str]:
|
|
197
|
+
def default_error_deserialization(self, serialize_namespace: str) -> Optional[str]:
|
|
199
198
|
default_exceptions = [e for e in self.exceptions if "default" in e.status_codes and e.type]
|
|
200
199
|
if not default_exceptions:
|
|
201
200
|
return None
|
|
202
201
|
exception_schema = default_exceptions[0].type
|
|
203
202
|
if isinstance(exception_schema, ModelType):
|
|
204
|
-
return exception_schema.type_annotation(skip_quote=True)
|
|
203
|
+
return exception_schema.type_annotation(skip_quote=True, serialize_namespace=serialize_namespace)
|
|
205
204
|
return None if self.code_model.options["models-mode"] == "dpg" else "'object'"
|
|
206
205
|
|
|
207
206
|
@property
|
|
@@ -469,7 +468,7 @@ class OperationBase( # pylint: disable=too-many-public-methods,too-many-instanc
|
|
|
469
468
|
file_import.add_submodule_import(relative_path, "_deserialize_xml", ImportType.LOCAL)
|
|
470
469
|
elif self.need_deserialize:
|
|
471
470
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
472
|
-
if self.default_error_deserialization or self.non_default_errors:
|
|
471
|
+
if self.default_error_deserialization(serialize_namespace) or self.non_default_errors:
|
|
473
472
|
file_import.add_submodule_import(relative_path, "_failsafe_deserialize", ImportType.LOCAL)
|
|
474
473
|
return file_import
|
|
475
474
|
|
|
@@ -173,7 +173,7 @@ class PagingOperationBase(OperationBase[PagingResponseType]):
|
|
|
173
173
|
serialize_namespace, module_name="_utils.model_base"
|
|
174
174
|
)
|
|
175
175
|
file_import.merge(self.item_type.imports(**kwargs))
|
|
176
|
-
if self.default_error_deserialization or self.need_deserialize:
|
|
176
|
+
if self.default_error_deserialization(serialize_namespace) or self.need_deserialize:
|
|
177
177
|
file_import.add_submodule_import(relative_path, "_deserialize", ImportType.LOCAL)
|
|
178
178
|
return file_import
|
|
179
179
|
|