@typespec/http-client-python 0.7.0 → 0.8.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 (67) hide show
  1. package/dist/emitter/code-model.js +6 -6
  2. package/dist/emitter/code-model.js.map +1 -1
  3. package/dist/emitter/emitter.d.ts.map +1 -1
  4. package/dist/emitter/emitter.js +97 -59
  5. package/dist/emitter/emitter.js.map +1 -1
  6. package/dist/emitter/external-process.js +3 -3
  7. package/dist/emitter/external-process.js.map +1 -1
  8. package/dist/emitter/http.d.ts.map +1 -1
  9. package/dist/emitter/http.js +81 -23
  10. package/dist/emitter/http.js.map +1 -1
  11. package/dist/emitter/lib.d.ts +37 -1
  12. package/dist/emitter/lib.d.ts.map +1 -1
  13. package/dist/emitter/lib.js +24 -0
  14. package/dist/emitter/lib.js.map +1 -1
  15. package/dist/emitter/types.d.ts.map +1 -1
  16. package/dist/emitter/types.js +6 -4
  17. package/dist/emitter/types.js.map +1 -1
  18. package/dist/emitter/utils.d.ts +5 -2
  19. package/dist/emitter/utils.d.ts.map +1 -1
  20. package/dist/emitter/utils.js +99 -2
  21. package/dist/emitter/utils.js.map +1 -1
  22. package/emitter/src/code-model.ts +8 -8
  23. package/emitter/src/emitter.ts +101 -58
  24. package/emitter/src/external-process.ts +3 -3
  25. package/emitter/src/http.ts +113 -26
  26. package/emitter/src/lib.ts +24 -0
  27. package/emitter/src/types.ts +7 -4
  28. package/emitter/src/utils.ts +118 -1
  29. package/emitter/temp/tsconfig.tsbuildinfo +1 -1
  30. package/emitter/test/utils.test.ts +6 -1
  31. package/eng/scripts/setup/__pycache__/venvtools.cpython-38.pyc +0 -0
  32. package/eng/scripts/setup/run_tsp.py +4 -5
  33. package/generator/build/lib/pygen/__init__.py +3 -3
  34. package/generator/build/lib/pygen/black.py +2 -2
  35. package/generator/build/lib/pygen/codegen/__init__.py +5 -5
  36. package/generator/build/lib/pygen/codegen/models/paging_operation.py +11 -2
  37. package/generator/build/lib/pygen/codegen/models/parameter.py +2 -1
  38. package/generator/build/lib/pygen/codegen/models/request_builder_parameter.py +2 -0
  39. package/generator/build/lib/pygen/codegen/models/response.py +1 -1
  40. package/generator/build/lib/pygen/codegen/serializers/builder_serializer.py +47 -25
  41. package/generator/build/lib/pygen/preprocess/__init__.py +10 -12
  42. package/generator/build/lib/pygen/preprocess/python_mappings.py +1 -1
  43. package/generator/build/lib/pygen/utils.py +5 -5
  44. package/generator/component-detection-pip-report.json +7 -6
  45. package/generator/dist/pygen-0.1.0-py3-none-any.whl +0 -0
  46. package/generator/pygen/__init__.py +3 -3
  47. package/generator/pygen/black.py +2 -2
  48. package/generator/pygen/codegen/__init__.py +5 -5
  49. package/generator/pygen/codegen/models/paging_operation.py +11 -2
  50. package/generator/pygen/codegen/models/parameter.py +2 -1
  51. package/generator/pygen/codegen/models/request_builder_parameter.py +2 -0
  52. package/generator/pygen/codegen/models/response.py +1 -1
  53. package/generator/pygen/codegen/serializers/builder_serializer.py +47 -25
  54. package/generator/pygen/preprocess/__init__.py +10 -12
  55. package/generator/pygen/preprocess/python_mappings.py +1 -1
  56. package/generator/pygen/utils.py +5 -5
  57. package/generator/pygen.egg-info/PKG-INFO +0 -1
  58. package/generator/pygen.egg-info/SOURCES.txt +0 -1
  59. package/generator/pygen.egg-info/requires.txt +0 -1
  60. package/generator/setup.py +0 -1
  61. package/generator/test/generic_mock_api_tests/asynctests/test_payload_pageable_async.py +75 -0
  62. package/generator/test/generic_mock_api_tests/test_payload_pageable.py +54 -0
  63. package/package.json +2 -1
  64. package/generator/build/lib/pygen/m2r.py +0 -65
  65. package/generator/pygen/m2r.py +0 -65
  66. package/generator/test/generic_mock_api_tests/unittests/test_m2r.py +0 -10
  67. package/generator/test/unbranded/mock_api_tests/cadl-ranch-config.yaml +0 -27
