@typespec/http-client-python 0.8.1 → 0.8.3-dev.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.
Files changed (114) hide show
  1. package/README.md +86 -84
  2. package/dist/emitter/code-model.d.ts +1 -2
  3. package/dist/emitter/code-model.d.ts.map +1 -1
  4. package/dist/emitter/code-model.js +5 -2
  5. package/dist/emitter/code-model.js.map +1 -1
  6. package/dist/emitter/emitter.d.ts +0 -2
  7. package/dist/emitter/emitter.d.ts.map +1 -1
  8. package/dist/emitter/emitter.js +21 -32
  9. package/dist/emitter/emitter.js.map +1 -1
  10. package/dist/emitter/http.d.ts +4 -4
  11. package/dist/emitter/http.d.ts.map +1 -1
  12. package/dist/emitter/http.js.map +1 -1
  13. package/dist/emitter/index.d.ts +1 -1
  14. package/dist/emitter/index.d.ts.map +1 -1
  15. package/dist/emitter/index.js +1 -1
  16. package/dist/emitter/index.js.map +1 -1
  17. package/dist/emitter/lib.d.ts +65 -22
  18. package/dist/emitter/lib.d.ts.map +1 -1
  19. package/dist/emitter/lib.js +51 -26
  20. package/dist/emitter/lib.js.map +1 -1
  21. package/dist/emitter/types.d.ts +3 -3
  22. package/dist/emitter/types.d.ts.map +1 -1
  23. package/dist/emitter/types.js.map +1 -1
  24. package/dist/emitter/utils.d.ts +5 -4
  25. package/dist/emitter/utils.d.ts.map +1 -1
  26. package/dist/emitter/utils.js +31 -16
  27. package/dist/emitter/utils.js.map +1 -1
  28. package/emitter/src/code-model.ts +16 -25
  29. package/emitter/src/emitter.ts +35 -51
  30. package/emitter/src/http.ts +18 -21
  31. package/emitter/src/index.ts +1 -1
  32. package/emitter/src/lib.ts +62 -41
  33. package/emitter/src/types.ts +13 -23
  34. package/emitter/src/utils.ts +36 -25
  35. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  36. package/eng/scripts/Generate.ps1 +3 -0
  37. package/eng/scripts/ci/pylintrc +1 -1
  38. package/eng/scripts/ci/regenerate.ts +92 -44
  39. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  40. package/generator/build/lib/pygen/codegen/__init__.py +7 -23
  41. package/generator/build/lib/pygen/codegen/_utils.py +26 -2
  42. package/generator/build/lib/pygen/codegen/models/code_model.py +38 -5
  43. package/generator/build/lib/pygen/codegen/serializers/__init__.py +21 -15
  44. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +5 -2
  45. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +1 -1
  46. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +3 -1
  47. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +3 -1
  48. package/generator/build/lib/pygen/codegen/templates/conftest.py.jinja2 +3 -1
  49. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +3 -1
  50. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +3 -1
  51. package/generator/build/lib/pygen/codegen/templates/model_base.py.jinja2 +3 -5
  52. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +3 -1
  53. package/generator/build/lib/pygen/codegen/templates/model_init.py.jinja2 +3 -1
  54. package/generator/build/lib/pygen/codegen/templates/operation_groups_container.py.jinja2 +3 -1
  55. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +3 -1
  56. package/generator/build/lib/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +1 -21
  57. package/generator/build/lib/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +6 -2
  58. package/generator/build/lib/pygen/codegen/templates/packaging_templates/README.md.jinja2 +5 -5
  59. package/generator/build/lib/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +3 -3
  60. package/generator/build/lib/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +20 -9
  61. package/generator/build/lib/pygen/codegen/templates/patch.py.jinja2 +9 -4
  62. package/generator/build/lib/pygen/codegen/templates/request_builders.py.jinja2 +3 -1
  63. package/generator/build/lib/pygen/codegen/templates/rest_init.py.jinja2 +3 -1
  64. package/generator/build/lib/pygen/codegen/templates/sample.py.jinja2 +3 -1
  65. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +4 -25
  66. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +3 -1
  67. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +3 -1
  68. package/generator/build/lib/pygen/codegen/templates/types.py.jinja2 +3 -1
  69. package/generator/build/lib/pygen/codegen/templates/validation.py.jinja2 +3 -1
  70. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +3 -1
  71. package/generator/build/lib/pygen/codegen/templates/version.py.jinja2 +3 -1
  72. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  73. package/generator/pygen/codegen/__init__.py +7 -23
  74. package/generator/pygen/codegen/_utils.py +26 -2
  75. package/generator/pygen/codegen/models/code_model.py +38 -5
  76. package/generator/pygen/codegen/serializers/__init__.py +21 -15
  77. package/generator/pygen/codegen/serializers/general_serializer.py +5 -2
  78. package/generator/pygen/codegen/serializers/test_serializer.py +1 -1
  79. package/generator/pygen/codegen/templates/client_container.py.jinja2 +3 -1
  80. package/generator/pygen/codegen/templates/config_container.py.jinja2 +3 -1
  81. package/generator/pygen/codegen/templates/conftest.py.jinja2 +3 -1
  82. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +3 -1
  83. package/generator/pygen/codegen/templates/init.py.jinja2 +3 -1
  84. package/generator/pygen/codegen/templates/model_base.py.jinja2 +3 -5
  85. package/generator/pygen/codegen/templates/model_container.py.jinja2 +3 -1
  86. package/generator/pygen/codegen/templates/model_init.py.jinja2 +3 -1
  87. package/generator/pygen/codegen/templates/operation_groups_container.py.jinja2 +3 -1
  88. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +3 -1
  89. package/generator/pygen/codegen/templates/packaging_templates/LICENSE.jinja2 +1 -21
  90. package/generator/pygen/codegen/templates/packaging_templates/MANIFEST.in.jinja2 +6 -2
  91. package/generator/pygen/codegen/templates/packaging_templates/README.md.jinja2 +5 -5
  92. package/generator/pygen/codegen/templates/packaging_templates/dev_requirements.txt.jinja2 +3 -3
  93. package/generator/pygen/codegen/templates/packaging_templates/setup.py.jinja2 +20 -9
  94. package/generator/pygen/codegen/templates/patch.py.jinja2 +9 -4
  95. package/generator/pygen/codegen/templates/request_builders.py.jinja2 +3 -1
  96. package/generator/pygen/codegen/templates/rest_init.py.jinja2 +3 -1
  97. package/generator/pygen/codegen/templates/sample.py.jinja2 +3 -1
  98. package/generator/pygen/codegen/templates/serialization.py.jinja2 +4 -25
  99. package/generator/pygen/codegen/templates/test.py.jinja2 +3 -1
  100. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +3 -1
  101. package/generator/pygen/codegen/templates/types.py.jinja2 +3 -1
  102. package/generator/pygen/codegen/templates/validation.py.jinja2 +3 -1
  103. package/generator/pygen/codegen/templates/vendor.py.jinja2 +3 -1
  104. package/generator/pygen/codegen/templates/version.py.jinja2 +3 -1
  105. package/generator/pygen.egg-info/PKG-INFO +2 -2
  106. package/generator/pygen.egg-info/requires.txt +2 -2
  107. package/generator/setup.py +2 -2
  108. package/generator/test/azure/mock_api_tests/asynctests/test_azure_core_lro_rpc_async.py +2 -2
  109. package/generator/test/azure/mock_api_tests/test_azure_core_lro_rpc.py +1 -1
  110. package/generator/test/azure/requirements.txt +2 -1
  111. package/generator/test/generic_mock_api_tests/asynctests/test_streaming_jsonl_async.py +27 -0
  112. package/generator/test/generic_mock_api_tests/test_streaming_jsonl.py +25 -0
  113. package/generator/test/unbranded/requirements.txt +1 -0
  114. package/package.json +13 -6
