@typespec/http-client-python 0.32.0 → 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.js +10 -2
- 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/emitter/src/emitter.ts +9 -1
- package/emitter/src/lib.ts +36 -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/utils.py +17 -12
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +32 -2
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +30 -2
- package/generator/build/lib/pygen/preprocess/__init__.py +168 -52
- package/generator/build/lib/pygen/utils.py +38 -4
- 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/utils.py +17 -12
- package/generator/pygen/codegen/serializers/general_serializer.py +32 -2
- package/generator/pygen/codegen/templates/packaging_templates/pyproject.toml.jinja2 +30 -2
- package/generator/pygen/preprocess/__init__.py +168 -52
- package/generator/pygen/utils.py +38 -4
- package/package.json +1 -1
|
@@ -11,8 +11,31 @@ SWAGGER_PACKAGE_MODE = ["mgmtplane", "dataplane"] # for backward compatibility
|
|
|
11
11
|
TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
|
|
12
12
|
VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
|
|
13
13
|
|
|
14
|
+
CODE_BLOCK_MARKER = ".. code-block::"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def description_ends_with_code_block(description: str) -> bool:
|
|
18
|
+
"""Return True when the description's trailing content is an RST ``.. code-block::``.
|
|
19
|
+
|
|
20
|
+
True when the last ``.. code-block::`` directive (starting its own line, so inline
|
|
21
|
+
mentions are ignored) is followed only by blank or indented lines, i.e. the literal
|
|
22
|
+
block runs to the end of the description.
|
|
23
|
+
"""
|
|
24
|
+
lines = description.rstrip().splitlines()
|
|
25
|
+
directives = [
|
|
26
|
+
i for i, line in enumerate(lines) if line.lstrip().startswith(CODE_BLOCK_MARKER)
|
|
27
|
+
]
|
|
28
|
+
if not directives:
|
|
29
|
+
return False
|
|
30
|
+
return all(
|
|
31
|
+
not line.strip() or line.startswith((" ", "\t"))
|
|
32
|
+
for line in lines[directives[-1] + 1 :]
|
|
33
|
+
)
|
|
34
|
+
|
|
14
35
|
|
|
15
|
-
def update_enum_value(
|
|
36
|
+
def update_enum_value(
|
|
37
|
+
name: str, value: Any, description: str, enum_type: dict[str, Any]
|
|
38
|
+
) -> dict[str, Any]:
|
|
16
39
|
return {
|
|
17
40
|
"name": name,
|
|
18
41
|
"type": "enumvalue",
|
|
@@ -39,7 +62,12 @@ def to_snake_case(name: str) -> str:
|
|
|
39
62
|
and len(name) - next_non_upper_case_char_location > 1
|
|
40
63
|
and name[next_non_upper_case_char_location].isalpha()
|
|
41
64
|
):
|
|
42
|
-
return
|
|
65
|
+
return (
|
|
66
|
+
prefix
|
|
67
|
+
+ match_str[: len(match_str) - 1]
|
|
68
|
+
+ "_"
|
|
69
|
+
+ match_str[len(match_str) - 1]
|
|
70
|
+
)
|
|
43
71
|
|
|
44
72
|
return prefix + match_str
|
|
45
73
|
|
|
@@ -86,7 +114,9 @@ def parse_args(
|
|
|
86
114
|
return value
|
|
87
115
|
|
|
88
116
|
unknown_args_ret = {
|
|
89
|
-
ua.strip("--").split("=", maxsplit=1)[0]: _get_value(
|
|
117
|
+
ua.strip("--").split("=", maxsplit=1)[0]: _get_value(
|
|
118
|
+
ua.strip("--").split("=", maxsplit=1)[1]
|
|
119
|
+
)
|
|
90
120
|
for ua in unknown_args
|
|
91
121
|
}
|
|
92
122
|
return args, unknown_args_ret
|
|
@@ -128,7 +158,11 @@ def build_policies(
|
|
|
128
158
|
"self._config.user_agent_policy",
|
|
129
159
|
"self._config.proxy_policy",
|
|
130
160
|
"policies.ContentDecodePolicy(**kwargs)",
|
|
131
|
-
(
|
|
161
|
+
(
|
|
162
|
+
f"{async_prefix}ARMAutoResourceProviderRegistrationPolicy()"
|
|
163
|
+
if is_arm
|
|
164
|
+
else None
|
|
165
|
+
),
|
|
132
166
|
"self._config.redirect_policy",
|
|
133
167
|
"self._config.retry_policy",
|
|
134
168
|
"self._config.authentication_policy",
|
|
Binary file
|
|
@@ -7,23 +7,24 @@ 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
|
-
CODE_BLOCK_MARKER = ".. code-block::"
|
|
15
|
-
|
|
16
|
-
|
|
17
16
|
def add_to_description(description: str, entry: str) -> str:
|
|
18
17
|
if not description:
|
|
19
18
|
return entry
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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()}"
|
|
27
28
|
return f"{description} {entry}"
|
|
28
29
|
|
|
29
30
|
|
|
@@ -44,6 +45,10 @@ class NamespaceType(str, Enum):
|
|
|
44
45
|
|
|
45
46
|
LOCALS_LENGTH_LIMIT = 25
|
|
46
47
|
|
|
47
|
-
REQUEST_BUILDER_BODY_VARIABLES_LENGTH =
|
|
48
|
+
REQUEST_BUILDER_BODY_VARIABLES_LENGTH = (
|
|
49
|
+
6 # how many body variables are present in a request builder
|
|
50
|
+
)
|
|
48
51
|
|
|
49
|
-
OPERATION_BODY_VARIABLES_LENGTH =
|
|
52
|
+
OPERATION_BODY_VARIABLES_LENGTH = (
|
|
53
|
+
14 # how many body variables are present in an operation
|
|
54
|
+
)
|
|
@@ -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
|
|
|
@@ -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"
|