@typespec/http-client-python 0.6.11 → 0.7.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 (39) hide show
  1. package/dist/emitter/emitter.d.ts.map +1 -1
  2. package/dist/emitter/emitter.js +114 -51
  3. package/dist/emitter/emitter.js.map +1 -1
  4. package/dist/emitter/lib.d.ts +28 -1
  5. package/dist/emitter/lib.d.ts.map +1 -1
  6. package/dist/emitter/lib.js +21 -1
  7. package/dist/emitter/lib.js.map +1 -1
  8. package/dist/emitter/types.d.ts.map +1 -1
  9. package/dist/emitter/types.js +3 -1
  10. package/dist/emitter/types.js.map +1 -1
  11. package/dist/emitter/utils.d.ts +1 -0
  12. package/dist/emitter/utils.d.ts.map +1 -1
  13. package/dist/emitter/utils.js +78 -0
  14. package/dist/emitter/utils.js.map +1 -1
  15. package/emitter/src/emitter.ts +119 -51
  16. package/emitter/src/lib.ts +22 -1
  17. package/emitter/src/types.ts +4 -1
  18. package/emitter/src/utils.ts +82 -0
  19. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  20. package/emitter/test/utils.test.ts +6 -1
  21. package/eng/scripts/Build-Packages.ps1 +3 -2
  22. package/eng/scripts/ci/regenerate.ts +31 -4
  23. package/eng/scripts/ci/run_apiview.py +5 -0
  24. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  25. package/eng/scripts/setup/run_tsp.py +2 -3
  26. package/generator/build/lib/pygen/codegen/templates/model_dpg.py.jinja2 +0 -10
  27. package/generator/build/lib/pygen/codegen/templates/serialization.py.jinja2 +1 -1
  28. package/generator/component-detection-pip-report.json +2 -2
  29. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  30. package/generator/pygen/codegen/templates/model_dpg.py.jinja2 +0 -10
  31. package/generator/pygen/codegen/templates/serialization.py.jinja2 +1 -1
  32. package/generator/pygen.egg-info/PKG-INFO +0 -1
  33. package/generator/pygen.egg-info/SOURCES.txt +0 -1
  34. package/generator/pygen.egg-info/requires.txt +0 -1
  35. package/generator/setup.py +0 -1
  36. package/package.json +24 -23
  37. package/generator/build/lib/pygen/m2r.py +0 -65
  38. package/generator/pygen/m2r.py +0 -65
  39. package/generator/test/generic_mock_api_tests/unittests/test_m2r.py +0 -10
@@ -58,6 +58,7 @@ const EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, st
58
58
  },
59
59
  "type/array": {
60
60
  "package-name": "typetest-array",
61
+ "use-pyodide": "true",
61
62
  },
62
63
  "type/dictionary": {
63
64
  "package-name": "typetest-dictionary",
@@ -85,6 +86,7 @@ const EMITTER_OPTIONS: Record<string, Record<string, string> | Record<string, st
85
86
  },
86
87
  "type/model/inheritance/recursive": {
87
88
  "package-name": "typetest-model-recursive",
89
+ "use-pyodide": "true",
88
90
  },
89
91
  "type/model/usage": {
90
92
  "package-name": "typetest-model-usage",
@@ -314,10 +316,24 @@ function _getCmdList(spec: string, flags: RegenerateFlags): TspCommand[] {
314
316
  });
315
317
  }
316
318
 
