@typespec/http-client-python 0.8.1 → 0.8.2
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/README.md +92 -84
- package/dist/emitter/code-model.d.ts +1 -2
- package/dist/emitter/code-model.d.ts.map +1 -1
- package/dist/emitter/code-model.js +2 -2
- package/dist/emitter/code-model.js.map +1 -1
- package/dist/emitter/emitter.d.ts +0 -2
- package/dist/emitter/emitter.d.ts.map +1 -1
- package/dist/emitter/emitter.js +21 -32
- package/dist/emitter/emitter.js.map +1 -1
- package/dist/emitter/http.d.ts +4 -4
- package/dist/emitter/http.d.ts.map +1 -1
- package/dist/emitter/http.js.map +1 -1
- package/dist/emitter/index.d.ts +1 -1
- package/dist/emitter/index.d.ts.map +1 -1
- package/dist/emitter/index.js +1 -1
- package/dist/emitter/index.js.map +1 -1
- package/dist/emitter/lib.d.ts +65 -21
- package/dist/emitter/lib.d.ts.map +1 -1
- package/dist/emitter/lib.js +56 -26
- package/dist/emitter/lib.js.map +1 -1
- package/dist/emitter/types.d.ts +3 -3
- package/dist/emitter/types.d.ts.map +1 -1
- package/dist/emitter/types.js.map +1 -1
- package/dist/emitter/utils.d.ts +5 -4
- package/dist/emitter/utils.d.ts.map +1 -1
- package/dist/emitter/utils.js +31 -16
- package/dist/emitter/utils.js.map +1 -1
- package/emitter/src/code-model.ts +13 -25
- package/emitter/src/emitter.ts +35 -51
- package/emitter/src/http.ts +18 -21
- package/emitter/src/index.ts +1 -1
- package/emitter/src/lib.ts +68 -40
- package/emitter/src/types.ts +13 -23
- package/emitter/src/utils.ts +36 -25
- package/emitter/temp/tsconfig.tsbuildinfo +1 -1
- package/eng/scripts/Generate.ps1 +3 -0
- package/eng/scripts/ci/regenerate.ts +92 -41
- package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
- package/generator/build/lib/pygen/codegen/__init__.py +0 -2
- package/generator/build/lib/pygen/codegen/models/code_model.py +5 -5
- package/generator/build/lib/pygen/codegen/serializers/__init__.py +18 -14
- package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +5 -2
- package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +1 -1
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +6 -2
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +5 -5
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +3 -3
- package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +14 -5
- package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
- package/generator/pygen/codegen/__init__.py +0 -2
- package/generator/pygen/codegen/models/code_model.py +5 -5
- package/generator/pygen/codegen/serializers/__init__.py +18 -14
- package/generator/pygen/codegen/serializers/general_serializer.py +5 -2
- package/generator/pygen/codegen/serializers/test_serializer.py +1 -1
- package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +6 -2
- package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +5 -5
- package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +3 -3
- package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +14 -5
- package/generator/pygen.egg-info/PKG-INFO +2 -2
- package/generator/pygen.egg-info/requires.txt +2 -2
- package/generator/setup.py +2 -2
- package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py +2 -2
- package/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py +1 -1
- package/generator/test/azure/requirements.txt +1 -1
- package/package.json +6 -5
|
@@ -38,96 +38,167 @@ interface TspCommand {
|
|
|
38
38
|
command: string;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
const AZURE_EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, string>[]> = {
|
|
42
|
+
"azure/example/basic": {
|
|
43
|
+
namespace: "specs.azure.example.basic",
|
|
44
|
+
},
|
|
45
|
+
"azure/client-generator-core/access": {
|
|
46
|
+
namespace: "specs.azure.clientgenerator.core.access",
|
|
47
|
+
},
|
|
48
|
+
"azure/client-generator-core/usage": {
|
|
49
|
+
namespace: "specs.azure.clientgenerator.core.usage",
|
|
50
|
+
},
|
|
51
|
+
"client/structure/default": {
|
|
52
|
+
namespace: "client.structure.service",
|
|
53
|
+
},
|
|
54
|
+
"client/structure/multi-client": {
|
|
55
|
+
"package-name": "client-structure-multiclient",
|
|
56
|
+
namespace: "client.structure.multiclient",
|
|
57
|
+
},
|
|
58
|
+
"client/structure/renamed-operation": {
|
|
59
|
+
"package-name": "client-structure-renamedoperation",
|
|
60
|
+
namespace: "client.structure.renamedoperation",
|
|
61
|
+
},
|
|
62
|
+
"client/structure/two-operation-group": {
|
|
63
|
+
"package-name": "client-structure-twooperationgroup",
|
|
64
|
+
namespace: "client.structure.twooperationgroup",
|
|
65
|
+
},
|
|
66
|
+
"client/naming": {
|
|
67
|
+
namespace: "client.naming",
|
|
68
|
+
},
|
|
69
|
+
"encode/duration": {
|
|
70
|
+
namespace: "encode.duration",
|
|
71
|
+
},
|
|
72
|
+
"encode/numeric": {
|
|
73
|
+
namespace: "encode.numeric",
|
|
74
|
+
},
|
|
75
|
+
"parameters/basic": {
|
|
76
|
+
namespace: "parameters.basic",
|
|
77
|
+
},
|
|
78
|
+
"parameters/spread": {
|
|
79
|
+
namespace: "parameters.spread",
|
|
80
|
+
},
|
|
81
|
+
"payload/content-negotiation": {
|
|
82
|
+
namespace: "payload.contentnegotiation",
|
|
83
|
+
},
|
|
84
|
+
"payload/multipart": {
|
|
85
|
+
namespace: "payload.multipart",
|
|
86
|
+
},
|
|
87
|
+
"serialization/encoded-name/json": {
|
|
88
|
+
namespace: "serialization.encodedname.json",
|
|
89
|
+
},
|
|
90
|
+
"special-words": {
|
|
91
|
+
namespace: "specialwords",
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
41
95
|
const EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, string>[]> = {
|
|
42
96
|
"resiliency/srv-driven/old.tsp": {
|
|
43
97
|
"package-name": "resiliency-srv-driven1",
|
|
98
|
+
namespace: "resiliency.srv.driven1",
|
|
44
99
|
"package-mode": "azure-dataplane",
|
|
45
100
|
"package-pprint-name": "ResiliencySrvDriven1",
|
|
46
101
|
},
|
|
47
102
|
"resiliency/srv-driven": {
|
|
48
103
|
"package-name": "resiliency-srv-driven2",
|
|
104
|
+
namespace: "resiliency.srv.driven2",
|
|
49
105
|
"package-mode": "azure-dataplane",
|
|
50
106
|
"package-pprint-name": "ResiliencySrvDriven2",
|
|
51
107
|
},
|
|
52
108
|
"authentication/http/custom": {
|
|
53
109
|
"package-name": "authentication-http-custom",
|
|
110
|
+
namespace: "authentication.http.custom",
|
|
54
111
|
"package-pprint-name": "Authentication Http Custom",
|
|
55
112
|
},
|
|
56
113
|
"authentication/union": {
|
|
57
114
|
"package-name": "authentication-union",
|
|
115
|
+
namespace: "authentication.union",
|
|
58
116
|
},
|
|
59
117
|
"type/array": {
|
|
60
118
|
"package-name": "typetest-array",
|
|
119
|
+
namespace: "typetest.array",
|
|
61
120
|
"use-pyodide": "true",
|
|
62
121
|
},
|
|
63
122
|
"type/dictionary": {
|
|
64
123
|
"package-name": "typetest-dictionary",
|
|
124
|
+
namespace: "typetest.dictionary",
|
|
65
125
|
},
|
|
66
126
|
"type/enum/extensible": {
|
|
67
127
|
"package-name": "typetest-enum-extensible",
|
|
128
|
+
namespace: "typetest.enum.extensible",
|
|
68
129
|
},
|
|
69
130
|
"type/enum/fixed": {
|
|
70
131
|
"package-name": "typetest-enum-fixed",
|
|
132
|
+
namespace: "typetest.enum.fixed",
|
|
71
133
|
},
|
|
72
134
|
"type/model/empty": {
|
|
73
135
|
"package-name": "typetest-model-empty",
|
|
136
|
+
namespace: "typetest.model.empty",
|
|
74
137
|
},
|
|
75
138
|
"type/model/inheritance/enum-discriminator": {
|
|
76
139
|
"package-name": "typetest-model-enumdiscriminator",
|
|
140
|
+
namespace: "typetest.model.enumdiscriminator",
|
|
77
141
|
},
|
|
78
142
|
"type/model/inheritance/nested-discriminator": {
|
|
79
143
|
"package-name": "typetest-model-nesteddiscriminator",
|
|
144
|
+
namespace: "typetest.model.nesteddiscriminator",
|
|
80
145
|
},
|
|
81
146
|
"type/model/inheritance/not-discriminated": {
|
|
82
147
|
"package-name": "typetest-model-notdiscriminated",
|
|
148
|
+
namespace: "typetest.model.notdiscriminated",
|
|
83
149
|
},
|
|
84
150
|
"type/model/inheritance/single-discriminator": {
|
|
85
151
|
"package-name": "typetest-model-singlediscriminator",
|
|
152
|
+
namespace: "typetest.model.singlediscriminator",
|
|
86
153
|
},
|
|
87
154
|
"type/model/inheritance/recursive": {
|
|
88
155
|
"package-name": "typetest-model-recursive",
|
|
156
|
+
namespace: "typetest.model.recursive",
|
|
89
157
|
"use-pyodide": "true",
|
|
90
158
|
},
|
|
91
159
|
"type/model/usage": {
|
|
92
160
|
"package-name": "typetest-model-usage",
|
|
161
|
+
namespace: "typetest.model.usage",
|
|
93
162
|
},
|
|
94
163
|
"type/model/visibility": [
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
164
|
+
{
|
|
165
|
+
"package-name": "typetest-model-visibility",
|
|
166
|
+
namespace: "typetest.model.visibility",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"package-name": "headasbooleantrue",
|
|
170
|
+
namespace: "headasbooleantrue",
|
|
171
|
+
"head-as-boolean": "true",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"package-name": "headasbooleanfalse",
|
|
175
|
+
namespace: "headasbooleanfalse",
|
|
176
|
+
"head-as-boolean": "false",
|
|
177
|
+
},
|
|
98
178
|
],
|
|
99
179
|
"type/property/nullable": {
|
|
100
180
|
"package-name": "typetest-property-nullable",
|
|
181
|
+
namespace: "typetest.property.nullable",
|
|
101
182
|
},
|
|
102
183
|
"type/property/optionality": {
|
|
103
184
|
"package-name": "typetest-property-optional",
|
|
185
|
+
namespace: "typetest.property.optional",
|
|
104
186
|
},
|
|
105
187
|
"type/property/additional-properties": {
|
|
106
188
|
"package-name": "typetest-property-additionalproperties",
|
|
189
|
+
namespace: "typetest.property.additionalproperties",
|
|
107
190
|
},
|
|
108
191
|
"type/scalar": {
|
|
109
192
|
"package-name": "typetest-scalar",
|
|
193
|
+
namespace: "typetest.scalar",
|
|
110
194
|
},
|
|
111
195
|
"type/property/value-types": {
|
|
112
196
|
"package-name": "typetest-property-valuetypes",
|
|
197
|
+
namespace: "typetest.property.valuetypes",
|
|
113
198
|
},
|
|
114
199
|
"type/union": {
|
|
115
200
|
"package-name": "typetest-union",
|
|
116
|
-
|
|
117
|
-
"azure/core/lro/rpc": {
|
|
118
|
-
"package-name": "azurecore-lro-rpc",
|
|
119
|
-
},
|
|
120
|
-
"client/structure/multi-client": {
|
|
121
|
-
"package-name": "client-structure-multiclient",
|
|
122
|
-
},
|
|
123
|
-
"client/structure/renamed-operation": {
|
|
124
|
-
"package-name": "client-structure-renamedoperation",
|
|
125
|
-
},
|
|
126
|
-
"client/structure/two-operation-group": {
|
|
127
|
-
"package-name": "client-structure-twooperationgroup",
|
|
128
|
-
},
|
|
129
|
-
"client/namespace": {
|
|
130
|
-
"enable-typespec-namespace": "true",
|
|
201
|
+
namespace: "typetest.union",
|
|
131
202
|
},
|
|
132
203
|
};
|
|
133
204
|
|
|
@@ -141,29 +212,9 @@ function getEmitterOption(spec: string, flavor: string): Record<string, string>[
|
|
|
141
212
|
const key = relativeSpec.includes("resiliency/srv-driven/old.tsp")
|
|
142
213
|
? relativeSpec
|
|
143
214
|
: dirname(relativeSpec);
|
|
144
|
-
const emitter_options = EMITTER_OPTIONS[key] ||
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
function updateOptions(options: Record<string, string>): void {
|
|
148
|
-
if (options["package-name"] && options["enable-typespec-namespace"] === undefined) {
|
|
149
|
-
options["enable-typespec-namespace"] = "false";
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// when package name is different with typespec namespace, disable typespec namespace
|
|
154
|
-
if (flavor !== "azure") {
|
|
155
|
-
for (const options of result) {
|
|
156
|
-
if (Array.isArray(options)) {
|
|
157
|
-
for (const option of options) {
|
|
158
|
-
updateOptions(option);
|
|
159
|
-
}
|
|
160
|
-
} else {
|
|
161
|
-
updateOptions(options);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return result;
|
|
215
|
+
const emitter_options = EMITTER_OPTIONS[key] ||
|
|
216
|
+
(flavor === "azure" ? AZURE_EMITTER_OPTIONS[key] : [{}]) || [{}];
|
|
217
|
+
return Array.isArray(emitter_options) ? emitter_options : [emitter_options];
|
|
167
218
|
}
|
|
168
219
|
|
|
169
220
|
// Function to execute CLI commands asynchronously
|
|
Binary file
|
|
@@ -40,7 +40,6 @@ class OptionsRetriever:
|
|
|
40
40
|
"generate-test": False,
|
|
41
41
|
"from-typespec": False,
|
|
42
42
|
"emit-cross-language-definition-file": False,
|
|
43
|
-
"enable-typespec-namespace": False,
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
@property
|
|
@@ -317,7 +316,6 @@ class CodeGenerator(Plugin):
|
|
|
317
316
|
"flavor",
|
|
318
317
|
"company_name",
|
|
319
318
|
"emit_cross_language_definition_file",
|
|
320
|
-
"enable_typespec_namespace",
|
|
321
319
|
]
|
|
322
320
|
return {f: getattr(self.options_retriever, f) for f in flags}
|
|
323
321
|
|
|
@@ -145,12 +145,8 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
145
145
|
return result
|
|
146
146
|
return f"{result}{module_name}" if result.endswith(".") else f"{result}.{module_name}"
|
|
147
147
|
|
|
148
|
-
@property
|
|
149
|
-
def need_unique_model_alias(self) -> bool:
|
|
150
|
-
return self.has_subnamespace and self.options["enable_typespec_namespace"]
|
|
151
|
-
|
|
152
148
|
def get_unique_models_alias(self, serialize_namespace: str, imported_namespace: str) -> str:
|
|
153
|
-
if not self.
|
|
149
|
+
if not self.has_subnamespace:
|
|
154
150
|
return "_models"
|
|
155
151
|
relative_path = self.get_relative_import_path(
|
|
156
152
|
serialize_namespace, self.get_imported_namespace_for_model(imported_namespace)
|
|
@@ -406,3 +402,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
406
402
|
@staticmethod
|
|
407
403
|
def has_non_json_models(models: List[ModelType]) -> bool:
|
|
408
404
|
return any(m for m in models if m.base != "json")
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def is_tsp(self) -> bool:
|
|
408
|
+
return self.options.get("tsp_file") is not None
|
|
@@ -197,6 +197,8 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
197
197
|
env = Environment(
|
|
198
198
|
loader=PackageLoader("pygen.codegen", "templates/packaging_templates"),
|
|
199
199
|
undefined=StrictUndefined,
|
|
200
|
+
trim_blocks=True,
|
|
201
|
+
lstrip_blocks=True,
|
|
200
202
|
)
|
|
201
203
|
|
|
202
204
|
package_files = _PACKAGE_FILES
|
|
@@ -460,21 +462,11 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
460
462
|
metadata_serializer = MetadataSerializer(self.code_model, env, client_namespace=namespace)
|
|
461
463
|
self.write_file(self.exec_path(namespace) / Path("_metadata.json"), metadata_serializer.serialize())
|
|
462
464
|
|
|
463
|
-
@property
|
|
464
|
-
def _namespace_from_package_name(self) -> str:
|
|
465
|
-
return get_namespace_from_package_name(self.code_model.options["package_name"])
|
|
466
|
-
|
|
467
|
-
def _name_space(self) -> str:
|
|
468
|
-
if self.code_model.namespace.count(".") >= self._namespace_from_package_name.count("."):
|
|
469
|
-
return self.code_model.namespace
|
|
470
|
-
|
|
471
|
-
return self._namespace_from_package_name
|
|
472
|
-
|
|
473
465
|
@property
|
|
474
466
|
def exec_path_compensation(self) -> Path:
|
|
475
467
|
"""Assume the process is running in the root folder of the package. If not, we need the path compensation."""
|
|
476
468
|
return (
|
|
477
|
-
Path("../" * (self.
|
|
469
|
+
Path("../" * (self.code_model.namespace.count(".") + 1))
|
|
478
470
|
if self.code_model.options["no_namespace_folders"]
|
|
479
471
|
else Path(".")
|
|
480
472
|
)
|
|
@@ -482,16 +474,28 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
482
474
|
def exec_path_for_test_sample(self, namespace: str) -> Path:
|
|
483
475
|
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
484
476
|
|
|
477
|
+
# pylint: disable=line-too-long
|
|
485
478
|
def exec_path(self, namespace: str) -> Path:
|
|
486
479
|
if self.code_model.options["no_namespace_folders"] and not self.code_model.options["multiapi"]:
|
|
480
|
+
# when output folder contains parts different from the namespace, we fall back to current folder directly.
|
|
481
|
+
# (e.g. https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/communication/azure-communication-callautomation/swagger/SWAGGER.md)
|
|
487
482
|
return Path(".")
|
|
488
483
|
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
489
484
|
|
|
485
|
+
# pylint: disable=line-too-long
|
|
490
486
|
@property
|
|
491
|
-
def
|
|
487
|
+
def sample_additional_folder(self) -> Path:
|
|
488
|
+
# For special package, we need to additional folder when generate samples.
|
|
489
|
+
# For example, azure-mgmt-resource is combined by multiple modules, and each module is multiapi package.
|
|
490
|
+
# one of namespace is "azure.mgmt.resource.resources.v2020_01_01", then additional folder is "resources"
|
|
491
|
+
# so that we could avoid conflict when generate samples.
|
|
492
|
+
# python config: https://github.com/Azure/azure-rest-api-specs/blob/main/specification/resources/resource-manager/readme.python.md
|
|
493
|
+
# generated SDK: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/resources/azure-mgmt-resource/generated_samples
|
|
492
494
|
namespace_config = get_namespace_config(self.code_model.namespace, self.code_model.options["multiapi"])
|
|
493
495
|
num_of_namespace = namespace_config.count(".") + 1
|
|
494
|
-
num_of_package_namespace =
|
|
496
|
+
num_of_package_namespace = (
|
|
497
|
+
get_namespace_from_package_name(self.code_model.options["package_name"]).count(".") + 1
|
|
498
|
+
)
|
|
495
499
|
if num_of_namespace > num_of_package_namespace:
|
|
496
500
|
return Path("/".join(namespace_config.split(".")[num_of_package_namespace:]))
|
|
497
501
|
return Path("")
|
|
@@ -514,7 +518,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
514
518
|
file_name = to_snake_case(extract_sample_name(file)) + ".py"
|
|
515
519
|
try:
|
|
516
520
|
self.write_file(
|
|
517
|
-
out_path / self.
|
|
521
|
+
out_path / self.sample_additional_folder / _sample_output_path(file) / file_name,
|
|
518
522
|
SampleSerializer(
|
|
519
523
|
code_model=self.code_model,
|
|
520
524
|
env=env,
|
|
@@ -28,7 +28,11 @@ class GeneralSerializer(BaseSerializer):
|
|
|
28
28
|
|
|
29
29
|
def serialize_package_file(self, template_name: str, **kwargs: Any) -> str:
|
|
30
30
|
template = self.env.get_template(template_name)
|
|
31
|
-
package_parts = (
|
|
31
|
+
package_parts = (
|
|
32
|
+
self.code_model.namespace.split(".")[:-1]
|
|
33
|
+
if self.code_model.is_tsp
|
|
34
|
+
else (self.code_model.options["package_name"] or "").split("-")[:-1]
|
|
35
|
+
)
|
|
32
36
|
token_credential = any(
|
|
33
37
|
c for c in self.code_model.clients if isinstance(getattr(c.credential, "type", None), TokenCredentialType)
|
|
34
38
|
)
|
|
@@ -44,7 +48,6 @@ class GeneralSerializer(BaseSerializer):
|
|
|
44
48
|
"pkgutil_names": [".".join(package_parts[: i + 1]) for i in range(len(package_parts))],
|
|
45
49
|
"init_names": ["/".join(package_parts[: i + 1]) + "/__init__.py" for i in range(len(package_parts))],
|
|
46
50
|
"client_name": self.code_model.clients[0].name,
|
|
47
|
-
"namespace": self.code_model.namespace,
|
|
48
51
|
}
|
|
49
52
|
params.update(self.code_model.options)
|
|
50
53
|
params.update(kwargs)
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
include *.md
|
|
2
2
|
include LICENSE
|
|
3
|
+
{% if code_model.is_tsp %}
|
|
4
|
+
include {{ code_model.namespace.replace('.', '/') }}/py.typed
|
|
5
|
+
{% else %}
|
|
3
6
|
include {{ package_name.replace('-', '/') }}/py.typed
|
|
7
|
+
{% endif %}
|
|
4
8
|
recursive-include tests *.py
|
|
5
9
|
recursive-include samples *.py *.md
|
|
6
|
-
{
|
|
10
|
+
{% for init_name in init_names %}
|
|
7
11
|
include {{ init_name }}
|
|
8
|
-
{
|
|
12
|
+
{% endfor %}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% if code_model.is_azure_flavor %}
|
|
2
|
-
{% if package_mode == "mgmtplane"
|
|
2
|
+
{% if package_mode == "mgmtplane" %}
|
|
3
3
|
# Microsoft Azure SDK for Python
|
|
4
4
|
|
|
5
5
|
This is the Microsoft {{package_pprint_name}} Client Library.
|
|
@@ -40,7 +40,7 @@ python -m pip install {{ package_name }}
|
|
|
40
40
|
- You need an [Azure subscription][azure_sub] to use this package.
|
|
41
41
|
- An existing {{ package_pprint_name }} instance.
|
|
42
42
|
|
|
43
|
-
{
|
|
43
|
+
{% if token_credential %}
|
|
44
44
|
#### Create with an Azure Active Directory Credential
|
|
45
45
|
To use an [Azure Active Directory (AAD) token credential][authenticate_with_token],
|
|
46
46
|
provide an instance of the desired credential type obtained from the
|
|
@@ -57,7 +57,7 @@ Set the values of the client ID, tenant ID, and client secret of the AAD applica
|
|
|
57
57
|
Use the returned token credential to authenticate the client:
|
|
58
58
|
|
|
59
59
|
```python
|
|
60
|
-
>>> from {{ namespace }} import {{ client_name }}
|
|
60
|
+
>>> from {{ code_model.namespace }} import {{ client_name }}
|
|
61
61
|
>>> from azure.identity import DefaultAzureCredential
|
|
62
62
|
>>> client = {{ client_name }}(endpoint='<endpoint>', credential=DefaultAzureCredential())
|
|
63
63
|
```
|
|
@@ -65,7 +65,7 @@ Use the returned token credential to authenticate the client:
|
|
|
65
65
|
## Examples
|
|
66
66
|
|
|
67
67
|
```python
|
|
68
|
-
>>> from {{ namespace }} import {{ client_name }}
|
|
68
|
+
>>> from {{ code_model.namespace }} import {{ client_name }}
|
|
69
69
|
>>> from azure.identity import DefaultAzureCredential
|
|
70
70
|
>>> from {{ code_model.core_library }}.exceptions import HttpResponseError
|
|
71
71
|
|
|
@@ -76,7 +76,7 @@ Use the returned token credential to authenticate the client:
|
|
|
76
76
|
print('service responds error: {}'.format(e.response.json()))
|
|
77
77
|
|
|
78
78
|
```
|
|
79
|
-
{
|
|
79
|
+
{% endif %}
|
|
80
80
|
|
|
81
81
|
## Contributing
|
|
82
82
|
|
package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
-e ../../../tools/azure-sdk-tools
|
|
2
2
|
../../core/azure-core
|
|
3
|
-
{% if token_credential
|
|
3
|
+
{% if token_credential %}
|
|
4
4
|
../../identity/azure-identity
|
|
5
5
|
{% endif -%}
|
|
6
|
-
{% if azure_arm
|
|
6
|
+
{% if azure_arm %}
|
|
7
7
|
../../core/azure-mgmt-core
|
|
8
|
-
{% endif
|
|
8
|
+
{% endif %}
|
|
9
9
|
aiohttp
|
|
@@ -2,19 +2,27 @@
|
|
|
2
2
|
{{ license_header }}
|
|
3
3
|
# coding: utf-8
|
|
4
4
|
{% if package_mode %}
|
|
5
|
+
|
|
5
6
|
import os
|
|
6
7
|
import re
|
|
7
|
-
{% endif
|
|
8
|
+
{% endif %}
|
|
8
9
|
from setuptools import setup, find_packages
|
|
9
10
|
|
|
10
11
|
{% set package_name = package_name or code_model.clients[0].name %}
|
|
11
12
|
|
|
12
13
|
PACKAGE_NAME = "{{ package_name|lower }}"
|
|
13
|
-
{% if package_mode
|
|
14
|
+
{% if package_mode %}
|
|
14
15
|
PACKAGE_PPRINT_NAME = "{{ package_pprint_name }}"
|
|
16
|
+
{% if code_model.is_tsp %}
|
|
17
|
+
PACKAGE_NAMESPACE = "{{ code_model.namespace|lower }}"
|
|
18
|
+
|
|
19
|
+
# a.b.c => a/b/c
|
|
20
|
+
package_folder_path = PACKAGE_NAMESPACE.replace(".", "/")
|
|
21
|
+
{% else %}
|
|
15
22
|
|
|
16
23
|
# a-b-c => a/b/c
|
|
17
24
|
package_folder_path = PACKAGE_NAME.replace("-", "/")
|
|
25
|
+
{% endif %}
|
|
18
26
|
|
|
19
27
|
# Version extraction inspired from 'requests'
|
|
20
28
|
with open(os.path.join(package_folder_path, "_version.py"), "r") as fd:
|
|
@@ -33,7 +41,8 @@ version = "{{ package_version }}"
|
|
|
33
41
|
{% set long_description = code_model.description %}
|
|
34
42
|
{% set author_email = "" %}
|
|
35
43
|
{% set url = "" %}
|
|
36
|
-
{% endif
|
|
44
|
+
{% endif %}
|
|
45
|
+
|
|
37
46
|
|
|
38
47
|
setup(
|
|
39
48
|
name=PACKAGE_NAME,
|
|
@@ -70,9 +79,9 @@ setup(
|
|
|
70
79
|
{% if pkgutil_names %}
|
|
71
80
|
# Exclude packages that will be covered by PEP420 or nspkg
|
|
72
81
|
{% endif %}
|
|
73
|
-
{
|
|
82
|
+
{% for pkgutil_name in pkgutil_names %}
|
|
74
83
|
"{{ pkgutil_name }}",
|
|
75
|
-
{
|
|
84
|
+
{% endfor %}
|
|
76
85
|
]
|
|
77
86
|
),
|
|
78
87
|
include_package_data=True,
|
|
Binary file
|
|
@@ -40,7 +40,6 @@ class OptionsRetriever:
|
|
|
40
40
|
"generate-test": False,
|
|
41
41
|
"from-typespec": False,
|
|
42
42
|
"emit-cross-language-definition-file": False,
|
|
43
|
-
"enable-typespec-namespace": False,
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
@property
|
|
@@ -317,7 +316,6 @@ class CodeGenerator(Plugin):
|
|
|
317
316
|
"flavor",
|
|
318
317
|
"company_name",
|
|
319
318
|
"emit_cross_language_definition_file",
|
|
320
|
-
"enable_typespec_namespace",
|
|
321
319
|
]
|
|
322
320
|
return {f: getattr(self.options_retriever, f) for f in flags}
|
|
323
321
|
|
|
@@ -145,12 +145,8 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
145
145
|
return result
|
|
146
146
|
return f"{result}{module_name}" if result.endswith(".") else f"{result}.{module_name}"
|
|
147
147
|
|
|
148
|
-
@property
|
|
149
|
-
def need_unique_model_alias(self) -> bool:
|
|
150
|
-
return self.has_subnamespace and self.options["enable_typespec_namespace"]
|
|
151
|
-
|
|
152
148
|
def get_unique_models_alias(self, serialize_namespace: str, imported_namespace: str) -> str:
|
|
153
|
-
if not self.
|
|
149
|
+
if not self.has_subnamespace:
|
|
154
150
|
return "_models"
|
|
155
151
|
relative_path = self.get_relative_import_path(
|
|
156
152
|
serialize_namespace, self.get_imported_namespace_for_model(imported_namespace)
|
|
@@ -406,3 +402,7 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
|
|
|
406
402
|
@staticmethod
|
|
407
403
|
def has_non_json_models(models: List[ModelType]) -> bool:
|
|
408
404
|
return any(m for m in models if m.base != "json")
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def is_tsp(self) -> bool:
|
|
408
|
+
return self.options.get("tsp_file") is not None
|
|
@@ -197,6 +197,8 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
197
197
|
env = Environment(
|
|
198
198
|
loader=PackageLoader("pygen.codegen", "templates/packaging_templates"),
|
|
199
199
|
undefined=StrictUndefined,
|
|
200
|
+
trim_blocks=True,
|
|
201
|
+
lstrip_blocks=True,
|
|
200
202
|
)
|
|
201
203
|
|
|
202
204
|
package_files = _PACKAGE_FILES
|
|
@@ -460,21 +462,11 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
460
462
|
metadata_serializer = MetadataSerializer(self.code_model, env, client_namespace=namespace)
|
|
461
463
|
self.write_file(self.exec_path(namespace) / Path("_metadata.json"), metadata_serializer.serialize())
|
|
462
464
|
|
|
463
|
-
@property
|
|
464
|
-
def _namespace_from_package_name(self) -> str:
|
|
465
|
-
return get_namespace_from_package_name(self.code_model.options["package_name"])
|
|
466
|
-
|
|
467
|
-
def _name_space(self) -> str:
|
|
468
|
-
if self.code_model.namespace.count(".") >= self._namespace_from_package_name.count("."):
|
|
469
|
-
return self.code_model.namespace
|
|
470
|
-
|
|
471
|
-
return self._namespace_from_package_name
|
|
472
|
-
|
|
473
465
|
@property
|
|
474
466
|
def exec_path_compensation(self) -> Path:
|
|
475
467
|
"""Assume the process is running in the root folder of the package. If not, we need the path compensation."""
|
|
476
468
|
return (
|
|
477
|
-
Path("../" * (self.
|
|
469
|
+
Path("../" * (self.code_model.namespace.count(".") + 1))
|
|
478
470
|
if self.code_model.options["no_namespace_folders"]
|
|
479
471
|
else Path(".")
|
|
480
472
|
)
|
|
@@ -482,16 +474,28 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
482
474
|
def exec_path_for_test_sample(self, namespace: str) -> Path:
|
|
483
475
|
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
484
476
|
|
|
477
|
+
# pylint: disable=line-too-long
|
|
485
478
|
def exec_path(self, namespace: str) -> Path:
|
|
486
479
|
if self.code_model.options["no_namespace_folders"] and not self.code_model.options["multiapi"]:
|
|
480
|
+
# when output folder contains parts different from the namespace, we fall back to current folder directly.
|
|
481
|
+
# (e.g. https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/communication/azure-communication-callautomation/swagger/SWAGGER.md)
|
|
487
482
|
return Path(".")
|
|
488
483
|
return self.exec_path_compensation / Path(*namespace.split("."))
|
|
489
484
|
|
|
485
|
+
# pylint: disable=line-too-long
|
|
490
486
|
@property
|
|
491
|
-
def
|
|
487
|
+
def sample_additional_folder(self) -> Path:
|
|
488
|
+
# For special package, we need to additional folder when generate samples.
|
|
489
|
+
# For example, azure-mgmt-resource is combined by multiple modules, and each module is multiapi package.
|
|
490
|
+
# one of namespace is "azure.mgmt.resource.resources.v2020_01_01", then additional folder is "resources"
|
|
491
|
+
# so that we could avoid conflict when generate samples.
|
|
492
|
+
# python config: https://github.com/Azure/azure-rest-api-specs/blob/main/specification/resources/resource-manager/readme.python.md
|
|
493
|
+
# generated SDK: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/resources/azure-mgmt-resource/generated_samples
|
|
492
494
|
namespace_config = get_namespace_config(self.code_model.namespace, self.code_model.options["multiapi"])
|
|
493
495
|
num_of_namespace = namespace_config.count(".") + 1
|
|
494
|
-
num_of_package_namespace =
|
|
496
|
+
num_of_package_namespace = (
|
|
497
|
+
get_namespace_from_package_name(self.code_model.options["package_name"]).count(".") + 1
|
|
498
|
+
)
|
|
495
499
|
if num_of_namespace > num_of_package_namespace:
|
|
496
500
|
return Path("/".join(namespace_config.split(".")[num_of_package_namespace:]))
|
|
497
501
|
return Path("")
|
|
@@ -514,7 +518,7 @@ class JinjaSerializer(ReaderAndWriter):
|
|
|
514
518
|
file_name = to_snake_case(extract_sample_name(file)) + ".py"
|
|
515
519
|
try:
|
|
516
520
|
self.write_file(
|
|
517
|
-
out_path / self.
|
|
521
|
+
out_path / self.sample_additional_folder / _sample_output_path(file) / file_name,
|
|
518
522
|
SampleSerializer(
|
|
519
523
|
code_model=self.code_model,
|
|
520
524
|
env=env,
|
|
@@ -28,7 +28,11 @@ class GeneralSerializer(BaseSerializer):
|
|
|
28
28
|
|
|
29
29
|
def serialize_package_file(self, template_name: str, **kwargs: Any) -> str:
|
|
30
30
|
template = self.env.get_template(template_name)
|
|
31
|
-
package_parts = (
|
|
31
|
+
package_parts = (
|
|
32
|
+
self.code_model.namespace.split(".")[:-1]
|
|
33
|
+
if self.code_model.is_tsp
|
|
34
|
+
else (self.code_model.options["package_name"] or "").split("-")[:-1]
|
|
35
|
+
)
|
|
32
36
|
token_credential = any(
|
|
33
37
|
c for c in self.code_model.clients if isinstance(getattr(c.credential, "type", None), TokenCredentialType)
|
|
34
38
|
)
|
|
@@ -44,7 +48,6 @@ class GeneralSerializer(BaseSerializer):
|
|
|
44
48
|
"pkgutil_names": [".".join(package_parts[: i + 1]) for i in range(len(package_parts))],
|
|
45
49
|
"init_names": ["/".join(package_parts[: i + 1]) + "/__init__.py" for i in range(len(package_parts))],
|
|
46
50
|
"client_name": self.code_model.clients[0].name,
|
|
47
|
-
"namespace": self.code_model.namespace,
|
|
48
51
|
}
|
|
49
52
|
params.update(self.code_model.options)
|
|
50
53
|
params.update(kwargs)
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
include *.md
|
|
2
2
|
include LICENSE
|
|
3
|
+
{% if code_model.is_tsp %}
|
|
4
|
+
include {{ code_model.namespace.replace('.', '/') }}/py.typed
|
|
5
|
+
{% else %}
|
|
3
6
|
include {{ package_name.replace('-', '/') }}/py.typed
|
|
7
|
+
{% endif %}
|
|
4
8
|
recursive-include tests *.py
|
|
5
9
|
recursive-include samples *.py *.md
|
|
6
|
-
{
|
|
10
|
+
{% for init_name in init_names %}
|
|
7
11
|
include {{ init_name }}
|
|
8
|
-
{
|
|
12
|
+
{% endfor %}
|