@typespec/http-client-python 0.5.0 → 0.6.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.
Files changed (163) hide show
  1. package/dist/emitter/code-model.d.ts.map +1 -1
  2. package/dist/emitter/code-model.js +10 -7
  3. package/dist/emitter/code-model.js.map +1 -1
  4. package/dist/emitter/emitter.d.ts.map +1 -1
  5. package/dist/emitter/emitter.js +35 -7
  6. package/dist/emitter/emitter.js.map +1 -1
  7. package/dist/emitter/http.js +1 -1
  8. package/dist/emitter/http.js.map +1 -1
  9. package/dist/emitter/lib.d.ts +1 -0
  10. package/dist/emitter/lib.d.ts.map +1 -1
  11. package/dist/emitter/lib.js +1 -0
  12. package/dist/emitter/lib.js.map +1 -1
  13. package/dist/emitter/types.d.ts.map +1 -1
  14. package/dist/emitter/types.js +7 -4
  15. package/dist/emitter/types.js.map +1 -1
  16. package/dist/emitter/utils.d.ts +1 -0
  17. package/dist/emitter/utils.d.ts.map +1 -1
  18. package/dist/emitter/utils.js +19 -0
  19. package/dist/emitter/utils.js.map +1 -1
  20. package/emitter/src/code-model.ts +16 -6
  21. package/emitter/src/emitter.ts +37 -11
  22. package/emitter/src/http.ts +1 -1
  23. package/emitter/src/lib.ts +4 -0
  24. package/emitter/src/types.ts +16 -4
  25. package/emitter/src/utils.ts +27 -0
  26. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  27. package/eng/scripts/Test-Packages.ps1 +1 -1
  28. package/eng/scripts/ci/regenerate.ts +21 -14
  29. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  30. package/eng/scripts/setup/install.py +0 -5
  31. package/eng/scripts/setup/install.ts +0 -20
  32. package/generator/build/lib/pygen/black.py +2 -2
  33. package/generator/build/lib/pygen/codegen/__init__.py +6 -4
  34. package/generator/build/lib/pygen/codegen/_utils.py +4 -0
  35. package/generator/build/lib/pygen/codegen/models/base.py +2 -3
  36. package/generator/build/lib/pygen/codegen/models/base_builder.py +5 -3
  37. package/generator/build/lib/pygen/codegen/models/client.py +28 -19
  38. package/generator/build/lib/pygen/codegen/models/code_model.py +200 -33
  39. package/generator/build/lib/pygen/codegen/models/combined_type.py +8 -5
  40. package/generator/build/lib/pygen/codegen/models/constant_type.py +2 -3
  41. package/generator/build/lib/pygen/codegen/models/credential_types.py +1 -2
  42. package/generator/build/lib/pygen/codegen/models/dictionary_type.py +2 -3
  43. package/generator/build/lib/pygen/codegen/models/enum_type.py +47 -24
  44. package/generator/build/lib/pygen/codegen/models/imports.py +14 -12
  45. package/generator/build/lib/pygen/codegen/models/list_type.py +2 -3
  46. package/generator/build/lib/pygen/codegen/models/lro_operation.py +8 -4
  47. package/generator/build/lib/pygen/codegen/models/lro_paging_operation.py +2 -2
  48. package/generator/build/lib/pygen/codegen/models/model_type.py +34 -19
  49. package/generator/build/lib/pygen/codegen/models/operation.py +66 -29
  50. package/generator/build/lib/pygen/codegen/models/operation_group.py +56 -11
  51. package/generator/build/lib/pygen/codegen/models/paging_operation.py +9 -6
  52. package/generator/build/lib/pygen/codegen/models/parameter.py +10 -10
  53. package/generator/build/lib/pygen/codegen/models/parameter_list.py +7 -7
  54. package/generator/build/lib/pygen/codegen/models/primitive_types.py +23 -43
  55. package/generator/build/lib/pygen/codegen/models/property.py +7 -7
  56. package/generator/build/lib/pygen/codegen/models/request_builder.py +9 -15
  57. package/generator/build/lib/pygen/codegen/models/response.py +6 -8
  58. package/generator/build/lib/pygen/codegen/models/utils.py +11 -0
  59. package/generator/build/lib/pygen/codegen/serializers/__init__.py +201 -242
  60. package/generator/build/lib/pygen/codegen/serializers/base_serializer.py +19 -1
  61. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +53 -35
  62. package/generator/build/lib/pygen/codegen/serializers/client_serializer.py +9 -5
  63. package/generator/build/lib/pygen/codegen/serializers/enum_serializer.py +17 -3
  64. package/generator/build/lib/pygen/codegen/serializers/general_serializer.py +26 -14
  65. package/generator/build/lib/pygen/codegen/serializers/metadata_serializer.py +26 -8
  66. package/generator/build/lib/pygen/codegen/serializers/model_init_serializer.py +9 -4
  67. package/generator/build/lib/pygen/codegen/serializers/model_serializer.py +62 -22
  68. package/generator/build/lib/pygen/codegen/serializers/operation_groups_serializer.py +19 -16
  69. package/generator/build/lib/pygen/codegen/serializers/operations_init_serializer.py +5 -10
  70. package/generator/build/lib/pygen/codegen/serializers/parameter_serializer.py +10 -7
  71. package/generator/build/lib/pygen/codegen/serializers/request_builders_serializer.py +10 -1
  72. package/generator/build/lib/pygen/codegen/serializers/sample_serializer.py +7 -10
  73. package/generator/build/lib/pygen/codegen/serializers/test_serializer.py +24 -28
  74. package/generator/build/lib/pygen/codegen/serializers/types_serializer.py +6 -1
  75. package/generator/build/lib/pygen/codegen/serializers/utils.py +1 -15
  76. package/generator/build/lib/pygen/codegen/templates/client_container.py.jinja2 +1 -1
  77. package/generator/build/lib/pygen/codegen/templates/config_container.py.jinja2 +1 -1
  78. package/generator/build/lib/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
  79. package/generator/build/lib/pygen/codegen/templates/init.py.jinja2 +1 -1
  80. package/generator/build/lib/pygen/codegen/templates/model_container.py.jinja2 +1 -1
  81. package/generator/build/lib/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
  82. package/generator/build/lib/pygen/codegen/templates/test.py.jinja2 +3 -3
  83. package/generator/build/lib/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
  84. package/generator/build/lib/pygen/codegen/templates/vendor.py.jinja2 +4 -4
  85. package/generator/build/lib/pygen/preprocess/__init__.py +0 -4
  86. package/generator/dev_requirements.txt +2 -2
  87. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  88. package/generator/pygen/black.py +2 -2
  89. package/generator/pygen/codegen/__init__.py +6 -4
  90. package/generator/pygen/codegen/_utils.py +4 -0
  91. package/generator/pygen/codegen/models/base.py +2 -3
  92. package/generator/pygen/codegen/models/base_builder.py +5 -3
  93. package/generator/pygen/codegen/models/client.py +28 -19
  94. package/generator/pygen/codegen/models/code_model.py +200 -33
  95. package/generator/pygen/codegen/models/combined_type.py +8 -5
  96. package/generator/pygen/codegen/models/constant_type.py +2 -3
  97. package/generator/pygen/codegen/models/credential_types.py +1 -2
  98. package/generator/pygen/codegen/models/dictionary_type.py +2 -3
  99. package/generator/pygen/codegen/models/enum_type.py +47 -24
  100. package/generator/pygen/codegen/models/imports.py +14 -12
  101. package/generator/pygen/codegen/models/list_type.py +2 -3
  102. package/generator/pygen/codegen/models/lro_operation.py +8 -4
  103. package/generator/pygen/codegen/models/lro_paging_operation.py +2 -2
  104. package/generator/pygen/codegen/models/model_type.py +34 -19
  105. package/generator/pygen/codegen/models/operation.py +66 -29
  106. package/generator/pygen/codegen/models/operation_group.py +56 -11
  107. package/generator/pygen/codegen/models/paging_operation.py +9 -6
  108. package/generator/pygen/codegen/models/parameter.py +10 -10
  109. package/generator/pygen/codegen/models/parameter_list.py +7 -7
  110. package/generator/pygen/codegen/models/primitive_types.py +23 -43
  111. package/generator/pygen/codegen/models/property.py +7 -7
  112. package/generator/pygen/codegen/models/request_builder.py +9 -15
  113. package/generator/pygen/codegen/models/response.py +6 -8
  114. package/generator/pygen/codegen/models/utils.py +11 -0
  115. package/generator/pygen/codegen/serializers/__init__.py +201 -242
  116. package/generator/pygen/codegen/serializers/base_serializer.py +19 -1
  117. package/generator/pygen/codegen/serializers/builder_serializer.py +53 -35
  118. package/generator/pygen/codegen/serializers/client_serializer.py +9 -5
  119. package/generator/pygen/codegen/serializers/enum_serializer.py +17 -3
  120. package/generator/pygen/codegen/serializers/general_serializer.py +26 -14
  121. package/generator/pygen/codegen/serializers/metadata_serializer.py +26 -8
  122. package/generator/pygen/codegen/serializers/model_init_serializer.py +9 -4
  123. package/generator/pygen/codegen/serializers/model_serializer.py +62 -22
  124. package/generator/pygen/codegen/serializers/operation_groups_serializer.py +19 -16
  125. package/generator/pygen/codegen/serializers/operations_init_serializer.py +5 -10
  126. package/generator/pygen/codegen/serializers/parameter_serializer.py +10 -7
  127. package/generator/pygen/codegen/serializers/request_builders_serializer.py +10 -1
  128. package/generator/pygen/codegen/serializers/sample_serializer.py +7 -10
  129. package/generator/pygen/codegen/serializers/test_serializer.py +24 -28
  130. package/generator/pygen/codegen/serializers/types_serializer.py +6 -1
  131. package/generator/pygen/codegen/serializers/utils.py +1 -15
  132. package/generator/pygen/codegen/templates/client_container.py.jinja2 +1 -1
  133. package/generator/pygen/codegen/templates/config_container.py.jinja2 +1 -1
  134. package/generator/pygen/codegen/templates/enum_container.py.jinja2 +1 -1
  135. package/generator/pygen/codegen/templates/init.py.jinja2 +1 -1
  136. package/generator/pygen/codegen/templates/model_container.py.jinja2 +1 -1
  137. package/generator/pygen/codegen/templates/operations_folder_init.py.jinja2 +2 -4
  138. package/generator/pygen/codegen/templates/test.py.jinja2 +3 -3
  139. package/generator/pygen/codegen/templates/testpreparer.py.jinja2 +2 -2
  140. package/generator/pygen/codegen/templates/vendor.py.jinja2 +4 -4
  141. package/generator/pygen/preprocess/__init__.py +0 -4
  142. package/generator/test/azure/mock_api_tests/asynctests/test_azure_client_generator_core_flatten_async.py +1 -1
  143. package/generator/test/{generic_mock_api_tests/asynctests/test_payload_pageable_async.py → azure/mock_api_tests/asynctests/test_azure_payload_pageable_async.py} +1 -1
  144. package/generator/test/azure/mock_api_tests/asynctests/test_client_namespace_async.py +31 -0
  145. package/generator/test/azure/mock_api_tests/conftest.py +5 -4
  146. package/generator/test/azure/mock_api_tests/test_azure_client_generator_core_flatten.py +1 -1
  147. package/generator/test/{generic_mock_api_tests/test_payload_pageable.py → azure/mock_api_tests/test_azure_payload_pageable.py} +1 -1
  148. package/generator/test/azure/mock_api_tests/test_client_namespace.py +29 -0
  149. package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_resiliency_srv_driven.py +4 -2
  150. package/generator/test/{generic_mock_api_tests/asynctests → azure/mock_api_tests}/test_resiliency_srv_driven_async.py +4 -2
  151. package/generator/test/azure/requirements.txt +11 -9
  152. package/generator/test/azure/tox.ini +2 -2
  153. package/generator/test/generic_mock_api_tests/conftest.py +9 -4
  154. package/generator/test/unbranded/mock_api_tests/conftest.py +4 -4
  155. package/generator/test/unbranded/mock_api_tests/test_unbranded.py +1 -1
  156. package/generator/test/unbranded/requirements.txt +2 -9
  157. package/generator/test/unbranded/tox.ini +2 -2
  158. package/package.json +5 -6
  159. package/generator/requirements.txt +0 -7
  160. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_naming_async.py +0 -0
  161. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/asynctests/test_client_structure_async.py +0 -0
  162. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_naming.py +0 -0
  163. /package/generator/test/{generic_mock_api_tests → azure/mock_api_tests}/test_client_structure.py +0 -0