319
+ async function runTaskPool(tasks: Array<() => Promise<void>>, poolLimit: number): Promise<void> {
320
+ let currentIndex = 0;
321
+
322
+ async function worker() {
323
+ while (currentIndex < tasks.length) {
324
+ const index = currentIndex++;
325
+ await tasks[index]();
326
+ }
327
+ }
328
+
329
+ const workers = new Array(Math.min(poolLimit, tasks.length)).fill(null).map(() => worker());
330
+ await Promise.all(workers);
331
+ }
332
+
317
333
  async function regenerate(flags: RegenerateFlagsInput): Promise<void> {
318
334
  if (flags.flavor === undefined) {
319
335
  await regenerate({ flavor: "azure", ...flags });
320
- await regenerate({ flavor: "unbranded", pyodide: true, ...flags });
336
+ await regenerate({ flavor: "unbranded", ...flags });
321
337
  } else {
322
338
  const flagsResolved = { debug: false, flavor: flags.flavor, ...flags };
323
339
  const subdirectoriesForAzure = await getSubdirectories(AZURE_HTTP_SPECS, flagsResolved);
@@ -329,11 +345,22 @@ async function regenerate(flags: RegenerateFlagsInput): Promise<void> {
329
345
  const cmdList: TspCommand[] = subdirectories.flatMap((subdirectory) =>
330
346
  _getCmdList(subdirectory, flagsResolved),
331
347
  );
332
- const PromiseCommands = cmdList.map((tspCommand) => executeCommand(tspCommand));
333
- await Promise.all(PromiseCommands);
348
+
349
+ // Create tasks as functions for the pool
350
+ const tasks: Array<() => Promise<void>> = cmdList.map((tspCommand) => {
351
+ return () => executeCommand(tspCommand);
352
+ });
353
+
354
+ // Run tasks with a concurrency limit
355
+ await runTaskPool(tasks, 30);
334
356
  }
335
357
  }
336
358
 
359
+ const start = performance.now();
337
360
  regenerate(argv.values)
338
- .then(() => console.log("Regeneration successful"))
361
+ .then(() =>
362
+ console.log(
363
+ `Regeneration successful, time taken: ${Math.round((performance.now() - start) / 1000)} s`,
364
+ ),
365
+ )
339
366
  .catch((error) => console.error(`Regeneration failed: ${error.message}`));
@@ -8,6 +8,8 @@
8
8
  # This script is used to execute apiview generation within a tox environment. Depending on which package is being executed against,
9
9
  # a failure may be suppressed.
10
10
 
11
+ import os
12
+ import sys
11
13
  from subprocess import check_call, CalledProcessError
12
14
  import logging
13
15
  from util import run_check
@@ -37,4 +39,7 @@ def _single_dir_apiview(mod):
37
39
 
38
40
 
39
41
  if __name__ == "__main__":
42
+ if os.name == "nt":
43
+ logging.info("Skip running ApiView on Windows for now to reduce time cost in CI")
44
+ sys.exit(0)
40
45
  run_check("apiview", _single_dir_apiview, "APIView")
@@ -7,7 +7,7 @@ import sys
7
7
  import venv
8
8
  import logging
9
9
  from pathlib import Path
10
- from pygen import m2r, preprocess, codegen, black
10
+ from pygen import preprocess, codegen, black
11
11
  from pygen.utils import parse_args
12
12
 
13
13
  _ROOT_DIR = Path(__file__).parent.parent.parent.parent
@@ -34,9 +34,8 @@ if __name__ == "__main__":
34
34
  debugpy.wait_for_client()
35
35
  breakpoint() # pylint: disable=undefined-variable
36
36
 
37
- # run m2r
37
+ # pre-process and run black
38
38
  args, unknown_args = parse_args()
39
- m2r.M2R(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
40
39
  preprocess.PreProcessPlugin(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
41
40
  codegen.CodeGenerator(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
42
41
  black.BlackScriptPlugin(output_folder=args.output_folder, **unknown_args).process()
@@ -8,16 +8,6 @@
8
8
 
9
9
  {{ serializer.discriminator_docstring(model) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n ') }}
10
10
  {% endif %}
11
- {% if model.has_readonly_or_constant_property %}
12
-
13
- Readonly variables are only populated by the server, and will be ignored when sending a request.
14
- {% endif %}
15
- {% if (model.properties | selectattr('optional', "equalto", false) | first) is defined %}
16
-
17
- {% if not model.is_usage_output %}
18
- All required parameters must be populated in order to send to server.
19
- {% endif %}
20
- {% endif %}
21
11
 
22
12
  {% if model.properties != None %}
23
13
  {% for p in model.properties %}
@@ -410,7 +410,7 @@ class Model:
410
410
  :param function key_extractors: A key extractor function.
411
411
  :param str content_type: JSON by default, set application/xml if XML.
412
412
  :returns: An instance of this model
413
- :raises: DeserializationError if something went wrong
413
+ :raises DeserializationError: if something went wrong
414
414
  :rtype: Self
415
415
  """
416
416
  deserializer = Deserializer(cls._infer_class_models())
@@ -126,9 +126,9 @@
126
126
  "implementation_version": "3.8.10",
127
127
  "os_name": "posix",
128
128
  "platform_machine": "x86_64",
129
- "platform_release": "5.15.0-1079-azure",
129
+ "platform_release": "5.15.0-1081-azure",
130
130
  "platform_system": "Linux",
131
- "platform_version": "#88~20.04.1-Ubuntu SMP Fri Jan 17 18:28:29 UTC 2025",
131
+ "platform_version": "#90~20.04.1-Ubuntu SMP Tue Jan 28 05:34:18 UTC 2025",
132
132
  "python_full_version": "3.8.10",
133
133
  "platform_python_implementation": "CPython",
134
134
  "python_version": "3.8",
@@ -8,16 +8,6 @@
8
8
 
9
9
  {{ serializer.discriminator_docstring(model) | wordwrap(width=95, break_long_words=False, break_on_hyphens=False, wrapstring='\n ') }}
10
10
  {% endif %}
11
- {% if model.has_readonly_or_constant_property %}
12
-
13
- Readonly variables are only populated by the server, and will be ignored when sending a request.
14
- {% endif %}
15
- {% if (model.properties | selectattr('optional', "equalto", false) | first) is defined %}
16
-
17
- {% if not model.is_usage_output %}
18
- All required parameters must be populated in order to send to server.
19
- {% endif %}
20
- {% endif %}
21
11
 
22
12
  {% if model.properties != None %}
23
13
  {% for p in model.properties %}
@@ -410,7 +410,7 @@ class Model:
410
410
  :param function key_extractors: A key extractor function.
411
411
  :param str content_type: JSON by default, set application/xml if XML.
412
412
  :returns: An instance of this model
413
- :raises: DeserializationError if something went wrong
413
+ :raises DeserializationError: if something went wrong
414
414
  :rtype: Self
415
415
  """
416
416
  deserializer = Deserializer(cls._infer_class_models())
@@ -20,7 +20,6 @@ License-File: LICENSE
20
20
  Requires-Dist: black==24.8.0
21
21
  Requires-Dist: docutils>=0.20.1
22
22
  Requires-Dist: Jinja2==3.1.3
23
- Requires-Dist: m2r2==0.3.3.post2
24
23
  Requires-Dist: PyYAML==6.0.1
25
24
  Requires-Dist: tomli==2.0.1
26
25
  Requires-Dist: setuptools==69.5.1
@@ -5,7 +5,6 @@ setup.py
5
5
  pygen/__init__.py
6
6
  pygen/_version.py
7
7
  pygen/black.py
8
- pygen/m2r.py
9
8
  pygen/utils.py
10
9
  pygen.egg-info/PKG-INFO
11
10
  pygen.egg-info/SOURCES.txt
@@ -1,7 +1,6 @@
1
1
  black==24.8.0
2
2
  docutils>=0.20.1
3
3
  Jinja2==3.1.3
4
- m2r2==0.3.3.post2
5
4
  PyYAML==6.0.1
6
5
  tomli==2.0.1
7
6
  setuptools==69.5.1
@@ -51,7 +51,6 @@ setup(
51
51
  "black==24.8.0",
52
52
  "docutils>=0.20.1",
53
53
  "Jinja2==3.1.3",
54
- "m2r2==0.3.3.post2",
55
54
  "PyYAML==6.0.1",
56
55
  "tomli==2.0.1",
57
56
  "setuptools==69.5.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http-client-python",
3
- "version": "0.6.11",
3
+ "version": "0.7.1",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec emitter for Python SDKs",
6
6
  "homepage": "https://typespec.io",
@@ -53,39 +53,40 @@
53
53
  "emitter"
54
54
  ],
55
55
  "peerDependencies": {
56
- "@azure-tools/typespec-autorest": ">=0.51.0 <1.0.0",
57
- "@azure-tools/typespec-azure-core": ">=0.51.0 <1.0.0",
58
- "@azure-tools/typespec-azure-resource-manager": ">=0.51.0 <1.0.0",
59
- "@azure-tools/typespec-azure-rulesets": ">=0.51.0 <3.0.0",
60
- "@azure-tools/typespec-client-generator-core": ">=0.51.1 <1.0.0",
61
- "@typespec/compiler": ">=0.65.0 <1.0.0",
62
- "@typespec/http": ">=0.65.0 <1.0.0",
63
- "@typespec/openapi": ">=0.65.0 <1.0.0",
64
- "@typespec/rest": ">=0.65.0 <1.0.0",
65
- "@typespec/versioning": ">=0.65.0 <1.0.0"
56
+ "@azure-tools/typespec-autorest": ">=0.52.0 <1.0.0",
57
+ "@azure-tools/typespec-azure-core": ">=0.52.0 <1.0.0",
58
+ "@azure-tools/typespec-azure-resource-manager": ">=0.52.0 <1.0.0",
59
+ "@azure-tools/typespec-azure-rulesets": ">=0.52.0 <3.0.0",
60
+ "@azure-tools/typespec-client-generator-core": ">=0.52.0 <1.0.0",
61
+ "@typespec/compiler": ">=0.66.0 <1.0.0",
62
+ "@typespec/http": ">=0.66.0 <1.0.0",
63
+ "@typespec/openapi": ">=0.66.0 <1.0.0",
64
+ "@typespec/rest": ">=0.66.0 <1.0.0",
65
+ "@typespec/versioning": ">=0.66.0 <1.0.0"
66
66
  },
67
67
  "dependencies": {
68
68
  "js-yaml": "~4.1.0",
69
+ "marked": "^15.0.6",
69
70
  "pyodide": "0.26.2",
70
71
  "semver": "~7.6.2",
71
72
  "tsx": "~4.19.1"
72
73
  },
73
74
  "devDependencies": {
74
- "@azure-tools/azure-http-specs": "0.1.0-alpha.6",
75
- "@azure-tools/typespec-autorest": "~0.51.0",
76
- "@azure-tools/typespec-azure-core": "~0.51.0",
77
- "@azure-tools/typespec-azure-resource-manager": "~0.51.0",
78
- "@azure-tools/typespec-azure-rulesets": "~0.51.0",
79
- "@azure-tools/typespec-client-generator-core": "~0.51.1",
75
+ "@azure-tools/azure-http-specs": "0.1.0-alpha.7",
76
+ "@azure-tools/typespec-autorest": "~0.52.0",
77
+ "@azure-tools/typespec-azure-core": "~0.52.0",
78
+ "@azure-tools/typespec-azure-resource-manager": "~0.52.0",
79
+ "@azure-tools/typespec-azure-rulesets": "~0.52.0",
80
+ "@azure-tools/typespec-client-generator-core": "~0.52.0",
80
81
  "@types/js-yaml": "~4.0.5",
81
82
  "@types/node": "~22.5.4",
82
83
  "@types/semver": "7.5.8",
83
- "@typespec/compiler": "~0.65.0",
84
- "@typespec/http": "~0.65.0",
85
- "@typespec/http-specs": "0.1.0-alpha.9",
86
- "@typespec/openapi": "~0.65.0",
87
- "@typespec/rest": "~0.65.0",
88
- "@typespec/versioning": "~0.65.0",
84
+ "@typespec/compiler": "~0.66.0",
85
+ "@typespec/http": "~0.66.0",
86
+ "@typespec/http-specs": "0.1.0-alpha.11",
87
+ "@typespec/openapi": "~0.66.0",
88
+ "@typespec/rest": "~0.66.0",
89
+ "@typespec/versioning": "~0.66.0",
89
90
  "c8": "^10.1.3",
90
91
  "chalk": "5.3.0",
91
92
  "rimraf": "~6.0.1",
@@ -1,65 +0,0 @@
1
- # -------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Corporation. All rights reserved.
3
- # Licensed under the MIT License. See License.txt in the project root for
4
- # license information.
5
- # --------------------------------------------------------------------------
6
- """An MD to RST plugin.
7
- """
8
- import logging
9
- from typing import Any, Dict, Set, Union
10
-
11
- import m2r2
12
-
13
- from . import YamlUpdatePlugin
14
- from .utils import parse_args
15
-
16
-
17
- _LOGGER = logging.getLogger(__name__)
18
-
19
-
20
- class GeneratorRenderer(m2r2.RestRenderer):
21
- """Redefine the concept of inline HTML in the renderer, we don't want to define a new format
22
- in the description/summary.
23
- """
24
-
25
- def inline_html(self, html: str) -> str:
26
- """Do not render inline HTML with a role definition."""
27
- return r"\ :code:`{}`".format(html)
28
-
29
-
30
- class M2R(YamlUpdatePlugin):
31
- """A plugin to convert any description and summary from MD to RST."""
32
-
33
- def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
34
- """Convert in place the YAML str."""
35
- self._convert_docstring_no_cycles(yaml_data, set())
36
-
37
- def _convert_docstring_no_cycles(self, yaml_data: Union[Dict[str, Any], str], node_list: Set[int]) -> None:
38
- """Walk the YAML tree to convert MD to RST."""
39
- if id(yaml_data) in node_list:
40
- return
41
- node_list.add(id(yaml_data))
42
-
43
- if isinstance(yaml_data, list):
44
- for elt in yaml_data:
45
- self._convert_docstring_no_cycles(elt, node_list)
46
- elif isinstance(yaml_data, dict):
47
- for key, value in yaml_data.items():
48
- if key in ["description", "summary"]:
49
- yaml_data[key] = self.convert_to_rst(value)
50
- continue
51
- self._convert_docstring_no_cycles(value, node_list)
52
-
53
- @staticmethod
54
- def convert_to_rst(string_to_convert: str) -> str:
55
- """Convert that string from MD to RST."""
56
- try:
57
- return m2r2.convert(string_to_convert, renderer=GeneratorRenderer()).strip()
58
- except Exception: # pylint: disable=broad-except
59
- return string_to_convert
60
-
61
-
62
- if __name__ == "__main__":
63
- # CADL pipeline will call this
64
- args, unknown_args = parse_args()
65
- M2R(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
@@ -1,65 +0,0 @@
1
- # -------------------------------------------------------------------------
2
- # Copyright (c) Microsoft Corporation. All rights reserved.
3
- # Licensed under the MIT License. See License.txt in the project root for
4
- # license information.
5
- # --------------------------------------------------------------------------
6
- """An MD to RST plugin.
7
- """
8
- import logging
9
- from typing import Any, Dict, Set, Union
10
-
11
- import m2r2
12
-
13
- from . import YamlUpdatePlugin
14
- from .utils import parse_args
15
-
16
-
17
- _LOGGER = logging.getLogger(__name__)
18
-
19
-
20
- class GeneratorRenderer(m2r2.RestRenderer):
21
- """Redefine the concept of inline HTML in the renderer, we don't want to define a new format
22
- in the description/summary.
23
- """
24
-
25
- def inline_html(self, html: str) -> str:
26
- """Do not render inline HTML with a role definition."""
27
- return r"\ :code:`{}`".format(html)
28
-
29
-
30
- class M2R(YamlUpdatePlugin):
31
- """A plugin to convert any description and summary from MD to RST."""
32
-
33
- def update_yaml(self, yaml_data: Dict[str, Any]) -> None:
34
- """Convert in place the YAML str."""
35
- self._convert_docstring_no_cycles(yaml_data, set())
36
-
37
- def _convert_docstring_no_cycles(self, yaml_data: Union[Dict[str, Any], str], node_list: Set[int]) -> None:
38
- """Walk the YAML tree to convert MD to RST."""
39
- if id(yaml_data) in node_list:
40
- return
41
- node_list.add(id(yaml_data))
42
-
43
- if isinstance(yaml_data, list):
44
- for elt in yaml_data:
45
- self._convert_docstring_no_cycles(elt, node_list)
46
- elif isinstance(yaml_data, dict):
47
- for key, value in yaml_data.items():
48
- if key in ["description", "summary"]:
49
- yaml_data[key] = self.convert_to_rst(value)
50
- continue
51
- self._convert_docstring_no_cycles(value, node_list)
52
-
53
- @staticmethod
54
- def convert_to_rst(string_to_convert: str) -> str:
55
- """Convert that string from MD to RST."""
56
- try:
57
- return m2r2.convert(string_to_convert, renderer=GeneratorRenderer()).strip()
58
- except Exception: # pylint: disable=broad-except
59
- return string_to_convert
60
-
61
-
62
- if __name__ == "__main__":
63
- # CADL pipeline will call this
64
- args, unknown_args = parse_args()
65
- M2R(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
@@ -1,10 +0,0 @@
1
- # ------------------------------------
2
- # Copyright (c) Microsoft Corporation.
3
- # Licensed under the MIT License.
4
- # ------------------------------------
5
- from pygen.m2r import M2R
6
-
7
-
8
- def test_inline_html():
9
- des = "Format: <MajorVersion>.<MinorVersion>.<Patch>"
10
- M2R.convert_to_rst(des) == r"Format: \ :code:`<MajorVersion>`.\ :code:`<MinorVersion>`.\ :code:`<Patch>`"