@@ -630,7 +630,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
630
630
  operation_name=f"('{builder.name}')" if builder.group_name == "" else "",
631
631
  )
632
632
  for p in builder.parameters.parameters:
633
- if p.hide_in_operation_signature:
633
+ if p.hide_in_operation_signature and not p.is_continuation_token:
634
634
  kwargs.append(f'{p.client_name} = kwargs.pop("{p.client_name}", None)')
635
635
  cls_annotation = builder.cls_type_annotation(
636
636
  async_mode=self.async_mode, serialize_namespace=self.serialize_namespace
@@ -1001,9 +1001,7 @@ class _OperationSerializer(_BuilderBaseSerializer[OperationType]):
1001
1001
  retval.extend(deserialize_code)
1002
1002
  return retval
1003
1003
 
1004
- def handle_error_response( # pylint: disable=too-many-statements, too-many-branches
1005
- self, builder: OperationType
1006
- ) -> List[str]:
1004
+ def handle_error_response(self, builder: OperationType) -> List[str]:
1007
1005
  async_await = "await " if self.async_mode else ""
1008
1006
  retval = [f"if response.status_code not in {str(builder.success_status_codes)}:"]
1009
1007
  response_read = [
@@ -1290,16 +1288,20 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1290
1288
 
1291
1289
  def _prepare_request_callback(self, builder: PagingOperationType) -> List[str]:
1292
1290
  retval = self._initialize_overloads(builder)
1293
- retval.append("def prepare_request(next_link=None):")
1294
- retval.append(" if not next_link:")
1295
- retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])
1296
- retval.append("")
1297
- retval.append(" else:")
1298
- retval.extend([f" {line}" for line in self.call_next_link_request_builder(builder)])
1299
- if not builder.next_request_builder and self.code_model.is_legacy:
1300
- retval.append(' _request.method = "GET"')
1291
+ if builder.has_continuation_token:
1292
+ retval.append(f"def prepare_request({builder.next_variable_name}=None):")
1293
+ retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])
1301
1294
  else:
1295
+ retval.append("def prepare_request(next_link=None):")
1296
+ retval.append(" if not next_link:")
1297
+ retval.extend([f" {line}" for line in self.call_request_builder(builder, is_paging=True)])
1302
1298
  retval.append("")
1299
+ retval.append(" else:")
1300
+ retval.extend([f" {line}" for line in self.call_next_link_request_builder(builder)])
1301
+ if not builder.next_request_builder and self.code_model.is_legacy:
1302
+ retval.append(' _request.method = "GET"')
1303
+ else:
1304
+ retval.append("")
1303
1305
  retval.append(" return _request")
1304
1306
  return retval
1305
1307
 
@@ -1307,7 +1309,7 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1307
1309
  def _function_def(self) -> str:
1308
1310
  return "def"
1309
1311
 
1310
- def _extract_data_callback(self, builder: PagingOperationType) -> List[str]:
1312
+ def _extract_data_callback(self, builder: PagingOperationType) -> List[str]: # pylint: disable=too-many-statements
1311
1313
  retval = [f"{'async ' if self.async_mode else ''}def extract_data(pipeline_response):"]