@@ -57,6 +57,9 @@ function addDefaultOptions(sdkContext: SdkContext) {
57
57
  if (!options.flavor && sdkContext.emitContext.emitterOutputDir.includes("azure")) {
58
58
  options.flavor = "azure";
59
59
  }
60
+ if (options["enable-typespec-namespace"] === undefined) {
61
+ options["enable-typespec-namespace"] = options.flavor !== "azure";
62
+ }
60
63
  }
61
64
 
62
65
  async function createPythonSdkContext<TServiceOperation extends SdkServiceOperation>(
@@ -79,6 +82,7 @@ export async function $onEmit(context: EmitContext<PythonEmitterOptions>) {
79
82
  const sdkContext = await createPythonSdkContext<SdkHttpOperation>(context);
80
83
  const root = path.join(dirname(fileURLToPath(import.meta.url)), "..", "..");
81
84
  const outputDir = context.emitterOutputDir;
85
+ addDefaultOptions(sdkContext);
82
86
  const yamlMap = emitCodeModel(sdkContext);
83
87
  if (yamlMap.clients.length === 0) {
84
88
  reportDiagnostic(program, {
@@ -88,7 +92,6 @@ export async function $onEmit(context: EmitContext<PythonEmitterOptions>) {
88
92
  return;
89
93
  }
90
94
  const yamlPath = await saveCodeModelAsYaml("python-yaml-path", yamlMap);
91
- addDefaultOptions(sdkContext);
92
95
  const resolvedOptions = sdkContext.emitContext.options;
93
96
  const commandArgs: Record<string, string> = {};
94
97
  if (resolvedOptions["packaging-files-config"]) {
@@ -186,15 +189,38 @@ async function setupPyodideCall(root: string) {
186
189
  const pyodide = await loadPyodide({
187
190
  indexURL: path.dirname(fileURLToPath(import.meta.resolve("pyodide"))),
188
191
  });
189
- // mount generator to pyodide
190
- pyodide.FS.mkdirTree("/generator");
191
- pyodide.FS.mount(
192
- pyodide.FS.filesystems.NODEFS,
193
- { root: path.join(root, "generator") },
194
- "/generator",
195
- );
196
- await pyodide.loadPackage("micropip");
197
- const micropip = pyodide.pyimport("micropip");
198
- await micropip.install("emfs:/generator/dist/pygen-0.1.0-py3-none-any.whl");
192
+ const micropipLockPath = path.join(root, "micropip.lock");
193
+ while (true) {
194
+ if (fs.existsSync(micropipLockPath)) {
195
+ try {
196
+ const stats = fs.statSync(micropipLockPath);
197
+ const now = new Date().getTime();
198
+ const lockAge = (now - stats.mtime.getTime()) / 1000;
199
+ if (lockAge > 300) {
200
+ fs.unlinkSync(micropipLockPath);
201
+ }
202
+ } catch (err) {
203
+ // ignore
204
+ }
205
+ }
206
+ try {
207
+ const fd = fs.openSync(micropipLockPath, "wx");
208
+ // mount generator to pyodide
209
+ pyodide.FS.mkdirTree("/generator");
210
+ pyodide.FS.mount(
211
+ pyodide.FS.filesystems.NODEFS,
212
+ { root: path.join(root, "generator") },
213
+ "/generator",
214
+ );
215
+ await pyodide.loadPackage("micropip");
216
+ const micropip = pyodide.pyimport("micropip");
217
+ await micropip.install("emfs:/generator/dist/pygen-0.1.0-py3-none-any.whl");
218
+ fs.closeSync(fd);
219
+ fs.unlinkSync(micropipLockPath);
220
+ break;
221
+ } catch (err) {
222
+ await new Promise((resolve) => setTimeout(resolve, 1000));
223
+ }
224
+ }
199
225
  return pyodide;
200
226
  }
@@ -204,7 +204,7 @@ function emitHttpOperation(
204
204
  apiVersions: [],
205
205
  wantTracing: true,
206
206
  exposeStreamKeyword: true,
207
- crossLanguageDefinitionId: method?.crossLanguageDefintionId,
207
+ crossLanguageDefinitionId: method?.crossLanguageDefinitionId,
208
208
  samples: arrayToRecord(method?.operation.examples),
209
209
  internal: method.access === "internal",
210
210
  };
@@ -17,6 +17,9 @@ export interface PythonEmitterOptions {
17
17
  debug?: boolean;
18
18
  flavor?: "azure";
19
19
  "examples-dir"?: string;
20
+ // If true, package namespace will respect the typespec namespace. Otherwise,
21
+ // package namespace is always aligned with package name.
22
+ "enable-typespec-namespace"?: boolean;
20
23
  "use-pyodide"?: boolean;
21
24
  }
22
25
 
@@ -44,6 +47,7 @@ const EmitterOptionsSchema: JSONSchemaType<PythonEmitterOptions> = {
44
47
  debug: { type: "boolean", nullable: true },
45
48
  flavor: { type: "string", nullable: true },
46
49
  "examples-dir": { type: "string", nullable: true, format: "absolute-path" },
50
+ "enable-typespec-namespace": { type: "boolean", nullable: true },
47
51
  "use-pyodide": { type: "boolean", nullable: true },
48
52
  },
49
53
  required: [],
@@ -21,7 +21,13 @@ import { Type } from "@typespec/compiler";
21
21
  import { HttpAuth, Visibility } from "@typespec/http";
22
22
  import { dump } from "js-yaml";
23
23
  import { PythonSdkContext } from "./lib.js";
24
- import { camelToSnakeCase, emitParamBase, getAddedOn, getImplementation } from "./utils.js";
24
+ import {
25
+ camelToSnakeCase,
26
+ emitParamBase,
27
+ getAddedOn,
28
+ getClientNamespace,
29
+ getImplementation,
30
+ } from "./utils.js";
25
31
 
26
32
  export const typesMap = new Map<SdkType, Record<string, any>>();
27
33
  export const simpleTypesMap = new Map<string | null, Record<string, any>>();
@@ -75,7 +81,7 @@ export function getType<TServiceOperation extends SdkServiceOperation>(
75
81
  case "union":
76
82
  return emitUnion(context, type);
77
83
  case "enum":
78
- return emitEnum(type);
84
+ return emitEnum(context, type);
79
85
  case "constant":
80
86
  return emitConstant(type)!;
81
87
  case "array":
@@ -86,7 +92,7 @@ export function getType<TServiceOperation extends SdkServiceOperation>(
86
92
  case "duration":
87
93
  return emitDurationOrDateType(type);
88
94
  case "enumvalue":
89
- return emitEnumMember(type, emitEnum(type.enumType));
95
+ return emitEnumMember(type, emitEnum(context, type.enumType));
90
96
  case "credential":
91
97
  return emitCredential(type);
92
98
  case "bytes":
@@ -289,6 +295,7 @@ function emitModel<TServiceOperation extends SdkServiceOperation>(
289
295
  usage: type.usage,
290
296
  isXml: type.usage & UsageFlags.Xml ? true : false,
291
297
  xmlMetadata: type.usage & UsageFlags.Xml ? getXmlMetadata(type) : undefined,
298
+ clientNamespace: getClientNamespace(context, type.clientNamespace),
292
299
  };
293
300
 
294
301
  typesMap.set(type, newValue);
@@ -314,7 +321,10 @@ function emitModel<TServiceOperation extends SdkServiceOperation>(
314
321
  return newValue;
315
322
  }
316
323
 
317
- function emitEnum(type: SdkEnumType): Record<string, any> {
324
+ function emitEnum<TServiceOperation extends SdkServiceOperation>(
325
+ context: PythonSdkContext<TServiceOperation>,
326
+ type: SdkEnumType,
327
+ ): Record<string, any> {
318
328
  if (typesMap.has(type)) {
319
329
  return typesMap.get(type)!;
320
330
  }
@@ -352,6 +362,7 @@ function emitEnum(type: SdkEnumType): Record<string, any> {
352
362
  values,
353
363
  xmlMetadata: {},
354
364
  crossLanguageDefinitionId: type.crossLanguageDefinitionId,
365
+ clientNamespace: getClientNamespace(context, type.clientNamespace),
355
366
  };
356
367
  for (const value of type.values) {
357
368
  newValue.values.push(emitEnumMember(value, newValue));
@@ -469,6 +480,7 @@ function emitUnion<TServiceOperation extends SdkServiceOperation>(
469
480
  type: "combined",
470
481
  types: type.variantTypes.map((x) => getType(context, x)),
471
482
  xmlMetadata: {},
483
+ clientNamespace: getClientNamespace(context, type.clientNamespace),
472
484
  });
473
485
  }
474
486
 
@@ -199,3 +199,30 @@ export function isAzureCoreErrorResponse(t: SdkType | undefined): boolean {
199
199
  export function capitalize(name: string): string {
200
200
  return name[0].toUpperCase() + name.slice(1);
201
201
  }
202
+
203
+ export function getClientNamespace<TServiceOperation extends SdkServiceOperation>(
204
+ context: PythonSdkContext<TServiceOperation>,
205
+ clientNamespace: string,
206
+ ) {
207
+ const rootNamespace = removeUnderscoresFromNamespace(
208
+ context.sdkPackage.rootNamespace,
209
+ ).toLowerCase();
210
+ if (!context.emitContext.options["enable-typespec-namespace"]) {
211
+ return rootNamespace;
212
+ }
213
+ if (
214
+ [
215
+ "azure.core",
216
+ "azure.resourcemanager",
217
+ "azure.clientgenerator.core",
218
+ "typespec.rest",
219
+ "typespec.http",
220
+ "typespec.versioning",
221
+ ].some((item) => clientNamespace.toLowerCase().startsWith(item))
222
+ ) {
223
+ return rootNamespace;
224
+ }
225
+ return clientNamespace === ""
226
+ ? rootNamespace
227
+ : removeUnderscoresFromNamespace(clientNamespace).toLowerCase();
228
+ }