stepxmlclient 1.0.0__py3-none-any.whl
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.
- stepxmlclient/__init__.py +22 -0
- stepxmlclient/client.py +373 -0
- stepxmlclient/creator.py +317 -0
- stepxmlclient/model/__init__.py +418 -0
- stepxmlclient/model/asset.py +250 -0
- stepxmlclient/model/attribute.py +288 -0
- stepxmlclient/model/business.py +233 -0
- stepxmlclient/model/classification.py +409 -0
- stepxmlclient/model/complex_elements.py +260 -0
- stepxmlclient/model/deletion.py +87 -0
- stepxmlclient/model/entity.py +368 -0
- stepxmlclient/model/metadata.py +199 -0
- stepxmlclient/model/organization.py +167 -0
- stepxmlclient/model/product.py +519 -0
- stepxmlclient/model/relations.py +105 -0
- stepxmlclient/model/replacement.py +417 -0
- stepxmlclient/parser.py +2805 -0
- stepxmlclient/rest_client/__init__.py +16 -0
- stepxmlclient/rest_client/base.py +388 -0
- stepxmlclient/rest_client/client.py +127 -0
- stepxmlclient/rest_client/exceptions.py +97 -0
- stepxmlclient/rest_client/models/__init__.py +175 -0
- stepxmlclient/rest_client/models/asset.py +253 -0
- stepxmlclient/rest_client/models/attribute.py +112 -0
- stepxmlclient/rest_client/models/background_process.py +23 -0
- stepxmlclient/rest_client/models/batch.py +41 -0
- stepxmlclient/rest_client/models/classification.py +57 -0
- stepxmlclient/rest_client/models/collection.py +26 -0
- stepxmlclient/rest_client/models/common.py +192 -0
- stepxmlclient/rest_client/models/context.py +16 -0
- stepxmlclient/rest_client/models/data_type_group.py +15 -0
- stepxmlclient/rest_client/models/entity.py +63 -0
- stepxmlclient/rest_client/models/event_processor.py +15 -0
- stepxmlclient/rest_client/models/import_export.py +43 -0
- stepxmlclient/rest_client/models/integration_endpoint.py +16 -0
- stepxmlclient/rest_client/models/product.py +200 -0
- stepxmlclient/rest_client/models/relations.py +280 -0
- stepxmlclient/rest_client/models/system_information.py +11 -0
- stepxmlclient/rest_client/models/user.py +28 -0
- stepxmlclient/rest_client/models/workflow.py +30 -0
- stepxmlclient/rest_client/operations/__init__.py +54 -0
- stepxmlclient/rest_client/operations/assets.py +652 -0
- stepxmlclient/rest_client/operations/attributes.py +252 -0
- stepxmlclient/rest_client/operations/background_processes.py +84 -0
- stepxmlclient/rest_client/operations/batch.py +28 -0
- stepxmlclient/rest_client/operations/classifications.py +248 -0
- stepxmlclient/rest_client/operations/collection_groups.py +46 -0
- stepxmlclient/rest_client/operations/collections.py +67 -0
- stepxmlclient/rest_client/operations/contexts.py +88 -0
- stepxmlclient/rest_client/operations/data_type_groups.py +68 -0
- stepxmlclient/rest_client/operations/entities.py +295 -0
- stepxmlclient/rest_client/operations/event_processors.py +109 -0
- stepxmlclient/rest_client/operations/exports.py +153 -0
- stepxmlclient/rest_client/operations/gateway.py +53 -0
- stepxmlclient/rest_client/operations/inbound.py +472 -0
- stepxmlclient/rest_client/operations/outbound.py +64 -0
- stepxmlclient/rest_client/operations/products.py +489 -0
- stepxmlclient/rest_client/operations/relations.py +349 -0
- stepxmlclient/rest_client/operations/reports.py +27 -0
- stepxmlclient/rest_client/operations/system_information.py +28 -0
- stepxmlclient/rest_client/operations/user_groups.py +79 -0
- stepxmlclient/rest_client/operations/users.py +119 -0
- stepxmlclient/rest_client/operations/workflow_tasks.py +61 -0
- stepxmlclient/rest_client/operations/workflows.py +50 -0
- stepxmlclient/upload.py +293 -0
- stepxmlclient-1.0.0.dist-info/METADATA +666 -0
- stepxmlclient-1.0.0.dist-info/RECORD +70 -0
- stepxmlclient-1.0.0.dist-info/WHEEL +5 -0
- stepxmlclient-1.0.0.dist-info/licenses/LICENSE +21 -0
- stepxmlclient-1.0.0.dist-info/top_level.txt +1 -0
stepxmlclient/creator.py
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""
|
|
2
|
+
STEP-XML Creator module.
|
|
3
|
+
|
|
4
|
+
This module provides the Creator class for serializing Python objects into STEP-XML documents.
|
|
5
|
+
It takes BaseObject instances representing STEP entities (Products, Assets, Attributes, etc.)
|
|
6
|
+
and generates valid STEP-XML that can be imported into STEP MDM systems.
|
|
7
|
+
|
|
8
|
+
The Creator maintains separate lists for each entity type and handles the complex hierarchical
|
|
9
|
+
structure of STEP-XML documents, including replacement rules, nested relationships, and
|
|
10
|
+
multi-workspace support.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
Basic workflow for creating STEP-XML documents::
|
|
14
|
+
|
|
15
|
+
from stepxmlclient.creator import Creator
|
|
16
|
+
from stepxmlclient.model import Product, Attribute
|
|
17
|
+
|
|
18
|
+
# Create a creator for a specific context
|
|
19
|
+
creator = Creator(context_id='Context1', workspace_id='Main')
|
|
20
|
+
|
|
21
|
+
# Add entities
|
|
22
|
+
product = Product({'ID': 'P1', 'Name': {'en_US': 'Example Product'}})
|
|
23
|
+
creator.add(product)
|
|
24
|
+
|
|
25
|
+
# Generate XML
|
|
26
|
+
creator.build()
|
|
27
|
+
xml_string = creator.to_string()
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
import xml.etree.ElementTree as ET
|
|
31
|
+
from typing import List, Optional
|
|
32
|
+
from . import STEPXML_NS
|
|
33
|
+
from .model import BaseObject
|
|
34
|
+
|
|
35
|
+
class Creator:
|
|
36
|
+
"""STEP-XML document creator for serializing Python objects.
|
|
37
|
+
|
|
38
|
+
Generates valid STEP-XML documents from BaseObject instances organized by entity type.
|
|
39
|
+
Supports all STEP entity types and handles the complex XML structure including
|
|
40
|
+
replacement rules, deletions, and multi-context/workspace configurations.
|
|
41
|
+
|
|
42
|
+
Attributes:
|
|
43
|
+
context_id: STEP Context ID for the document
|
|
44
|
+
workspace_id: STEP Workspace ID for the document
|
|
45
|
+
products: List of Product objects to include
|
|
46
|
+
assets: List of Asset objects to include
|
|
47
|
+
classifications: List of Classification objects to include
|
|
48
|
+
entities: List of Entity objects to include
|
|
49
|
+
attributes: List of Attribute definitions to include
|
|
50
|
+
attributegroups: List of Attribute Group definitions to include
|
|
51
|
+
listofvalues: List of List-of-Values items to include
|
|
52
|
+
contexts: List of Context definitions to include
|
|
53
|
+
qualifiers: List of Qualifier definitions to include
|
|
54
|
+
dimensions: List of Dimension definitions to include
|
|
55
|
+
usertypes: List of User Type definitions to include
|
|
56
|
+
linktypes: List of Link Type definitions to include
|
|
57
|
+
tags: List of Tag definitions to include
|
|
58
|
+
taggroups: List of Tag Group definitions to include
|
|
59
|
+
units: List of Unit definitions to include
|
|
60
|
+
businessrules: List of Business Rule definitions to include
|
|
61
|
+
workflows: List of Workflow definitions to include
|
|
62
|
+
collections: List of Collection objects to include
|
|
63
|
+
collectiongroups: List of Collection Group definitions to include
|
|
64
|
+
deletedproducts: List of Product deletion specifications
|
|
65
|
+
deletedassets: List of Asset deletion specifications
|
|
66
|
+
product_replacement_rules: List of Product replacement rules
|
|
67
|
+
replace_products: List of Products to replace
|
|
68
|
+
replace_classifications: List of Classifications to replace
|
|
69
|
+
replace_entities: List of Entities to replace
|
|
70
|
+
replace_assets: List of Assets to replace
|
|
71
|
+
replace_attributes: List of Attributes to replace
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
context_id: str,
|
|
77
|
+
workspace_id: str = 'Main') -> None:
|
|
78
|
+
"""Initialize a Creator instance.
|
|
79
|
+
|
|
80
|
+
Creates a new Creator for generating STEP-XML documents. All entity lists are
|
|
81
|
+
initialized as empty; populate them by calling add() or add_list() methods.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
context_id: STEP Context ID to use in the generated document
|
|
85
|
+
(required, identifies the STEP context for import)
|
|
86
|
+
workspace_id: STEP Workspace ID (default: 'Main')
|
|
87
|
+
identifies the workspace for multi-workspace environments
|
|
88
|
+
"""
|
|
89
|
+
self.context_id: str = context_id
|
|
90
|
+
self.workspace_id: str = workspace_id
|
|
91
|
+
self.root: Optional[ET.Element] = None
|
|
92
|
+
self.tree: Optional[ET.ElementTree] = None
|
|
93
|
+
self.products: List[BaseObject] = []
|
|
94
|
+
self.assets: List[BaseObject] = []
|
|
95
|
+
self.classifications: List[BaseObject] = []
|
|
96
|
+
self.entities: List[BaseObject] = []
|
|
97
|
+
self.attributes: List[BaseObject] = []
|
|
98
|
+
self.attributegroups: List[BaseObject] = []
|
|
99
|
+
self.listofvalues: List[BaseObject] = []
|
|
100
|
+
self.contexts: List[BaseObject] = []
|
|
101
|
+
self.qualifiers: List[BaseObject] = []
|
|
102
|
+
self.dimensions: List[BaseObject] = []
|
|
103
|
+
self.usertypes: List[BaseObject] = []
|
|
104
|
+
self.linktypes: List[BaseObject] = []
|
|
105
|
+
self.tags: List[BaseObject] = []
|
|
106
|
+
self.taggroups: List[BaseObject] = []
|
|
107
|
+
self.units: List[BaseObject] = []
|
|
108
|
+
self.businessrules: List[BaseObject] = []
|
|
109
|
+
self.workflows: List[BaseObject] = []
|
|
110
|
+
self.collections: List[BaseObject] = []
|
|
111
|
+
self.collectiongroups: List[BaseObject] = []
|
|
112
|
+
self.deletedproducts: List[BaseObject] = []
|
|
113
|
+
self.deletedassets: List[BaseObject] = []
|
|
114
|
+
self.product_replacement_rules: List[BaseObject] = []
|
|
115
|
+
self.replace_products: List[BaseObject] = []
|
|
116
|
+
self.replace_classifications: List[BaseObject] = []
|
|
117
|
+
self.replace_entities: List[BaseObject] = []
|
|
118
|
+
self.replace_assets: List[BaseObject] = []
|
|
119
|
+
self.replace_attributes: List[BaseObject] = []
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
def build(self) -> None:
|
|
123
|
+
"""Build the XML document structure from added entities.
|
|
124
|
+
|
|
125
|
+
Generates the ElementTree representation of the STEP-XML document based on all
|
|
126
|
+
entities currently in the creator's lists. Must be called before to_string()
|
|
127
|
+
or to_bytes(). This method:
|
|
128
|
+
|
|
129
|
+
1. Creates the root STEP-ProductInformation element
|
|
130
|
+
2. Adds ReplacementRules section if any replacement rules exist
|
|
131
|
+
3. Adds all entity sections in the correct STEP-XML order
|
|
132
|
+
4. Sets the ContextID and WorkspaceID attributes
|
|
133
|
+
|
|
134
|
+
After calling build(), the XML can be accessed via to_string() or to_bytes().
|
|
135
|
+
|
|
136
|
+
Note:
|
|
137
|
+
The method only includes sections for entity types that have items.
|
|
138
|
+
Empty lists do not generate corresponding XML elements.
|
|
139
|
+
"""
|
|
140
|
+
self.root = ET.Element(
|
|
141
|
+
'STEP-ProductInformation',
|
|
142
|
+
{
|
|
143
|
+
"ContextID": self.context_id,
|
|
144
|
+
"WorkspaceID": self.workspace_id
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
self.tree = ET.ElementTree(self.root)
|
|
148
|
+
# replacement rules section (Phase 1 + Phase 7)
|
|
149
|
+
replacement_rules_collections = {
|
|
150
|
+
"Products": self.product_replacement_rules,
|
|
151
|
+
"Classifications": self.replace_classifications,
|
|
152
|
+
"Entities": self.replace_entities,
|
|
153
|
+
"Assets": self.replace_assets,
|
|
154
|
+
"Attributes": self.replace_attributes
|
|
155
|
+
}
|
|
156
|
+
# Check if any replacement rules exist
|
|
157
|
+
has_replacement_rules = any(replacement_rules_collections.values())
|
|
158
|
+
if has_replacement_rules:
|
|
159
|
+
rules = ET.SubElement(self.root, 'ReplacementRules')
|
|
160
|
+
for xml_name, collection in replacement_rules_collections.items():
|
|
161
|
+
if collection:
|
|
162
|
+
self._build_element_list(rules, xml_name, collection)
|
|
163
|
+
# others - map XML element names to attribute names
|
|
164
|
+
element_mapping = {
|
|
165
|
+
"Assets": "assets",
|
|
166
|
+
"Products": "products",
|
|
167
|
+
"Classifications": "classifications",
|
|
168
|
+
"Entities": "entities",
|
|
169
|
+
"Attributes": "attributes",
|
|
170
|
+
"AttributeGroups": "attributegroups",
|
|
171
|
+
"ListOfValues": "listofvalues",
|
|
172
|
+
"Contexts": "contexts",
|
|
173
|
+
"Qualifiers": "qualifiers",
|
|
174
|
+
"Dimensions": "dimensions",
|
|
175
|
+
"UserTypes": "usertypes",
|
|
176
|
+
"LinkTypes": "linktypes",
|
|
177
|
+
"Tags": "tags",
|
|
178
|
+
"TagGroups": "taggroups",
|
|
179
|
+
"Units": "units",
|
|
180
|
+
"BusinessRules": "businessrules",
|
|
181
|
+
"Workflows": "workflows",
|
|
182
|
+
"Collections": "collections",
|
|
183
|
+
"CollectionGroups": "collectiongroups",
|
|
184
|
+
"DeletedAssets": "deletedassets",
|
|
185
|
+
"DeletedProducts": "deletedproducts"
|
|
186
|
+
}
|
|
187
|
+
for xml_name, attr_name in element_mapping.items():
|
|
188
|
+
values = getattr(self, attr_name)
|
|
189
|
+
if values:
|
|
190
|
+
self._build_element_list(self.root, xml_name, values)
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
def _build_element_list(self, parent: ET.Element,
|
|
194
|
+
list_name: str,
|
|
195
|
+
objs: List[BaseObject]) -> None:
|
|
196
|
+
"""Add a collection of objects as child elements to a parent element.
|
|
197
|
+
|
|
198
|
+
Internal helper method that creates a container element and populates it with
|
|
199
|
+
the serialized representations of the provided objects.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
parent: Parent ElementTree Element to add the collection to
|
|
203
|
+
list_name: XML tag name for the collection container
|
|
204
|
+
objs: List of BaseObject instances to serialize
|
|
205
|
+
"""
|
|
206
|
+
list_element = ET.SubElement(parent, list_name)
|
|
207
|
+
for obj in objs:
|
|
208
|
+
obj.to_element(list_element)
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
def add(self, obj: BaseObject) -> bool:
|
|
212
|
+
"""Add a single object to the appropriate collection list.
|
|
213
|
+
|
|
214
|
+
Automatically routes the object to the correct list based on its _GROUP_NAME.
|
|
215
|
+
Objects must be instances of BaseObject subclasses with a valid _GROUP_NAME.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
obj: BaseObject instance to add
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
True if the object was successfully added, False if _GROUP_NAME not found
|
|
222
|
+
or is not a list attribute
|
|
223
|
+
|
|
224
|
+
Example:
|
|
225
|
+
creator = Creator('Context1')
|
|
226
|
+
product = Product({'ID': 'P1', 'Name': {'en_US': 'Product'}})
|
|
227
|
+
if creator.add(product):
|
|
228
|
+
print("Product added successfully")
|
|
229
|
+
"""
|
|
230
|
+
if obj._GROUP_NAME is None:
|
|
231
|
+
return False
|
|
232
|
+
list_attr = getattr(self, obj._GROUP_NAME)
|
|
233
|
+
if isinstance(list_attr, list):
|
|
234
|
+
list_attr.append(obj)
|
|
235
|
+
return True
|
|
236
|
+
return False
|
|
237
|
+
|
|
238
|
+
def add_list(self, obj_list: List[BaseObject]) -> List[BaseObject]:
|
|
239
|
+
"""Add multiple objects at once.
|
|
240
|
+
|
|
241
|
+
Attempts to add all objects in the provided list. Returns a list of any objects
|
|
242
|
+
that failed to be added (typically due to missing _GROUP_NAME).
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
obj_list: List of BaseObject instances to add
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
List of objects that failed to be added (empty list if all succeeded)
|
|
249
|
+
|
|
250
|
+
Example:
|
|
251
|
+
creator = Creator('Context1')
|
|
252
|
+
products = [Product({...}), Product({...})]
|
|
253
|
+
failed = creator.add_list(products)
|
|
254
|
+
if not failed:
|
|
255
|
+
print("All products added successfully")
|
|
256
|
+
"""
|
|
257
|
+
not_added: List[BaseObject] = []
|
|
258
|
+
for obj in obj_list:
|
|
259
|
+
if not self.add(obj):
|
|
260
|
+
not_added.append(obj)
|
|
261
|
+
return not_added
|
|
262
|
+
|
|
263
|
+
def to_bytes(self, encoding: str = 'utf-8') -> bytes:
|
|
264
|
+
"""Serialize the XML document to bytes.
|
|
265
|
+
|
|
266
|
+
Converts the generated ElementTree to bytes with optional encoding and
|
|
267
|
+
XML declaration.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
encoding: Character encoding for the output (default: 'utf-8')
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
Bytes representation of the XML document with declaration
|
|
274
|
+
|
|
275
|
+
Raises:
|
|
276
|
+
RuntimeError: If build() has not been called yet
|
|
277
|
+
|
|
278
|
+
Example:
|
|
279
|
+
creator = Creator('Context1')
|
|
280
|
+
creator.add(product)
|
|
281
|
+
creator.build()
|
|
282
|
+
xml_bytes = creator.to_bytes()
|
|
283
|
+
"""
|
|
284
|
+
if self.root is None:
|
|
285
|
+
raise RuntimeError("XML tree not built yet. Call build() first.")
|
|
286
|
+
return ET.tostring(
|
|
287
|
+
self.root,
|
|
288
|
+
encoding=encoding,
|
|
289
|
+
xml_declaration=True
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
def to_string(self, encoding: str = 'utf-8') -> str:
|
|
293
|
+
"""Serialize the XML document to a string.
|
|
294
|
+
|
|
295
|
+
Converts the generated ElementTree to a string representation.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
encoding: Character encoding to use (default: 'utf-8')
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
String representation of the XML document
|
|
302
|
+
|
|
303
|
+
Raises:
|
|
304
|
+
RuntimeError: If build() has not been called yet
|
|
305
|
+
|
|
306
|
+
Example:
|
|
307
|
+
creator = Creator('Context1')
|
|
308
|
+
creator.add(product)
|
|
309
|
+
creator.build()
|
|
310
|
+
xml_str = creator.to_string()
|
|
311
|
+
print(xml_str)
|
|
312
|
+
"""
|
|
313
|
+
return self.to_bytes(encoding).decode(encoding)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|