@autorest/python 5.14.0 → 5.17.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 (120) hide show
  1. package/ChangeLog.md +91 -2
  2. package/README.md +30 -4
  3. package/autorest/__init__.py +2 -3
  4. package/autorest/black/__init__.py +12 -5
  5. package/autorest/codegen/__init__.py +130 -179
  6. package/autorest/codegen/models/__init__.py +122 -78
  7. package/autorest/codegen/models/base_builder.py +70 -72
  8. package/autorest/codegen/models/base_model.py +7 -5
  9. package/autorest/codegen/models/{base_schema.py → base_type.py} +62 -49
  10. package/autorest/codegen/models/client.py +195 -36
  11. package/autorest/codegen/models/code_model.py +165 -299
  12. package/autorest/codegen/models/combined_type.py +107 -0
  13. package/autorest/codegen/models/constant_type.py +122 -0
  14. package/autorest/codegen/models/credential_types.py +224 -0
  15. package/autorest/codegen/models/dictionary_type.py +116 -0
  16. package/autorest/codegen/models/enum_type.py +195 -0
  17. package/autorest/codegen/models/imports.py +95 -41
  18. package/autorest/codegen/models/list_type.py +134 -0
  19. package/autorest/codegen/models/lro_operation.py +90 -133
  20. package/autorest/codegen/models/lro_paging_operation.py +28 -12
  21. package/autorest/codegen/models/model_type.py +239 -0
  22. package/autorest/codegen/models/operation.py +415 -241
  23. package/autorest/codegen/models/operation_group.py +82 -88
  24. package/autorest/codegen/models/paging_operation.py +101 -117
  25. package/autorest/codegen/models/parameter.py +307 -322
  26. package/autorest/codegen/models/parameter_list.py +366 -357
  27. package/autorest/codegen/models/primitive_types.py +544 -0
  28. package/autorest/codegen/models/property.py +122 -134
  29. package/autorest/codegen/models/request_builder.py +138 -86
  30. package/autorest/codegen/models/request_builder_parameter.py +122 -79
  31. package/autorest/codegen/models/response.py +325 -0
  32. package/autorest/codegen/models/utils.py +17 -1
  33. package/autorest/codegen/serializers/__init__.py +242 -118
  34. package/autorest/codegen/serializers/builder_serializer.py +863 -1027
  35. package/autorest/codegen/serializers/client_serializer.py +148 -82
  36. package/autorest/codegen/serializers/general_serializer.py +44 -47
  37. package/autorest/codegen/serializers/import_serializer.py +96 -31
  38. package/autorest/codegen/serializers/metadata_serializer.py +39 -79
  39. package/autorest/codegen/serializers/model_base_serializer.py +65 -29
  40. package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
  41. package/autorest/codegen/serializers/model_init_serializer.py +4 -2
  42. package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
  43. package/autorest/codegen/serializers/operation_groups_serializer.py +21 -18
  44. package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
  45. package/autorest/codegen/serializers/parameter_serializer.py +174 -0
  46. package/autorest/codegen/serializers/patch_serializer.py +14 -2
  47. package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
  48. package/autorest/codegen/serializers/utils.py +0 -103
  49. package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
  50. package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
  51. package/autorest/codegen/templates/config.py.jinja2 +13 -13
  52. package/autorest/codegen/templates/enum.py.jinja2 +4 -4
  53. package/autorest/codegen/templates/enum_container.py.jinja2 +1 -2
  54. package/autorest/codegen/templates/init.py.jinja2 +9 -6
  55. package/autorest/codegen/templates/keywords.jinja2 +14 -1
  56. package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
  57. package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
  58. package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
  59. package/autorest/codegen/templates/model.py.jinja2 +23 -29
  60. package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
  61. package/autorest/codegen/templates/model_init.py.jinja2 +9 -8
  62. package/autorest/codegen/templates/operation.py.jinja2 +10 -15
  63. package/autorest/codegen/templates/operation_group.py.jinja2 +14 -13
  64. package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -2
  65. package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
  66. package/autorest/codegen/templates/operations_folder_init.py.jinja2 +4 -0
  67. package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
  68. package/autorest/codegen/templates/patch.py.jinja2 +18 -29
  69. package/autorest/codegen/templates/request_builder.py.jinja2 +20 -13
  70. package/autorest/codegen/templates/setup.py.jinja2 +9 -3
  71. package/autorest/codegen/templates/vendor.py.jinja2 +12 -2
  72. package/autorest/jsonrpc/__init__.py +7 -12
  73. package/autorest/jsonrpc/localapi.py +4 -3
  74. package/autorest/jsonrpc/server.py +28 -9
  75. package/autorest/jsonrpc/stdstream.py +13 -6
  76. package/autorest/m2r/__init__.py +5 -8
  77. package/autorest/m4reformatter/__init__.py +1108 -0
  78. package/autorest/multiapi/__init__.py +24 -14
  79. package/autorest/multiapi/models/client.py +21 -11
  80. package/autorest/multiapi/models/code_model.py +23 -10
  81. package/autorest/multiapi/models/config.py +4 -1
  82. package/autorest/multiapi/models/constant_global_parameter.py +1 -0
  83. package/autorest/multiapi/models/global_parameter.py +2 -1
  84. package/autorest/multiapi/models/global_parameters.py +14 -8
  85. package/autorest/multiapi/models/imports.py +35 -18
  86. package/autorest/multiapi/models/mixin_operation.py +5 -5
  87. package/autorest/multiapi/models/operation_group.py +2 -1
  88. package/autorest/multiapi/models/operation_mixin_group.py +21 -10
  89. package/autorest/multiapi/serializers/__init__.py +20 -25
  90. package/autorest/multiapi/serializers/import_serializer.py +47 -15
  91. package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
  92. package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
  93. package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
  94. package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
  95. package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
  96. package/autorest/multiapi/utils.py +3 -3
  97. package/autorest/postprocess/__init__.py +202 -0
  98. package/autorest/postprocess/get_all.py +19 -0
  99. package/autorest/postprocess/venvtools.py +73 -0
  100. package/autorest/preprocess/__init__.py +209 -0
  101. package/autorest/preprocess/helpers.py +54 -0
  102. package/autorest/{namer → preprocess}/python_mappings.py +25 -32
  103. package/package.json +3 -3
  104. package/run-python3.js +2 -3
  105. package/venvtools.py +1 -1
  106. package/autorest/codegen/models/constant_schema.py +0 -97
  107. package/autorest/codegen/models/credential_schema.py +0 -90
  108. package/autorest/codegen/models/credential_schema_policy.py +0 -77
  109. package/autorest/codegen/models/dictionary_schema.py +0 -103
  110. package/autorest/codegen/models/enum_schema.py +0 -246
  111. package/autorest/codegen/models/list_schema.py +0 -113
  112. package/autorest/codegen/models/object_schema.py +0 -249
  113. package/autorest/codegen/models/primitive_schemas.py +0 -476
  114. package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
  115. package/autorest/codegen/models/rest.py +0 -42
  116. package/autorest/codegen/models/schema_request.py +0 -45
  117. package/autorest/codegen/models/schema_response.py +0 -123
  118. package/autorest/codegen/serializers/rest_serializer.py +0 -57
  119. package/autorest/namer/__init__.py +0 -25
  120. package/autorest/namer/name_converter.py +0 -412