@@ -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
- { "package-name": "typetest-model-visibility" },
96
- { "package-name": "headasbooleantrue", "head-as-boolean": "true" },
97
- { "package-name": "headasbooleanfalse", "head-as-boolean": "false" },
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
- const result = Array.isArray(emitter_options) ? emitter_options : [emitter_options];
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
@@ -293,9 +344,6 @@ function addOptions(
293
344
  if (flags.debug) {
294
345
  options["debug"] = "true";
295
346
  }
296
- if (flags.flavor === "unbranded") {
297
- options["company-name"] = "Unbranded";
298
- }
299
347
  options["examples-dir"] = toPosix(join(dirname(spec), "examples"));
300
348
  const configs = Object.entries(options).flatMap(([k, v]) => {
301
349
  return `--option ${argv.values.emitterName || "@typespec/http-client-python"}.${k}=${typeof v === "string" && v.indexOf(" ") > -1 ? `"${v}"` : v}`;
@@ -13,7 +13,7 @@ from .. import Plugin
13
13
  from ..utils import parse_args
14
14
  from .models.code_model import CodeModel
15
15
  from .serializers import JinjaSerializer
16
- from ._utils import DEFAULT_HEADER_TEXT, VALID_PACKAGE_MODE, TYPESPEC_PACKAGE_MODE
16
+ from ._utils import VALID_PACKAGE_MODE, TYPESPEC_PACKAGE_MODE
17
17
 
18
18
 
19
19
  def _default_pprint(package_name: str) -> str:
@@ -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
@@ -54,24 +53,6 @@ class OptionsRetriever:
54
53
  key = prop.replace("_", "-")
55
54
  return self.options.get(key, self.OPTIONS_TO_DEFAULT.get(key))
56
55
 
57
- @property
58
- def company_name(self) -> str:
59
- return self.options.get("company-name", "Microsoft" if self.is_azure_flavor else "")
60
-
61
- @property
62
- def license_header(self) -> str:
63
- license_header = self.options.get(
64
- "header-text",
65
- (DEFAULT_HEADER_TEXT.format(company_name=self.company_name) if self.company_name else ""),
66
- )
67
- if license_header:
68
- license_header = license_header.replace("\n", "\n# ")
69
- license_header = (
70
- "# --------------------------------------------------------------------------\n# " + license_header
71
- )
72
- license_header += "\n# --------------------------------------------------------------------------"
73
- return license_header
74
-
75
56
  @property
76
57
  def show_operations(self) -> bool:
77
58
  return self.options.get("show-operations", not self.low_level_client)
@@ -169,6 +150,11 @@ class OptionsRetriever:
169
150
  def package_version(self) -> Optional[str]:
170
151
  return str(self.options.get("package-version", ""))
171
152
 
153
+
154
+ @property
155
+ def header_text(self) -> Optional[str]:
156
+ return self.options.get("header-text")
157
+
172
158
 
173
159
  class CodeGenerator(Plugin):
174
160
  def __init__(self, *args, **kwargs: Any) -> None:
@@ -287,7 +273,7 @@ class CodeGenerator(Plugin):
287
273
  flags = [
288
274
  "azure_arm",
289
275
  "head_as_boolean",
290
- "license_header",
276
+ "header_text",
291
277
  "keep_version_file",
292
278
  "no_async",
293
279
  "no_namespace_folders",
@@ -315,9 +301,7 @@ class CodeGenerator(Plugin):
315
301
  "default_api_version",
316
302
  "from_typespec",
317
303
  "flavor",
318
- "company_name",
319
304
  "emit_cross_language_definition_file",
320
- "enable_typespec_namespace",
321
305
  ]
322
306
  return {f: getattr(self.options_retriever, f) for f in flags}
323
307
 
@@ -5,12 +5,36 @@
5
5
  # --------------------------------------------------------------------------
6
6
 
7
7
  DEFAULT_HEADER_TEXT = (
8
- "Copyright (c) {company_name} Corporation. All rights reserved.\n"
8
+ "Copyright (c) Microsoft Corporation. All rights reserved.\n"
9
9
  "Licensed under the MIT License. See License.txt in the project root for license information.\n"
10
- "Code generated by {company_name} (R) Python Code Generator.\n"
10
+ "Code generated by Microsoft (R) Python Code Generator.\n"
11
11
  "Changes may cause incorrect behavior and will be lost if the code is regenerated."
12
12
  )
13
13
 
14
+ DEFAULT_LICENSE_DESCRIPTION = (
15
+ "Copyright (c) Microsoft Corporation.\n"
16
+ "\n"
17
+ "MIT License\n"
18
+ "\n"
19
+ "Permission is hereby granted, free of charge, to any person obtaining a copy\n"
20
+ "of this software and associated documentation files (the \"Software\"), to deal\n"
21
+ "in the Software without restriction, including without limitation the rights\n"
22
+ "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n"
23
+ "copies of the Software, and to permit persons to whom the Software is\n"
24
+ "furnished to do so, subject to the following conditions:\n"
25
+ "\n"
26
+ "The above copyright notice and this permission notice shall be included in all\n"
27
+ "copies or substantial portions of the Software.\n"
28
+ "\n"
29
+ "THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
30
+ "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
31
+ "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
32
+ "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
33
+ "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
34
+ "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
35
+ "SOFTWARE."
36
+ )
37
+
14
38
  SWAGGER_PACKAGE_MODE = ["mgmtplane", "dataplane"] # for backward compatibility
15
39
  TYPESPEC_PACKAGE_MODE = ["azure-mgmt", "azure-dataplane", "generic"]
16
40
  VALID_PACKAGE_MODE = SWAGGER_PACKAGE_MODE + TYPESPEC_PACKAGE_MODE
@@ -13,6 +13,7 @@ from .client import Client
13
13
  from .request_builder import RequestBuilder, OverloadedRequestBuilder
14
14
  from .operation_group import OperationGroup
15
15
  from .utils import NamespaceType
16
+ from .._utils import DEFAULT_HEADER_TEXT, DEFAULT_LICENSE_DESCRIPTION
16
17
 
17
18
 
18
19
  def _is_legacy(options) -> bool:
@@ -145,12 +146,8 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
145
146
  return result
146
147
  return f"{result}{module_name}" if result.endswith(".") else f"{result}.{module_name}"
147
148
 
148
- @property
149
- def need_unique_model_alias(self) -> bool:
150
- return self.has_subnamespace and self.options["enable_typespec_namespace"]
151
-
152
149
  def get_unique_models_alias(self, serialize_namespace: str, imported_namespace: str) -> str:
153
- if not self.need_unique_model_alias:
150
+ if not self.has_subnamespace:
154
151
  return "_models"
155
152
  relative_path = self.get_relative_import_path(
156
153
  serialize_namespace, self.get_imported_namespace_for_model(imported_namespace)
@@ -406,3 +403,39 @@ class CodeModel: # pylint: disable=too-many-public-methods, disable=too-many-in
406
403
  @staticmethod
407
404
  def has_non_json_models(models: List[ModelType]) -> bool:
408
405
  return any(m for m in models if m.base != "json")
406
+
407
+ @property
408
+ def is_tsp(self) -> bool:
409
+ return self.options.get("tsp_file") is not None
410
+
411
+ @property
412
+ def license_header(self) -> str:
413
+ if self.yaml_data.get("licenseInfo") or not self.is_azure_flavor:
414
+ # typespec unbranded case and azure case with custom license
415
+ license_header = self.yaml_data.get("licenseInfo", {}).get("header", "")
416
+ else:
417
+ # typespec azure case without custom license and swagger case
418
+ license_header = self.options.get("header_text", DEFAULT_HEADER_TEXT)
419
+ if license_header:
420
+ license_header = license_header.replace("\n", "\n# ")
421
+ license_header = (
422
+ "# --------------------------------------------------------------------------\n# " + license_header
423
+ )
424
+ license_header += "\n# --------------------------------------------------------------------------"
425
+ return license_header
426
+
427
+ @property
428
+ def license_description(self) -> str:
429
+ if self.yaml_data.get("licenseInfo") or not self.is_azure_flavor:
430
+ # typespec unbranded case and azure case with custom license
431
+ return self.yaml_data.get("licenseInfo", {}).get("description", "")
432
+ # typespec azure case without custom license and swagger case
433
+ return DEFAULT_LICENSE_DESCRIPTION
434
+
435
+ @property
436
+ def company_name(self) -> str:
437
+ if self.yaml_data.get("licenseInfo") or not self.is_azure_flavor:
438
+ # typespec unbranded case and azure case with custom license
439
+ return self.yaml_data.get("licenseInfo", {}).get("company", "")
440
+ # typespec azure case without custom license and swagger case
441
+ return "Microsoft Corporation"
@@ -197,9 +197,13 @@ 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
205
+ if not self.code_model.license_description:
206
+ package_files.remove("LICENSE.jinja2")
203
207
  elif Path(self.code_model.options["package_mode"]).exists():
204
208
  env = Environment(
205
209
  loader=FileSystemLoader(str(Path(self.code_model.options["package_mode"]))),
@@ -271,7 +275,7 @@ class JinjaSerializer(ReaderAndWriter):
271
275
  if not "" in group_names:
272
276
  self.write_file(
273
277
  rest_path / Path("__init__.py"),
274
- self.code_model.options["license_header"],
278
+ self.code_model.license_header,
275
279
  )
276
280
 
277
281
  def _serialize_and_write_single_rest_layer(
@@ -460,21 +464,11 @@ class JinjaSerializer(ReaderAndWriter):
460
464
  metadata_serializer = MetadataSerializer(self.code_model, env, client_namespace=namespace)
461
465
  self.write_file(self.exec_path(namespace) / Path("_metadata.json"), metadata_serializer.serialize())
462
466
 
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
467
  @property
474
468
  def exec_path_compensation(self) -> Path:
475
469
  """Assume the process is running in the root folder of the package. If not, we need the path compensation."""
476
470
  return (
477
- Path("../" * (self._name_space().count(".") + 1))
471
+ Path("../" * (self.code_model.namespace.count(".") + 1))
478
472
  if self.code_model.options["no_namespace_folders"]
479
473
  else Path(".")
480
474
  )
@@ -482,16 +476,28 @@ class JinjaSerializer(ReaderAndWriter):
482
476
  def exec_path_for_test_sample(self, namespace: str) -> Path:
483
477
  return self.exec_path_compensation / Path(*namespace.split("."))
484
478
 
479
+ # pylint: disable=line-too-long
485
480
  def exec_path(self, namespace: str) -> Path:
486
481
  if self.code_model.options["no_namespace_folders"] and not self.code_model.options["multiapi"]:
482
+ # when output folder contains parts different from the namespace, we fall back to current folder directly.
483
+ # (e.g. https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/communication/azure-communication-callautomation/swagger/SWAGGER.md)
487
484
  return Path(".")
488
485
  return self.exec_path_compensation / Path(*namespace.split("."))
489
486
 
487
+ # pylint: disable=line-too-long
490
488
  @property
491
- def _additional_folder(self) -> Path:
489
+ def sample_additional_folder(self) -> Path:
490
+ # For special package, we need to additional folder when generate samples.
491
+ # For example, azure-mgmt-resource is combined by multiple modules, and each module is multiapi package.
492
+ # one of namespace is "azure.mgmt.resource.resources.v2020_01_01", then additional folder is "resources"
493
+ # so that we could avoid conflict when generate samples.
494
+ # python config: https://github.com/Azure/azure-rest-api-specs/blob/main/specification/resources/resource-manager/readme.python.md
495
+ # generated SDK: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/resources/azure-mgmt-resource/generated_samples
492
496
  namespace_config = get_namespace_config(self.code_model.namespace, self.code_model.options["multiapi"])
493
497
  num_of_namespace = namespace_config.count(".") + 1
494
- num_of_package_namespace = self._namespace_from_package_name.count(".") + 1
498
+ num_of_package_namespace = (
499
+ get_namespace_from_package_name(self.code_model.options["package_name"]).count(".") + 1
500
+ )
495
501
  if num_of_namespace > num_of_package_namespace:
496
502
  return Path("/".join(namespace_config.split(".")[num_of_package_namespace:]))
497
503
  return Path("")
@@ -514,7 +520,7 @@ class JinjaSerializer(ReaderAndWriter):
514
520
  file_name = to_snake_case(extract_sample_name(file)) + ".py"
515
521
  try:
516
522
  self.write_file(
517
- out_path / self._additional_folder / _sample_output_path(file) / file_name,
523
+ out_path / self.sample_additional_folder / _sample_output_path(file) / file_name,
518
524
  SampleSerializer(
519
525
  code_model=self.code_model,
520
526
  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 = (self.code_model.options["package_name"] or "").split("-")[:-1]
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)
@@ -19,7 +19,7 @@ from ..models import (
19
19
  CombinedType,
20
20
  FileImport,
21
21
  )
22
- from .utils import get_namespace_from_package_name, json_dumps_template
22
+ from .utils import json_dumps_template
23
23
 
24
24
 
25
25
  def is_lro(operation_type: str) -> bool:
@@ -2,7 +2,9 @@
2
2
  {% import 'operation_tools.jinja2' as op_tools %}
3
3
  {# actual template starts here #}
4
4
  # coding=utf-8
5
- {{ code_model.options['license_header'] }}
5
+ {% if code_model.license_header %}
6
+ {{ code_model.license_header }}
7
+ {% endif %}
6
8
 
7
9
  {{ imports }}
8
10
 
@@ -2,7 +2,9 @@
2
2
  {% import 'operation_tools.jinja2' as op_tools %}
3
3
  {# actual template starts here #}
4
4
  # coding=utf-8
5
- {{ code_model.options['license_header'] }}
5
+ {% if code_model.license_header %}
6
+ {{ code_model.license_header }}
7
+ {% endif %}
6
8
 
7
9
  {{ imports }}
8
10
 
@@ -1,5 +1,7 @@
1
1
  # coding=utf-8
2
- {{ code_model.options['license_header'] }}
2
+ {% if code_model.license_header %}
3
+ {{ code_model.license_header }}
4
+ {% endif %}
3
5
  import os
4
6
  import pytest
5
7
  from dotenv import load_dotenv
@@ -1,6 +1,8 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools %}
2
2
  # coding=utf-8
3
- {{ code_model.options['license_header'] }}
3
+ {% if code_model.license_header %}
4
+ {{ code_model.license_header }}
5
+ {% endif %}
4
6
 
5
7
  from enum import Enum
6
8
  from {{ code_model.core_library }}{{ "" if code_model.is_azure_flavor else ".utils" }} import CaseInsensitiveEnumMeta
@@ -1,6 +1,8 @@
1
1
  {% import 'keywords.jinja2' as keywords %}
2
2
  # coding=utf-8
3
- {{ code_model.options['license_header'] }}
3
+ {% if code_model.license_header %}
4
+ {{ code_model.license_header }}
5
+ {% endif %}
4
6
  {{ keywords.path_type_checking_imports() }}
5
7
  {% if clients %}
6
8
  {% for client in clients %}
@@ -1,9 +1,7 @@
1
1
  # coding=utf-8
2
- # --------------------------------------------------------------------------
3
- # Copyright (c) {{ code_model.options["company_name"] }} Corporation. All rights reserved.
4
- # Licensed under the MIT License. See License.txt in the project root for
5
- # license information.
6
- # --------------------------------------------------------------------------
2
+ {% if code_model.license_header %}
3
+ {{ code_model.license_header }}
4
+ {% endif %}
7
5
  # pylint: disable=protected-access, broad-except
8
6
 
9
7
  import copy
@@ -1,6 +1,8 @@
1
1
  {% import 'operation_tools.jinja2' as op_tools %}
2
2
  # coding=utf-8
3
- {{ code_model.options['license_header'] }}
3
+ {% if code_model.license_header %}
4
+ {{ code_model.license_header }}
5
+ {% endif %}
4
6
  {% if serializer.global_pylint_disables() %}
5
7
  {{ serializer.global_pylint_disables() }}
6
8
  {% endif %}
@@ -1,6 +1,8 @@
1
1
  {% import 'keywords.jinja2' as keywords %}
2
2
  # coding=utf-8
3
- {{ code_model.options['license_header'] }}
3
+ {% if code_model.license_header %}
4
+ {{ code_model.license_header }}
5
+ {% endif %}
4
6
  {{ keywords.path_type_checking_imports() }}
5
7
  {% if schemas %}
6
8
 
@@ -2,7 +2,9 @@
2
2
  {% set operations_description = "async operations" if async_mode else "operations" %}
3
3
  {% set return_none_type_annotation = " -> None" if async_mode else "" %}
4
4
  # coding=utf-8
5
- {{ code_model.options['license_header'] }}
5
+ {% if code_model.license_header %}
6
+ {{ code_model.license_header }}
7
+ {% endif %}
6
8
  {{ imports }}
7
9
  {{ unset }}
8
10
  {% if code_model.options["builders_visibility"] == "embedded" and not async_mode %}
@@ -2,7 +2,9 @@
2
2
  {% import 'keywords.jinja2' as keywords %}
3
3
  {# actual template starts here #}
4
4
  # coding=utf-8
5
- {{ code_model.options['license_header'] }}
5
+ {% if code_model.license_header %}
6
+ {{ code_model.license_header }}
7
+ {% endif %}
6
8
  {{ keywords.path_type_checking_imports() }}
7
9
  {{ op_tools.serialize(operation_group_imports()) }}
8
10
  {{ keywords.patch_imports() }}
@@ -1,21 +1 @@
1
- Copyright (c) {{ code_model.options["company_name"] }} Corporation.
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ {{ code_model.license_description }}