1312
1314
  response = builder.responses[0]
1313
1315
  deserialized = "pipeline_response.http_response.json()"
@@ -1328,7 +1330,13 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1328
1330
  else:
1329
1331
  retval.append(f" deserialized = {deserialized}")
1330
1332
  item_name = builder.item_name
1331
- access = f".{item_name}" if self.code_model.options["models_mode"] == "msrest" else f'["{item_name}"]'
1333
+ if self.code_model.options["models_mode"] == "msrest":
1334
+ access = f".{item_name}"
1335
+ else:
1336
+ item_name_array = item_name.split(".")
1337
+ access = (
1338
+ "".join([f'.get("{i}", {{}})' for i in item_name_array[:-1]]) + f'.get("{item_name_array[-1]}", [])'
1339
+ )
1332
1340
  list_of_elem_deserialized = ""
1333
1341
  if self.code_model.options["models_mode"] == "dpg":
1334
1342
  item_type = builder.item_type.type_annotation(
@@ -1341,20 +1349,34 @@ class _PagingOperationSerializer(_OperationSerializer[PagingOperationType]):
1341
1349
  retval.append(" if cls:")
1342
1350
  retval.append(" list_of_elem = cls(list_of_elem) # type: ignore")
1343
1351
 
1344
- continuation_token_name = builder.continuation_token_name
1345
- if not continuation_token_name:
1346
- cont_token_property = "None"
1347
- elif self.code_model.options["models_mode"] == "msrest":
1348
- cont_token_property = f"deserialized.{continuation_token_name} or None"
1352
+ if builder.has_continuation_token:
1353
+ location = builder.continuation_token.get("output", {}).get("location")
1354
+ wire_name = builder.continuation_token.get("output", {}).get("wireName") or ""
1355
+ if location == "header":
1356
+ cont_token_property = f'pipeline_response.http_response.headers.get("{wire_name}") or None'
1357
+ else:
1358
+ wire_name_array = wire_name.split(".")
1359
+ wire_name_call = (
1360
+ "".join([f'.get("{i}", {{}})' for i in wire_name_array[:-1]]) + f'.get("{wire_name_array[-1]}")'
1361
+ )
1362
+ cont_token_property = f"deserialized{wire_name_call} or None"
1349
1363
  else:
1350
- cont_token_property = f'deserialized.get("{continuation_token_name}") or None'
1364
+ next_link_name = builder.next_link_name
1365
+ if not next_link_name:
1366
+ cont_token_property = "None"
1367
+ elif self.code_model.options["models_mode"] == "msrest":
1368
+ cont_token_property = f"deserialized.{next_link_name} or None"
1369
+ else:
1370
+ cont_token_property = f'deserialized.get("{next_link_name}") or None'
1351
1371
  list_type = "AsyncList" if self.async_mode else "iter"
1352
1372
  retval.append(f" return {cont_token_property}, {list_type}(list_of_elem)")
1353
1373
  return retval
1354
1374
 
1355
1375
  def _get_next_callback(self, builder: PagingOperationType) -> List[str]:
1356
- retval = [f"{'async ' if self.async_mode else ''}def get_next(next_link=None):"]
1357
- retval.append(" _request = prepare_request(next_link)")
1376
+ retval = [
1377
+ f"{'async ' if self.async_mode else ''}def get_next({builder.next_variable_name}=None):" # pylint: disable=line-too-long
1378
+ ]
1379
+ retval.append(f" _request = prepare_request({builder.next_variable_name})")
1358
1380
  retval.append("")
1359
1381
  retval.extend([f" {l}" for l in self.make_pipeline_call(builder)])
1360
1382
  retval.append(" response = pipeline_response.http_response")
@@ -1506,10 +1528,10 @@ class LROPagingOperationSerializer(
1506
1528
 
1507
1529
  def get_long_running_output(self, builder: LROPagingOperation) -> List[str]:
1508
1530
  retval = ["def get_long_running_output(pipeline_response):"]
1509
- retval.append(f" {self._function_def} internal_get_next(next_link=None):")
1510
- retval.append(" if next_link is None:")
1531
+ retval.append(f" {self._function_def} internal_get_next({builder.next_variable_name}=None):")
1532
+ retval.append(f" if {builder.next_variable_name} is None:")
1511
1533
  retval.append(" return pipeline_response")
1512
- retval.append(f" return {self._call_method}get_next(next_link)")
1534
+ retval.append(f" return {self._call_method}get_next({builder.next_variable_name})")
1513
1535
  retval.append("")
1514
1536
  retval.append(f" return {builder.get_pager(self.async_mode)}(")
1515
1537
  retval.append(" internal_get_next, extract_data")
@@ -14,7 +14,7 @@ from .helpers import (
14
14
  pad_builtin_namespaces,
15
15
  pad_special_chars,
16
16
  )
17
- from .python_mappings import CADL_RESERVED_WORDS, RESERVED_WORDS, PadType
17
+ from .python_mappings import TSP_RESERVED_WORDS, RESERVED_WORDS, PadType
18
18
 
19
19
  from .. import YamlUpdatePlugin
20
20
  from ..utils import (
@@ -182,11 +182,11 @@ class PreProcessPlugin(YamlUpdatePlugin):
182
182
 
183
183
  @property
184
184
  def models_mode(self) -> Optional[str]:
185
- return self.options.get("models-mode", "dpg" if self.is_cadl else None)
185
+ return self.options.get("models-mode", "dpg" if self.is_tsp else None)
186
186
 
187
187
  @property
188
- def is_cadl(self) -> bool:
189
- return self.options.get("cadl_file", False)
188
+ def is_tsp(self) -> bool:
189
+ return self.options.get("tsp_file", False)
190
190
 
191
191
  def add_body_param_type(
192
192
  self,
@@ -197,9 +197,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
197
197
  if ( # pylint: disable=too-many-boolean-expressions
198
198
  body_parameter
199
199
  and body_parameter["type"]["type"] in ("model", "dict", "list")
200
- and (
201
- has_json_content_type(body_parameter) or (self.is_cadl and has_multi_part_content_type(body_parameter))
202
- )
200
+ and (has_json_content_type(body_parameter) or (self.is_tsp and has_multi_part_content_type(body_parameter)))
203
201
  and not body_parameter["type"].get("xmlMetadata")
204
202
  and not any(t for t in ["flattened", "groupedBy"] if body_parameter.get(t))
205
203
  ):
@@ -210,7 +208,7 @@ class PreProcessPlugin(YamlUpdatePlugin):
210
208
  "types": [body_parameter["type"]],
211
209
  }
212
210
  # don't add binary overload for multipart content type
213
- if not (self.is_cadl and has_multi_part_content_type(body_parameter)):
211
+ if not (self.is_tsp and has_multi_part_content_type(body_parameter)):
214
212
  body_parameter["type"]["types"].append(KNOWN_TYPES["binary"])
215
213
 
216
214
  if origin_type == "model" and is_dpg_model and self.models_mode == "dpg":
@@ -223,8 +221,8 @@ class PreProcessPlugin(YamlUpdatePlugin):
223
221
  # we'll pass in empty operation groups sometime etc.
224
222
  return name
225
223
 
226
- if self.is_cadl:
227
- reserved_words = {k: (v + CADL_RESERVED_WORDS.get(k, [])) for k, v in RESERVED_WORDS.items()}
224
+ if self.is_tsp:
225
+ reserved_words = {k: (v + TSP_RESERVED_WORDS.get(k, [])) for k, v in RESERVED_WORDS.items()}
228
226
  else:
229
227
  reserved_words = RESERVED_WORDS
230
228
  name = pad_special_chars(name)
@@ -506,6 +504,6 @@ class PreProcessPlugin(YamlUpdatePlugin):
506
504
 
507
505
 
508
506
  if __name__ == "__main__":
509
- # CADL pipeline will call this
507
+ # TSP pipeline will call this
510
508
  args, unknown_args = parse_args()
511
- PreProcessPlugin(output_folder=args.output_folder, cadl_file=args.cadl_file, **unknown_args).process()
509
+ PreProcessPlugin(output_folder=args.output_folder, tsp_file=args.tsp_file, **unknown_args).process()
@@ -185,7 +185,7 @@ RESERVED_WORDS = {
185
185
  PadType.OPERATION_GROUP: [*_always_reserved],
186
186
  }
187
187
 
188
- CADL_RESERVED_WORDS = {
188
+ TSP_RESERVED_WORDS = {
189
189
  PadType.PARAMETER: ["stream"],
190
190
  PadType.PROPERTY: RESERVED_MODEL_PROPERTIES,
191
191
  }
@@ -44,7 +44,7 @@ def to_snake_case(name: str) -> str:
44
44
 
45
45
 
46
46
  def parse_args(
47
- need_cadl_file: bool = True,
47
+ need_tsp_file: bool = True,
48
48
  ) -> Tuple[argparse.Namespace, Dict[str, Any]]:
49
49
  parser = argparse.ArgumentParser(
50
50
  description="Run mypy against target folder. Add a local custom plugin to the path prior to execution. "
@@ -56,10 +56,10 @@ def parse_args(
56
56
  required=True,
57
57
  )
58
58
  parser.add_argument(
59
- "--cadl-file",
60
- dest="cadl_file",
61
- help="Serialized cadl file",
62
- required=need_cadl_file,
59
+ "--tsp-file",
60
+ dest="tsp_file",
61
+ help="Serialized tsp file",
62
+ required=need_tsp_file,
63
63
  )
64
64
  parser.add_argument(
65
65
  "--debug",
@@ -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",
@@ -0,0 +1,75 @@
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
+ import pytest
7
+ from payload.pageable.aio import PageableClient
8
+
9
+
10
+ @pytest.fixture
11
+ async def client():
12
+ async with PageableClient(endpoint="http://localhost:3000") as client:
13
+ yield client
14
+
15
+
16
+ def assert_result(result):
17
+ assert len(result) == 4
18
+ assert result[0].id == "1"
19
+ assert result[1].id == "2"
20
+ assert result[2].id == "3"
21
+ assert result[3].id == "4"
22
+ assert result[0].name == "dog"
23
+ assert result[1].name == "cat"
24
+ assert result[2].name == "bird"
25
+ assert result[3].name == "fish"
26
+
27
+
28
+ @pytest.mark.asyncio
29
+ async def test_link(client: PageableClient):
30
+ result = [p async for p in client.server_driven_pagination.link()]
31
+ assert_result(result)
32
+
33
+
34
+ @pytest.mark.asyncio
35
+ async def test_request_query_response_body(client: PageableClient):
36
+ result = [
37
+ p
38
+ async for p in client.server_driven_pagination.continuation_token.request_query_response_body(
39
+ foo="foo", bar="bar"
40
+ )
41
+ ]
42
+ assert_result(result)
43
+
44
+
45
+ @pytest.mark.asyncio
46
+ async def test_request_header_response_body(client: PageableClient):
47
+ result = [
48
+ p
49
+ async for p in client.server_driven_pagination.continuation_token.request_header_response_body(
50
+ foo="foo", bar="bar"
51
+ )
52
+ ]
53
+ assert_result(result)
54
+
55
+
56
+ @pytest.mark.asyncio
57
+ async def test_request_query_response_header(client: PageableClient):
58
+ result = [
59
+ p
60
+ async for p in client.server_driven_pagination.continuation_token.request_query_response_header(
61
+ foo="foo", bar="bar"
62
+ )
63
+ ]
64
+ assert_result(result)
65
+
66
+
67
+ @pytest.mark.asyncio
68
+ async def test_request_header_response_header(client: PageableClient):
69
+ result = [
70
+ p
71
+ async for p in client.server_driven_pagination.continuation_token.request_query_response_header(
72
+ foo="foo", bar="bar"
73
+ )
74
+ ]
75
+ assert_result(result)
@@ -0,0 +1,54 @@
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
+ import pytest
7
+ from payload.pageable import PageableClient
8
+
9
+
10
+ @pytest.fixture
11
+ def client():
12
+ with PageableClient(endpoint="http://localhost:3000") as client:
13
+ yield client
14
+
15
+
16
+ def assert_result(result):
17
+ assert len(result) == 4
18
+ assert result[0].id == "1"
19
+ assert result[1].id == "2"
20
+ assert result[2].id == "3"
21
+ assert result[3].id == "4"
22
+ assert result[0].name == "dog"
23
+ assert result[1].name == "cat"
24
+ assert result[2].name == "bird"
25
+ assert result[3].name == "fish"
26
+
27
+
28
+ def test_link(client: PageableClient):
29
+ result = list(client.server_driven_pagination.link())
30
+ assert_result(result)
31
+
32
+
33
+ def test_request_query_response_body(client: PageableClient):
34
+ result = list(client.server_driven_pagination.continuation_token.request_query_response_body(foo="foo", bar="bar"))
35
+ assert_result(result)
36
+
37
+
38
+ def test_request_header_response_body(client: PageableClient):
39
+ result = list(client.server_driven_pagination.continuation_token.request_header_response_body(foo="foo", bar="bar"))
40
+ assert_result(result)
41
+
42
+
43
+ def test_request_query_response_header(client: PageableClient):
44
+ result = list(
45
+ client.server_driven_pagination.continuation_token.request_query_response_header(foo="foo", bar="bar")
46
+ )
47
+ assert_result(result)
48
+
49
+
50
+ def test_request_header_response_header(client: PageableClient):
51
+ result = list(
52
+ client.server_driven_pagination.continuation_token.request_header_response_header(foo="foo", bar="bar")
53
+ )
54
+ assert_result(result)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http-client-python",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec emitter for Python SDKs",
6
6
  "homepage": "https://typespec.io",
@@ -66,6 +66,7 @@
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"
@@ -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>`"
@@ -1,27 +0,0 @@
1
- unsupportedScenarios: Azure_ClientGenerator_Core_Access_InternalOperation
2
- Azure_ClientGenerator_Core_Access_PublicOperation
3
- Azure_ClientGenerator_Core_Access_RelativeModelInOperation
4
- Azure_ClientGenerator_Core_Access_SharedModelInOperation
5
- Azure_ClientGenerator_Core_Usage_ModelInOperation
6
- Azure_Core_Basic_createOrReplace
7
- Azure_Core_Basic_createOrUpdate
8
- Azure_Core_Basic_delete
9
- Azure_Core_Basic_export
10
- Azure_Core_Basic_get
11
- Azure_Core_Basic_list
12
- Azure_Core_Basic_listWithCustomPageModel
13
- Azure_Core_Basic_listWithPage
14
- Azure_Core_Basic_listWithParameters
15
- Azure_Core_Basic_TwoModelsAsPageItem
16
- Azure_Core_Lro_Rpc_longRunningRpc
17
- Azure_Core_Lro_Standard_createOrReplace
18
- Azure_Core_Lro_Standard_delete
19
- Azure_Core_Lro_Standard_export
20
- Azure_Core_Scalar_AzureLocationScalar_get
21
- Azure_Core_Scalar_AzureLocationScalar_header
22
- Azure_Core_Scalar_AzureLocationScalar_post
23
- Azure_Core_Scalar_AzureLocationScalar_put
24
- Azure_Core_Scalar_AzureLocationScalar_query
25
- Azure_Core_Traits_repeatableAction
26
- Azure_Core_Traits_smokeTest
27
- Azure_SpecialHeaders_XmsClientRequestId