@autorest/python 5.15.0 → 5.18.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.
- package/ChangeLog.md +98 -4
- package/README.md +30 -4
- package/autorest/__init__.py +2 -3
- package/autorest/black/__init__.py +12 -5
- package/autorest/codegen/__init__.py +122 -211
- package/autorest/codegen/models/__init__.py +122 -78
- package/autorest/codegen/models/base_builder.py +70 -72
- package/autorest/codegen/models/base_model.py +7 -5
- package/autorest/codegen/models/{base_schema.py → base_type.py} +68 -45
- package/autorest/codegen/models/client.py +193 -40
- package/autorest/codegen/models/code_model.py +145 -245
- package/autorest/codegen/models/combined_type.py +107 -0
- package/autorest/codegen/models/constant_type.py +122 -0
- package/autorest/codegen/models/credential_types.py +224 -0
- package/autorest/codegen/models/dictionary_type.py +131 -0
- package/autorest/codegen/models/enum_type.py +195 -0
- package/autorest/codegen/models/imports.py +93 -41
- package/autorest/codegen/models/list_type.py +149 -0
- package/autorest/codegen/models/lro_operation.py +90 -133
- package/autorest/codegen/models/lro_paging_operation.py +28 -12
- package/autorest/codegen/models/model_type.py +262 -0
- package/autorest/codegen/models/operation.py +412 -259
- package/autorest/codegen/models/operation_group.py +80 -91
- package/autorest/codegen/models/paging_operation.py +101 -117
- package/autorest/codegen/models/parameter.py +302 -341
- package/autorest/codegen/models/parameter_list.py +373 -357
- package/autorest/codegen/models/primitive_types.py +544 -0
- package/autorest/codegen/models/property.py +136 -134
- package/autorest/codegen/models/request_builder.py +138 -86
- package/autorest/codegen/models/request_builder_parameter.py +122 -86
- package/autorest/codegen/models/response.py +325 -0
- package/autorest/codegen/models/utils.py +13 -17
- package/autorest/codegen/serializers/__init__.py +212 -112
- package/autorest/codegen/serializers/builder_serializer.py +931 -1040
- package/autorest/codegen/serializers/client_serializer.py +140 -84
- package/autorest/codegen/serializers/general_serializer.py +26 -50
- package/autorest/codegen/serializers/import_serializer.py +96 -31
- package/autorest/codegen/serializers/metadata_serializer.py +39 -79
- package/autorest/codegen/serializers/model_base_serializer.py +62 -34
- package/autorest/codegen/serializers/model_generic_serializer.py +9 -10
- package/autorest/codegen/serializers/model_init_serializer.py +4 -2
- package/autorest/codegen/serializers/model_python3_serializer.py +29 -22
- package/autorest/codegen/serializers/operation_groups_serializer.py +21 -19
- package/autorest/codegen/serializers/operations_init_serializer.py +23 -11
- package/autorest/codegen/serializers/parameter_serializer.py +174 -0
- package/autorest/codegen/serializers/patch_serializer.py +4 -1
- package/autorest/codegen/serializers/request_builders_serializer.py +57 -0
- package/autorest/codegen/serializers/utils.py +0 -126
- package/autorest/codegen/templates/MANIFEST.in.jinja2 +1 -0
- package/autorest/codegen/templates/{service_client.py.jinja2 → client.py.jinja2} +7 -7
- package/autorest/codegen/templates/config.py.jinja2 +13 -13
- package/autorest/codegen/templates/enum.py.jinja2 +4 -4
- package/autorest/codegen/templates/enum_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/init.py.jinja2 +3 -3
- package/autorest/codegen/templates/lro_operation.py.jinja2 +6 -5
- package/autorest/codegen/templates/lro_paging_operation.py.jinja2 +6 -5
- package/autorest/codegen/templates/metadata.json.jinja2 +36 -35
- package/autorest/codegen/templates/model.py.jinja2 +23 -24
- package/autorest/codegen/templates/model_container.py.jinja2 +2 -1
- package/autorest/codegen/templates/model_init.py.jinja2 +3 -5
- package/autorest/codegen/templates/operation.py.jinja2 +10 -14
- package/autorest/codegen/templates/operation_group.py.jinja2 +9 -15
- package/autorest/codegen/templates/operation_groups_container.py.jinja2 +1 -1
- package/autorest/codegen/templates/operation_tools.jinja2 +8 -2
- package/autorest/codegen/templates/paging_operation.py.jinja2 +7 -8
- package/autorest/codegen/templates/request_builder.py.jinja2 +19 -10
- package/autorest/codegen/templates/setup.py.jinja2 +9 -3
- package/autorest/codegen/templates/vendor.py.jinja2 +1 -1
- package/autorest/jsonrpc/__init__.py +7 -12
- package/autorest/jsonrpc/localapi.py +4 -3
- package/autorest/jsonrpc/server.py +28 -9
- package/autorest/jsonrpc/stdstream.py +13 -6
- package/autorest/m2r/__init__.py +5 -8
- package/autorest/m4reformatter/__init__.py +1126 -0
- package/autorest/multiapi/__init__.py +24 -14
- package/autorest/multiapi/models/client.py +21 -11
- package/autorest/multiapi/models/code_model.py +23 -10
- package/autorest/multiapi/models/config.py +4 -1
- package/autorest/multiapi/models/constant_global_parameter.py +1 -0
- package/autorest/multiapi/models/global_parameter.py +2 -1
- package/autorest/multiapi/models/global_parameters.py +14 -8
- package/autorest/multiapi/models/imports.py +24 -17
- package/autorest/multiapi/models/mixin_operation.py +5 -5
- package/autorest/multiapi/models/operation_group.py +2 -1
- package/autorest/multiapi/models/operation_mixin_group.py +21 -10
- package/autorest/multiapi/serializers/__init__.py +20 -25
- package/autorest/multiapi/serializers/import_serializer.py +47 -17
- package/autorest/multiapi/serializers/multiapi_serializer.py +17 -17
- package/autorest/multiapi/templates/multiapi_config.py.jinja2 +3 -3
- package/autorest/multiapi/templates/multiapi_init.py.jinja2 +2 -2
- package/autorest/multiapi/templates/multiapi_operations_mixin.py.jinja2 +4 -4
- package/autorest/multiapi/templates/multiapi_service_client.py.jinja2 +9 -9
- package/autorest/multiapi/utils.py +3 -3
- package/autorest/postprocess/__init__.py +202 -0
- package/autorest/postprocess/get_all.py +19 -0
- package/autorest/postprocess/venvtools.py +73 -0
- package/autorest/preprocess/__init__.py +210 -0
- package/autorest/preprocess/helpers.py +54 -0
- package/autorest/{namer → preprocess}/python_mappings.py +25 -32
- package/package.json +3 -3
- package/run-python3.js +2 -3
- package/venvtools.py +1 -1
- package/autorest/codegen/models/constant_schema.py +0 -101
- package/autorest/codegen/models/credential_model.py +0 -47
- package/autorest/codegen/models/credential_schema.py +0 -91
- package/autorest/codegen/models/credential_schema_policy.py +0 -77
- package/autorest/codegen/models/dictionary_schema.py +0 -103
- package/autorest/codegen/models/enum_schema.py +0 -215
- package/autorest/codegen/models/list_schema.py +0 -123
- package/autorest/codegen/models/object_schema.py +0 -253
- package/autorest/codegen/models/primitive_schemas.py +0 -466
- package/autorest/codegen/models/request_builder_parameter_list.py +0 -280
- package/autorest/codegen/models/rest.py +0 -42
- package/autorest/codegen/models/schema_request.py +0 -45
- package/autorest/codegen/models/schema_response.py +0 -136
- package/autorest/codegen/serializers/rest_serializer.py +0 -57
- package/autorest/namer/__init__.py +0 -25
- package/autorest/namer/name_converter.py +0 -412
|
@@ -3,22 +3,38 @@
|
|
|
3
3
|
# Licensed under the MIT License. See License.txt in the project root for
|
|
4
4
|
# license information.
|
|
5
5
|
# --------------------------------------------------------------------------
|
|
6
|
+
from typing import Any
|
|
6
7
|
from .imports import FileImport
|
|
7
|
-
from .lro_operation import
|
|
8
|
-
from .paging_operation import
|
|
8
|
+
from .lro_operation import LROOperationBase
|
|
9
|
+
from .paging_operation import PagingOperationBase
|
|
10
|
+
from .response import LROPagingResponse, Response
|
|
9
11
|
|
|
10
|
-
class LROPagingOperation(PagingOperation, LROOperation):
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
class LROPagingOperation(
|
|
14
|
+
LROOperationBase[LROPagingResponse], PagingOperationBase[LROPagingResponse]
|
|
15
|
+
):
|
|
16
|
+
@property
|
|
17
|
+
def success_status_codes(self):
|
|
18
|
+
"""The list of all successfull status code."""
|
|
19
|
+
return [200]
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def operation_type(self) -> str:
|
|
23
|
+
return "lropaging"
|
|
24
|
+
|
|
25
|
+
def cls_type_annotation(self, *, async_mode: bool) -> str:
|
|
26
|
+
return f"ClsType[{Response.type_annotation(self.responses[0], async_mode=async_mode)}]" # pylint: disable=no-member
|
|
27
|
+
|
|
28
|
+
def imports(
|
|
29
|
+
self, async_mode: bool, is_python3_file: bool, **kwargs: Any
|
|
30
|
+
) -> FileImport:
|
|
31
|
+
lro_imports = LROOperationBase.imports(
|
|
32
|
+
self, async_mode, is_python3_file, **kwargs
|
|
33
|
+
)
|
|
34
|
+
paging_imports = PagingOperationBase.imports(
|
|
35
|
+
self, async_mode, is_python3_file, **kwargs
|
|
36
|
+
)
|
|
15
37
|
|
|
16
38
|
file_import = lro_imports
|
|
17
39
|
file_import.merge(paging_imports)
|
|
18
40
|
return file_import
|
|
19
|
-
|
|
20
|
-
@property
|
|
21
|
-
def success_status_code(self):
|
|
22
|
-
"""The list of all successfull status code.
|
|
23
|
-
"""
|
|
24
|
-
return [200]
|
|
@@ -0,0 +1,262 @@
|
|
|
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
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING, cast
|
|
7
|
+
|
|
8
|
+
from autorest.codegen.models.utils import add_to_pylint_disable
|
|
9
|
+
from .base_type import BaseType
|
|
10
|
+
from .property import Property
|
|
11
|
+
from .imports import FileImport, ImportType, TypingSection
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from .code_model import CodeModel
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _get_properties(type: "ModelType", properties: List[Property]) -> List[Property]:
|
|
18
|
+
for parent in type.parents:
|
|
19
|
+
# here we're adding the properties from our parents
|
|
20
|
+
|
|
21
|
+
# need to make sure that the properties we choose from our parent also don't contain
|
|
22
|
+
# any of our own properties
|
|
23
|
+
property_names = set(
|
|
24
|
+
[p.client_name for p in properties]
|
|
25
|
+
+ [p.client_name for p in type.properties]
|
|
26
|
+
)
|
|
27
|
+
chosen_parent_properties = [
|
|
28
|
+
p for p in parent.properties if p.client_name not in property_names
|
|
29
|
+
]
|
|
30
|
+
properties = _get_properties(parent, chosen_parent_properties) + properties
|
|
31
|
+
return properties
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ModelType(BaseType): # pylint: disable=too-many-instance-attributes
|
|
35
|
+
"""Represents a class ready to be serialized in Python.
|
|
36
|
+
|
|
37
|
+
:param str name: The name of the class.
|
|
38
|
+
:param str description: The description of the class.
|
|
39
|
+
:param properties: the optional properties of the class.
|
|
40
|
+
:type properties: dict(str, str)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
yaml_data: Dict[str, Any],
|
|
46
|
+
code_model: "CodeModel",
|
|
47
|
+
*,
|
|
48
|
+
properties: Optional[List[Property]] = None,
|
|
49
|
+
parents: Optional[List["ModelType"]] = None,
|
|
50
|
+
discriminated_subtypes: Optional[Dict[str, "ModelType"]] = None,
|
|
51
|
+
) -> None:
|
|
52
|
+
super().__init__(yaml_data=yaml_data, code_model=code_model)
|
|
53
|
+
self.name: str = self.yaml_data["name"]
|
|
54
|
+
self.max_properties: Optional[int] = self.yaml_data.get("maxProperties")
|
|
55
|
+
self.min_properties: Optional[int] = self.yaml_data.get("minProperties")
|
|
56
|
+
self.properties = properties or []
|
|
57
|
+
self.parents = parents or []
|
|
58
|
+
self.discriminated_subtypes = discriminated_subtypes or {}
|
|
59
|
+
self.discriminator_value: Optional[str] = self.yaml_data.get(
|
|
60
|
+
"discriminatorValue"
|
|
61
|
+
)
|
|
62
|
+
self._created_json_template_representation = False
|
|
63
|
+
self.is_public: bool = self.yaml_data.get("isPublic", True)
|
|
64
|
+
self.snake_case_name: str = self.yaml_data["snakeCaseName"]
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def is_xml(self) -> bool:
|
|
68
|
+
return self.yaml_data.get("isXml", False)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def serialization_type(self) -> str:
|
|
72
|
+
if self.code_model.options["models_mode"]:
|
|
73
|
+
return self.name
|
|
74
|
+
return "object"
|
|
75
|
+
|
|
76
|
+
def type_annotation(self, **kwargs: Any) -> str:
|
|
77
|
+
if self.code_model.options["models_mode"]:
|
|
78
|
+
is_operation_file = kwargs.pop("is_operation_file", False)
|
|
79
|
+
if self.is_public:
|
|
80
|
+
retval = f"_models.{self.name}"
|
|
81
|
+
return retval if is_operation_file else f'"{retval}"'
|
|
82
|
+
return self.name if is_operation_file else f'"{self.name}"'
|
|
83
|
+
return "ET.Element" if self.is_xml else "JSON"
|
|
84
|
+
|
|
85
|
+
def docstring_type(self, **kwargs: Any) -> str:
|
|
86
|
+
if self.code_model.options["models_mode"]:
|
|
87
|
+
return f"~{self.code_model.namespace}.models.{self.name}"
|
|
88
|
+
return "ET.Element" if self.is_xml else "JSON"
|
|
89
|
+
|
|
90
|
+
def description(self, *, is_operation_file: bool = False) -> str:
|
|
91
|
+
return "" if is_operation_file else self.yaml_data.get("description", self.name)
|
|
92
|
+
|
|
93
|
+
def docstring_text(self, **kwargs: Any) -> str:
|
|
94
|
+
if self.code_model.options["models_mode"]:
|
|
95
|
+
return self.name
|
|
96
|
+
return "XML Element" if self.is_xml else "JSON object"
|
|
97
|
+
|
|
98
|
+
def get_declaration(self, value: Any) -> str:
|
|
99
|
+
return f"{self.name}()"
|
|
100
|
+
|
|
101
|
+
def __repr__(self) -> str:
|
|
102
|
+
return f"<{self.__class__.__name__} {self.name}>"
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def xml_serialization_ctxt(self) -> Optional[str]:
|
|
106
|
+
# object schema contains _xml_map, they don't need serialization context
|
|
107
|
+
return ""
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def xml_map_content(self) -> Optional[str]:
|
|
111
|
+
# This is NOT an error on the super call, we use the serialization context for "xml_map",
|
|
112
|
+
# but we don't want to write a serialization context for an object.
|
|
113
|
+
return super().xml_serialization_ctxt
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def discriminated_subtypes_name_mapping(self) -> Dict[str, str]:
|
|
117
|
+
return {k: v.name for k, v in self.discriminated_subtypes.items()}
|
|
118
|
+
|
|
119
|
+
def get_json_template_representation(
|
|
120
|
+
self,
|
|
121
|
+
*,
|
|
122
|
+
optional: bool = True,
|
|
123
|
+
client_default_value_declaration: Optional[str] = None,
|
|
124
|
+
description: Optional[str] = None,
|
|
125
|
+
) -> Any:
|
|
126
|
+
if self._created_json_template_representation:
|
|
127
|
+
return "..." # do this to avoid loop
|
|
128
|
+
self._created_json_template_representation = True
|
|
129
|
+
if self.discriminated_subtypes:
|
|
130
|
+
# we will instead print the discriminated subtypes
|
|
131
|
+
self._created_json_template_representation = False
|
|
132
|
+
return self.snake_case_name
|
|
133
|
+
|
|
134
|
+
# don't add additional properties, because there's not really a concept of
|
|
135
|
+
# additional properties in the template
|
|
136
|
+
representation = {
|
|
137
|
+
f'"{prop.rest_api_name}"': prop.get_json_template_representation(
|
|
138
|
+
optional=optional,
|
|
139
|
+
client_default_value_declaration=client_default_value_declaration,
|
|
140
|
+
description=description,
|
|
141
|
+
)
|
|
142
|
+
for prop in [
|
|
143
|
+
p
|
|
144
|
+
for p in self.properties
|
|
145
|
+
if not (p.is_discriminator or p.client_name == "additional_properties")
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
if self.discriminator and self.discriminator_value:
|
|
149
|
+
representation[
|
|
150
|
+
f'"{self.discriminator.rest_api_name}"'
|
|
151
|
+
] = f'"{self.discriminator_value}"'
|
|
152
|
+
|
|
153
|
+
# once we've finished, we want to reset created_json_template_representation to false
|
|
154
|
+
# so we can call it again
|
|
155
|
+
self._created_json_template_representation = False
|
|
156
|
+
return representation
|
|
157
|
+
|
|
158
|
+
def get_polymorphic_subtypes(self, polymorphic_subtypes: List["ModelType"]) -> None:
|
|
159
|
+
is_polymorphic_subtype = (
|
|
160
|
+
self.discriminator_value and not self.discriminated_subtypes
|
|
161
|
+
)
|
|
162
|
+
if (
|
|
163
|
+
self.name not in (m.name for m in polymorphic_subtypes)
|
|
164
|
+
and is_polymorphic_subtype
|
|
165
|
+
):
|
|
166
|
+
polymorphic_subtypes.append(self)
|
|
167
|
+
for discriminated_subtype in self.discriminated_subtypes.values():
|
|
168
|
+
discriminated_subtype.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
169
|
+
for property in self.properties:
|
|
170
|
+
property.get_polymorphic_subtypes(polymorphic_subtypes)
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def from_yaml(
|
|
174
|
+
cls, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
175
|
+
) -> "ModelType":
|
|
176
|
+
raise ValueError(
|
|
177
|
+
"You shouldn't call from_yaml for ModelType to avoid recursion. "
|
|
178
|
+
"Please initial a blank ModelType, then call .fill_instance_from_yaml on the created type."
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def fill_instance_from_yaml(
|
|
182
|
+
self, yaml_data: Dict[str, Any], code_model: "CodeModel"
|
|
183
|
+
) -> None:
|
|
184
|
+
from . import build_type
|
|
185
|
+
|
|
186
|
+
self.parents = [
|
|
187
|
+
cast(ModelType, build_type(bm, code_model))
|
|
188
|
+
for bm in yaml_data.get("parents", [])
|
|
189
|
+
]
|
|
190
|
+
properties = [
|
|
191
|
+
Property.from_yaml(p, code_model) for p in yaml_data["properties"]
|
|
192
|
+
]
|
|
193
|
+
self.properties = _get_properties(self, properties)
|
|
194
|
+
# checking to see if this is a polymorphic class
|
|
195
|
+
self.discriminated_subtypes = {
|
|
196
|
+
k: cast(ModelType, build_type(v, code_model))
|
|
197
|
+
for k, v in self.yaml_data.get("discriminatedSubtypes", {}).items()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def has_readonly_or_constant_property(self) -> bool:
|
|
202
|
+
return any(x.readonly or x.constant for x in self.properties)
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def discriminator(self) -> Optional[Property]:
|
|
206
|
+
try:
|
|
207
|
+
return next(p for p in self.properties if p.is_discriminator)
|
|
208
|
+
except StopIteration:
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def instance_check_template(self) -> str:
|
|
213
|
+
if self.code_model.options["models_mode"]:
|
|
214
|
+
return "isinstance({}, msrest.Model)"
|
|
215
|
+
return "isinstance({}, MutableMapping)"
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def pylint_disable(self) -> str:
|
|
219
|
+
retval: str = ""
|
|
220
|
+
if len(self.properties) > 10:
|
|
221
|
+
retval = add_to_pylint_disable(retval, "too-many-instance-attributes")
|
|
222
|
+
return retval
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def init_pylint_disable(self) -> str:
|
|
226
|
+
retval: str = ""
|
|
227
|
+
if len(self.properties) > 23:
|
|
228
|
+
retval = add_to_pylint_disable(retval, "too-many-locals")
|
|
229
|
+
return retval
|
|
230
|
+
|
|
231
|
+
def imports(self, **kwargs: Any) -> FileImport:
|
|
232
|
+
file_import = FileImport()
|
|
233
|
+
relative_path = kwargs.pop("relative_path", None)
|
|
234
|
+
if self.code_model.options["models_mode"] and relative_path:
|
|
235
|
+
# add import for models in operations file
|
|
236
|
+
if self.is_public:
|
|
237
|
+
file_import.add_submodule_import(
|
|
238
|
+
relative_path, "models", ImportType.LOCAL, alias="_models"
|
|
239
|
+
)
|
|
240
|
+
else:
|
|
241
|
+
# a little hacky, but we only do this for version tolerant
|
|
242
|
+
# models files, which are all python3 only
|
|
243
|
+
models_filename = self.code_model.get_models_filename(
|
|
244
|
+
is_python3_file=True
|
|
245
|
+
)
|
|
246
|
+
file_import.add_submodule_import(
|
|
247
|
+
f"{relative_path}models.{models_filename}",
|
|
248
|
+
self.name,
|
|
249
|
+
ImportType.LOCAL,
|
|
250
|
+
)
|
|
251
|
+
if self.code_model.options["models_mode"]:
|
|
252
|
+
return file_import
|
|
253
|
+
file_import.add_submodule_import(
|
|
254
|
+
"typing", "Any", ImportType.STDLIB, TypingSection.CONDITIONAL
|
|
255
|
+
)
|
|
256
|
+
file_import.add_import("sys", ImportType.STDLIB)
|
|
257
|
+
file_import.define_mutable_mapping_type()
|
|
258
|
+
if self.is_xml:
|
|
259
|
+
file_import.add_submodule_import(
|
|
260
|
+
"xml.etree", "ElementTree", ImportType.STDLIB, alias="ET"
|
|
261
|
+
)
|
|
262
|
+
return file_import
|