@@ -1,412 +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
- import re
7
- import copy
8
- from typing import cast, Any, Dict, List, Match, Optional
9
- from .python_mappings import basic_latin_chars, reserved_words, PadType
10
- from ..codegen.models.utils import JSON_REGEXP
11
-
12
- def _get_all_values(all_headers: List[Dict[str, Any]]) -> List[str]:
13
- content_types: List[str] = []
14
- for h in all_headers:
15
- if h['schema']['type'] == 'constant':
16
- content_types.append(h['schema']['value']['value'])
17
- elif any(
18
- choice_type for choice_type in ['sealed-choice', 'choice']
19
- if h['schema']['type'] == choice_type
20
- ):
21
- content_types.extend([
22
- choice['value']
23
- for choice in h['schema']['choices']
24
- ])
25
- return content_types
26
-
27
- def _get_default_value(all_values: List[str]) -> str:
28
- json_values = [v for v in all_values if JSON_REGEXP.match(v)]
29
- if json_values:
30
- if "application/json" in json_values:
31
- return "application/json"
32
- return json_values[0]
33
-
34
- xml_values = [v for v in all_values if "xml" in v]
35
- if xml_values:
36
- if "application/xml" in xml_values:
37
- return "application/xml"
38
- return xml_values[0]
39
- return all_values[0]
40
-
41
- _M4_HEADER_PARAMETERS = ["content_type", "accept"]
42
- class NameConverter:
43
- @staticmethod
44
- def convert_yaml_names(yaml_data: Dict[str, Any]) -> None:
45
- NameConverter._convert_language_default_python_case(yaml_data)
46
- yaml_data["info"]["python_title"] = NameConverter._to_valid_python_name(
47
- name=yaml_data["info"]["title"].replace(" ", ""), convert_name=True
48
- )
49
- yaml_data['info']['pascal_case_title'] = yaml_data["language"]["default"]["name"]
50
- if yaml_data['info'].get("description"):
51
- if yaml_data["info"]["description"][-1] != ".":
52
- yaml_data["info"]["description"] += "."
53
- else:
54
- yaml_data["info"]["description"] = yaml_data['info']['pascal_case_title'] + "."
55
- NameConverter._convert_schemas(yaml_data['schemas'])
56
- NameConverter._convert_operation_groups(yaml_data['operationGroups'], yaml_data['info']['pascal_case_title'])
57
- if yaml_data.get('globalParameters'):
58
- NameConverter._convert_global_parameters(yaml_data['globalParameters'])
59
-
60
- @staticmethod
61
- def _convert_global_parameters(global_parameters: List[Dict[str, Any]]) -> None:
62
- for global_parameter in global_parameters:
63
- NameConverter._convert_language_default_python_case(global_parameter)
64
-
65
- @staticmethod
66
- def _convert_operation_groups(operation_groups: List[Dict[str, Any]], code_model_title: str) -> None:
67
- for operation_group in operation_groups:
68
- builder_group = copy.deepcopy(operation_group)
69
- NameConverter._convert_language_default_python_case(
70
- operation_group, pad_string=PadType.OperationGroup, convert_name=True
71
- )
72
- operation_group_name = operation_group['language']['default']['name']
73
- if not operation_group_name:
74
- operation_group['language']['python']['className'] = code_model_title + "OperationsMixin"
75
- operation_group['language']['python']['name'] = ""
76
- elif operation_group_name == 'Operations':
77
- operation_group['language']['python']['className'] = operation_group_name
78
- else:
79
- operation_group['language']['python']['className'] = operation_group_name + "Operations"
80
- for operation in operation_group['operations']:
81
- NameConverter._convert_language_default_python_case(operation, pad_string=PadType.Method)
82
- if operation_group_name:
83
- operation['language']['python']['operationGroupName'] = (
84
- operation_group['language']['python']['name'].lower()
85
- )
86
- NameConverter._convert_language_default_python_case(
87
- builder_group, pad_string=PadType.BuilderGroup, convert_name=True
88
- )
89
- operation['language']['python']['builderGroupName'] = (
90
- builder_group['language']['python']['name'].lower()
91
- )
92
- else:
93
- operation['language']['python']['operationGroupName'] = ""
94
- operation['language']['python']['builderGroupName'] = ""
95
- for exception in operation.get('exceptions', []):
96
- NameConverter._convert_language_default_python_case(exception)
97
- for parameter in operation.get("parameters", []):
98
- NameConverter._add_multipart_information(parameter, operation)
99
- NameConverter._convert_language_default_python_case(parameter, pad_string=PadType.Parameter)
100
- for request in operation.get("requests", []):
101
- NameConverter._convert_language_default_python_case(request)
102
- for parameter in request.get("parameters", []):
103
- NameConverter._add_multipart_information(parameter, request)
104
- NameConverter._convert_language_default_python_case(parameter, pad_string=PadType.Parameter)
105
- if parameter.get("origin", "") == "modelerfour:synthesized/content-type":
106
- parameter["required"] = False
107
- NameConverter._handle_m4_header_parameters(operation.get("requests", []))
108
- for response in operation.get("responses", []):
109
- NameConverter._convert_language_default_python_case(response)
110
- if operation.get("extensions"):
111
- NameConverter._convert_extensions(operation)
112
-
113
- @staticmethod
114
- def _handle_m4_header_parameters(requests):
115
- m4_header_params = []
116
- for request in requests:
117
- m4_header_params.extend([
118
- p for p in request.get('parameters', [])
119
- if NameConverter._is_schema_an_m4_header_parameter(p['language']['default']['name'], p)
120
- ])
121
- m4_header_params_to_remove = []
122
- for m4_header in _M4_HEADER_PARAMETERS:
123
- params_of_header = [
124
- p for p in m4_header_params
125
- if p['language']['default']['name'] == m4_header
126
- ]
127
- if len(params_of_header) < 2:
128
- continue
129
- param_schema_to_param = { # if they share the same schema, we don't need to keep both of them in this case
130
- id(param['schema']): param
131
- for param in params_of_header
132
- }
133
- if len(param_schema_to_param) == 1:
134
- # we'll remove the ones that aren't the first
135
- m4_header_params_to_remove.extend([
136
- id(p) for p in params_of_header[1:]
137
- ])
138
- else:
139
- all_values = _get_all_values(params_of_header)
140
- # if one of them is an enum schema, set the default value to constant
141
- param_with_constant_schema = next(p for p in params_of_header if p['schema']['type'] == 'constant')
142
- try:
143
- param_with_enum_schema = next(
144
- p for p in params_of_header
145
- if p['schema']['type'] == 'sealed-choice' or p['schema']['type'] == 'choice'
146
- )
147
- except StopIteration:
148
- # this means there's no enum schema
149
- pass
150
- else:
151
- param_with_enum_schema['clientDefaultValue'] = _get_default_value(all_values)
152
- # add constant enum schema value into list of possible schema values
153
- constant_schema = param_with_constant_schema['schema']
154
- constant_choice = {
155
- "language": {
156
- "default": {
157
- "description": constant_schema['language']['default']['description'],
158
- "name": constant_schema['language']['default']['name'],
159
- },
160
- "python": {
161
- "description": constant_schema['language']['python']['description'],
162
- "name": constant_schema['language']['python']['name'].upper(),
163
- }
164
- },
165
- "value": constant_schema['value']['value']
166
- }
167
- param_with_enum_schema['schema']['choices'].append(constant_choice)
168
- m4_header_params_to_remove.append(id(param_with_constant_schema))
169
-
170
- for request in requests:
171
- if not request.get('parameters'):
172
- continue
173
- request['parameters'] = [p for p in request['parameters'] if id(p) not in m4_header_params_to_remove]
174
-
175
-
176
- @staticmethod
177
- def _add_multipart_information(parameter: Dict[str, Any], request: Dict[str, Any]):
178
- multipart = request["protocol"].get("http", {}).get("multipart", False)
179
- if multipart:
180
- if parameter["protocol"]["http"]["in"] == "body":
181
- parameter["language"]["default"]["multipart"] = True
182
- if parameter["language"]["default"]["serializedName"] == "Content-Type":
183
- parameter['schema']['value']['value'] = None
184
-
185
-
186
- @staticmethod
187
- def _convert_extensions(operation: Dict[str, Any]) -> None:
188
- operation_extensions = operation["extensions"]
189
- if operation_extensions.get('x-ms-pageable'):
190
- operation["extensions"]["pager-sync"] = operation_extensions.get(
191
- "x-python-custom-pager-sync", "azure.core.paging.ItemPaged"
192
- )
193
- operation["extensions"]["pager-async"] = operation_extensions.get(
194
- "x-python-custom-pager-async", "azure.core.async_paging.AsyncItemPaged"
195
- )
196
- if operation_extensions.get("x-ms-long-running-operation"):
197
- # poller
198
- operation["extensions"]["poller-sync"] = operation_extensions.get(
199
- "x-python-custom-poller-sync", "azure.core.polling.LROPoller"
200
- )
201
- operation["extensions"]["poller-async"] = operation_extensions.get(
202
- "x-python-custom-poller-async", "azure.core.polling.AsyncLROPoller"
203
- )
204
-
205
- # polling methods
206
- sync_polling_method_directive = "x-python-custom-default-polling-method-sync"
207
- operation["extensions"]["default-polling-method-sync"] = {
208
- "azure-arm": operation_extensions.get(
209
- sync_polling_method_directive, "azure.mgmt.core.polling.arm_polling.ARMPolling"
210
- ),
211
- "data-plane": operation_extensions.get(
212
- sync_polling_method_directive, "azure.core.polling.base_polling.LROBasePolling"
213
- ),
214
- }
215
- async_polling_method_directive = "x-python-custom-default-polling-method-async"
216
- operation["extensions"]["default-polling-method-async"] = {
217
- "azure-arm": operation_extensions.get(
218
- async_polling_method_directive, "azure.mgmt.core.polling.async_arm_polling.AsyncARMPolling"
219
- ),
220
- "data-plane": operation_extensions.get(
221
- async_polling_method_directive, "azure.core.polling.async_base_polling.AsyncLROBasePolling"
222
- ),
223
- }
224
-
225
- operation["extensions"]["default-no-polling-method-sync"] = "azure.core.polling.NoPolling"
226
- operation["extensions"]["default-no-polling-method-async"] = "azure.core.polling.AsyncNoPolling"
227
- operation["extensions"]["base-polling-method-sync"] = "azure.core.polling.PollingMethod"
228
- operation["extensions"]["base-polling-method-async"] = "azure.core.polling.AsyncPollingMethod"
229
-
230
- @staticmethod
231
- def _convert_schemas(schemas: Dict[str, Any]) -> None:
232
- for enum in schemas.get("sealedChoices", []) + schemas.get("choices", []):
233
- NameConverter._convert_enum_schema(enum)
234
- for obj in schemas.get("objects", []) + schemas.get("groups", []):
235
- NameConverter._convert_object_schema(obj)
236
- for type_list, schema_yamls in schemas.items():
237
- for schema in schema_yamls:
238
- if type_list == "objects":
239
- continue
240
- if type_list in ["arrays", "dictionaries"]:
241
- NameConverter._convert_language_default_python_case(schema)
242
- NameConverter._convert_language_default_python_case(schema["elementType"])
243
- elif type_list == "constants":
244
- NameConverter._convert_language_default_python_case(schema)
245
- NameConverter._convert_language_default_python_case(schema["value"])
246
- NameConverter._convert_language_default_python_case(schema["valueType"])
247
- else:
248
- NameConverter._convert_language_default_python_case(schema)
249
-
250
- @staticmethod
251
- def _convert_enum_schema(schema: Dict[str, Any]) -> None:
252
- NameConverter._convert_language_default_pascal_case(schema)
253
- for choice in schema["choices"]:
254
- NameConverter._convert_language_default_python_case(choice, pad_string=PadType.Enum, all_upper=True)
255
-
256
- @staticmethod
257
- def _convert_object_schema(schema: Dict[str, Any]) -> None:
258
- NameConverter._convert_language_default_pascal_case(schema)
259
- schema_description = schema["language"]["python"]["description"]
260
- if not schema_description:
261
- # what is being used for empty ObjectSchema descriptions
262
- schema_description = schema["language"]["python"]["name"]
263
- if schema_description and schema_description[-1] != ".":
264
- schema_description += "."
265
- schema["language"]["python"]["description"] = schema_description
266
- for prop in schema.get("properties", []):
267
- NameConverter._convert_language_default_python_case(schema=prop, pad_string=PadType.Property)
268
-
269
- @staticmethod
270
- def _is_schema_an_m4_header_parameter(schema_name: str, schema: Dict[str, Any]) -> bool:
271
- return (
272
- schema_name in _M4_HEADER_PARAMETERS and
273
- schema.get('protocol', {}).get('http', {}).get('in', {}) == 'header'
274
- )
275
-
276
- @staticmethod
277
- def _convert_language_default_python_case(
278
- schema: Dict[str, Any],
279
- *,
280
- pad_string: Optional[PadType] = None,
281
- convert_name: bool = False,
282
- all_upper: bool = False
283
- ) -> None:
284
- if not schema.get("language") or schema["language"].get("python"):
285
- return
286
- schema['language']['python'] = dict(schema['language']['default'])
287
- schema_name = schema['language']['default']['name']
288
- schema_python_name = schema['language']['python']['name']
289
-
290
- if not NameConverter._is_schema_an_m4_header_parameter(
291
- schema_name, schema
292
- ):
293
- # only escaping name if it's not a content_type header parameter
294
- schema_python_name = NameConverter._to_valid_python_name(
295
- name=schema_name, pad_string=pad_string, convert_name=convert_name
296
- )
297
- # need to add the lower in case certain words, like LRO, are overriden to
298
- # always return LRO. Without .lower(), for example, begin_lro would be
299
- # begin_LRO
300
- schema['language']['python']['name'] = (
301
- schema_python_name.upper() if all_upper else schema_python_name.lower()
302
- )
303
-
304
- schema_description = schema["language"]["default"]["description"].strip()
305
- if pad_string == PadType.Method and not schema_description and not schema["language"]["default"].get("summary"):
306
- schema_description = schema["language"]["python"]["name"]
307
- if schema_description and schema_description[-1] != ".":
308
- schema_description += "."
309
- schema["language"]["python"]["description"] = schema_description
310
-
311
- schema_summary = schema["language"]["python"].get("summary")
312
- if schema_summary:
313
- schema_summary = schema_summary.strip()
314
- if schema_summary[-1] != ".":
315
- schema_summary += "."
316
- schema["language"]["python"]["summary"] = schema_summary
317
-
318
- @staticmethod
319
- def _convert_language_default_pascal_case(schema: Dict[str, Any]) -> None:
320
- if schema["language"].get("python"):
321
- return
322
- schema['language']['python'] = dict(schema['language']['default'])
323
-
324
- schema_description = schema["language"]["default"]["description"].strip()
325
-
326
- schema["language"]["python"]["description"] = schema_description
327
-
328
- @staticmethod
329
- def _to_pascal_case(name: str) -> str:
330
- name_list = re.split("[^a-zA-Z\\d]", name)
331
- name_list = [s[0].upper() + s[1:] if len(s) > 1 else s.upper() for s in name_list]
332
- return "".join(name_list)
333
-
334
- @staticmethod
335
- def _to_valid_python_name(name: str, *, pad_string: Optional[PadType] = None, convert_name: bool = False) -> str:
336
- if not name:
337
- return NameConverter._to_python_case(pad_string.value if pad_string else "")
338
- escaped_name = NameConverter._get_escaped_reserved_name(
339
- NameConverter._to_valid_name(name.replace("-", "_"), ["_"]), pad_string
340
- )
341
- if convert_name or name != escaped_name:
342
- return NameConverter._to_python_case(escaped_name)
343
- return escaped_name
344
-
345
- @staticmethod
346
- def _to_python_case(name: str) -> str:
347
- def replace_upper_characters(m: Match[str]) -> str:
348
- match_str = m.group().lower()
349
- if m.start() > 0 and name[m.start() - 1] == "_":
350
- # we are good if a '_' already exists
351
- return match_str
352
- # the first letter should not have _
353
- prefix = "_" if m.start() > 0 else ""
354
-
355
- # we will add an extra _ if there are multiple upper case chars together
356
- next_non_upper_case_char_location = m.start() + len(match_str)
357
- if (
358
- len(match_str) > 2
359
- and len(name) - next_non_upper_case_char_location > 1
360
- and name[next_non_upper_case_char_location].isalpha()
361
- ):
362
-
363
- return prefix + match_str[: len(match_str) - 1] + "_" + match_str[len(match_str) - 1]
364
-
365
- return prefix + match_str
366
- return re.sub("[A-Z]+", replace_upper_characters, name)
367
-
368
- @staticmethod
369
- def _get_escaped_reserved_name(name: str, pad_string: Optional[PadType] = None) -> str:
370
- if name is None:
371
- raise ValueError("The value for name can not be None")
372
- try:
373
- # check to see if name is reserved for the type of name we are converting
374
- pad_string = cast(PadType, pad_string)
375
- # there are some private variables, such as grouped parameters
376
- # that are private. We still want to escape them for DPG
377
- name_prefix = ""
378
- if name[0] == "_":
379
- # i am private
380
- name_prefix = "_"
381
- name = name[1:]
382
- if pad_string and name.lower() in reserved_words[pad_string]:
383
- name += pad_string.value
384
- return name_prefix + name
385
- except AttributeError:
386
- raise ValueError(f"The name {name} is a reserved word and you have not specified a pad string for it.")
387
-
388
- @staticmethod
389
- def _remove_invalid_characters(name: str, allowed_characters: List[str]) -> str:
390
- name = name.replace("[]", "Sequence")
391
- valid_string = "".join([n for n in name if n.isalpha() or n.isdigit() or n in allowed_characters])
392
- return valid_string
393
-
394
- @staticmethod
395
- def _to_valid_name(name: str, allowed_characters: List[str]) -> str:
396
- correct_name = NameConverter._remove_invalid_characters(name, allowed_characters)
397
-
398
- # here we have an empty string or a string that consists only of invalid characters
399
- if not correct_name or correct_name[0] in basic_latin_chars.keys():
400
- ret_name = ""
401
- for c in name:
402
- if c in basic_latin_chars.keys():
403
- ret_name += basic_latin_chars[c]
404
- else:
405
- ret_name += c
406
- correct_name = NameConverter._remove_invalid_characters(ret_name, allowed_characters)
407
-
408
- if not correct_name:
409
- raise ValueError(
410
- "Property name {} cannot be used as an identifier, as it contains only invalid characters.".format(name)
411
- )
412
- return correct_name