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
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Deletion models for STEP XML Client.
|
|
2
|
+
|
|
3
|
+
Defines entity and cross-reference deletion classes for removing items from STEP MDM.
|
|
4
|
+
Supports both full entity deletion and link severance operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
from . import BaseObject
|
|
9
|
+
|
|
10
|
+
class DeleteAsset(BaseObject):
|
|
11
|
+
"""Top-level deletion specification for assets.
|
|
12
|
+
|
|
13
|
+
Moves an asset to the recycle bin. The asset and all its associated data is marked for deletion.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
ID: Asset ID to delete
|
|
17
|
+
KeyValue: Optional key value reference
|
|
18
|
+
"""
|
|
19
|
+
_GROUP_NAME: str = 'deletedassets'
|
|
20
|
+
_TAG_NAME: str = 'DeleteAsset'
|
|
21
|
+
_ATTRIBUTE_NAMES: List[str] = ["ID"]
|
|
22
|
+
_TEXT_NAMES: List[str] = []
|
|
23
|
+
_CHILDREN_NAMES: List[str] = ["KeyValue"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DeleteProduct(BaseObject):
|
|
27
|
+
"""Top-level deletion specification for products.
|
|
28
|
+
|
|
29
|
+
Moves a product to the recycle bin. The product and all its associated data is marked for deletion.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
ID: Product ID to delete
|
|
33
|
+
KeyValue: Optional key value reference
|
|
34
|
+
"""
|
|
35
|
+
_GROUP_NAME: str = 'deletedproducts'
|
|
36
|
+
_TAG_NAME: str = 'DeleteProduct'
|
|
37
|
+
_ATTRIBUTE_NAMES: List[str] = ["ID"]
|
|
38
|
+
_TEXT_NAMES: List[str] = []
|
|
39
|
+
_CHILDREN_NAMES: List[str] = ["KeyValue"]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DeleteAssetCrossReference(BaseObject):
|
|
43
|
+
"""Deletion specification for asset cross-references.
|
|
44
|
+
|
|
45
|
+
Severs the link between an asset and a product while keeping both items intact.
|
|
46
|
+
The product remains but the asset reference is removed.
|
|
47
|
+
|
|
48
|
+
Attributes:
|
|
49
|
+
AssetID: Asset ID of the link to sever
|
|
50
|
+
Type: Link type
|
|
51
|
+
QualifierID: Optional qualifier
|
|
52
|
+
Changed: Whether changed
|
|
53
|
+
KeyValue: Optional key value reference
|
|
54
|
+
MetaData: Optional metadata
|
|
55
|
+
"""
|
|
56
|
+
_GROUP_NAME: Optional[str] = None # Used as child element only
|
|
57
|
+
_TAG_NAME: str = 'DeleteAssetCrossReference'
|
|
58
|
+
_ATTRIBUTE_NAMES: List[str] = ["AssetID", "Type", "QualifierID", "Changed"]
|
|
59
|
+
_TEXT_NAMES: List[str] = []
|
|
60
|
+
_CHILDREN_NAMES: List[str] = ["KeyValue", "MetaData"]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class DeleteProductCrossReference(BaseObject):
|
|
64
|
+
"""Delete/sever product link from another product while keeping both intact."""
|
|
65
|
+
_GROUP_NAME: Optional[str] = None # Used as child element only
|
|
66
|
+
_TAG_NAME: str = 'DeleteProductCrossReference'
|
|
67
|
+
_ATTRIBUTE_NAMES: List[str] = ["ProductID", "Type", "QualifierID", "MountLocation", "Changed"]
|
|
68
|
+
_TEXT_NAMES: List[str] = []
|
|
69
|
+
_CHILDREN_NAMES: List[str] = ["KeyValue", "MetaData"]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class DeleteClassificationCrossReference(BaseObject):
|
|
73
|
+
"""Delete/sever classification link while keeping classification intact."""
|
|
74
|
+
_GROUP_NAME: Optional[str] = None # Used as child element only
|
|
75
|
+
_TAG_NAME: str = 'DeleteClassificationCrossReference'
|
|
76
|
+
_ATTRIBUTE_NAMES: List[str] = ["ClassificationID", "Type", "QualifierID", "Changed"]
|
|
77
|
+
_TEXT_NAMES: List[str] = []
|
|
78
|
+
_CHILDREN_NAMES: List[str] = ["KeyValue", "MetaData"]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DeleteEntityCrossReference(BaseObject):
|
|
82
|
+
"""Delete/sever entity link while keeping entity intact."""
|
|
83
|
+
_GROUP_NAME: Optional[str] = None # Used as child element only
|
|
84
|
+
_TAG_NAME: str = 'DeleteEntityCrossReference'
|
|
85
|
+
_ATTRIBUTE_NAMES: List[str] = ["EntityID", "Type", "QualifierID", "Changed"]
|
|
86
|
+
_TEXT_NAMES: List[str] = []
|
|
87
|
+
_CHILDREN_NAMES: List[str] = ["KeyValue", "MetaData"]
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"""Entity model for STEP XML Client.
|
|
2
|
+
|
|
3
|
+
Defines the Entity class for representing generic MDM objects in STEP.
|
|
4
|
+
Entities provide a flexible structure for modeling various types of business objects beyond
|
|
5
|
+
products, classifications, and assets.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Optional, Any, Dict, TYPE_CHECKING
|
|
9
|
+
from . import BaseObject
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .relations import ProductCrossReference, ClassificationCrossReference, EntityCrossReference, AssetCrossReference
|
|
13
|
+
from .deletion import DeleteProductCrossReference, DeleteClassificationCrossReference, DeleteEntityCrossReference, DeleteAssetCrossReference
|
|
14
|
+
from .complex_elements import CurrentTasks, Task, Terms, Term
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Entity(BaseObject):
|
|
18
|
+
"""Entity model in STEP MDM.
|
|
19
|
+
|
|
20
|
+
Common ``data`` keys:
|
|
21
|
+
- ``ID``, ``ParentID``, ``UserTypeID``, ``QualifierID``
|
|
22
|
+
- ``Name``
|
|
23
|
+
- ``KeyValue`` / ``ParentKeyValue``
|
|
24
|
+
- ``Values`` and ``DataContainers``
|
|
25
|
+
|
|
26
|
+
Supports cross-references and also ``CurrentTasks`` / ``Terms`` children.
|
|
27
|
+
|
|
28
|
+
Usage examples:
|
|
29
|
+
Dict-first style::
|
|
30
|
+
|
|
31
|
+
entity = Entity({"ID": "E100", "UserTypeID": "UT_ENTITY"})
|
|
32
|
+
entity.add_product_reference(product_id="P100", type_="Owner")
|
|
33
|
+
entity.add_term({"TermsListID": "NET", "value": "Net 30"})
|
|
34
|
+
|
|
35
|
+
Pre-built object style::
|
|
36
|
+
|
|
37
|
+
from stepxmlclient.model import Task, Terms, Term
|
|
38
|
+
entity = Entity({"ID": "E101", "UserTypeID": "UT_ENTITY"})
|
|
39
|
+
entity.add_current_task(task_object=Task({
|
|
40
|
+
"STEPWorkflowID": "WF2",
|
|
41
|
+
"StateID": "S2",
|
|
42
|
+
"AssigneeID": "U2",
|
|
43
|
+
"AssignedToGroup": False,
|
|
44
|
+
"EntryTime": "2026-02-02T00:00:00Z",
|
|
45
|
+
}))
|
|
46
|
+
entity.add_term(terms_object=Terms({"Term": [Term({"TermsListID": "T1", "value": "Immediate"})]}))
|
|
47
|
+
"""
|
|
48
|
+
_GROUP_NAME: str = 'entities'
|
|
49
|
+
_TAG_NAME: str = 'Entity'
|
|
50
|
+
_ATTRIBUTE_NAMES: List[str] = ["ID", "ParentID", "UserTypeID", "QualifierID", "Changed", "Republished", "Selected", "Referenced"]
|
|
51
|
+
_TEXT_NAMES: List[str] = ["Name"]
|
|
52
|
+
_CHILDREN_NAMES: List[str] = [
|
|
53
|
+
"KeyValue",
|
|
54
|
+
"ParentKeyValue",
|
|
55
|
+
"Entity", # Nested entities
|
|
56
|
+
"DeleteSuppressedClassificationCrossReference",
|
|
57
|
+
"DeleteClassificationCrossReference",
|
|
58
|
+
"SuppressedClassificationCrossReference",
|
|
59
|
+
"ClassificationCrossReference",
|
|
60
|
+
"DeleteSuppressedProductCrossReference",
|
|
61
|
+
"DeleteProductCrossReference",
|
|
62
|
+
"SuppressedProductCrossReference",
|
|
63
|
+
"ProductCrossReference",
|
|
64
|
+
"DeleteSuppressedAssetCrossReference",
|
|
65
|
+
"DeleteAssetCrossReference",
|
|
66
|
+
"SuppressedAssetCrossReference",
|
|
67
|
+
"AssetCrossReference",
|
|
68
|
+
"DeleteSuppressedEntityCrossReference",
|
|
69
|
+
"DeleteEntityCrossReference",
|
|
70
|
+
"SuppressedEntityCrossReference",
|
|
71
|
+
"EntityCrossReference",
|
|
72
|
+
"SuppressedContextCrossReference",
|
|
73
|
+
"ContextCrossReference",
|
|
74
|
+
"SuppressedWorkspaceCrossReference",
|
|
75
|
+
"WorkspaceCrossReference",
|
|
76
|
+
"Values",
|
|
77
|
+
"DataContainers",
|
|
78
|
+
"CurrentTasks",
|
|
79
|
+
"Terms"
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
83
|
+
super().__init__(data)
|
|
84
|
+
# Initialize relation lists if not provided
|
|
85
|
+
for rel_name in ["ProductCrossReference", "DeleteProductCrossReference",
|
|
86
|
+
"SuppressedProductCrossReference", "DeleteSuppressedProductCrossReference",
|
|
87
|
+
"ClassificationCrossReference", "DeleteClassificationCrossReference",
|
|
88
|
+
"SuppressedClassificationCrossReference", "DeleteSuppressedClassificationCrossReference",
|
|
89
|
+
"EntityCrossReference", "DeleteEntityCrossReference",
|
|
90
|
+
"SuppressedEntityCrossReference", "DeleteSuppressedEntityCrossReference",
|
|
91
|
+
"AssetCrossReference", "DeleteAssetCrossReference",
|
|
92
|
+
"SuppressedAssetCrossReference", "DeleteSuppressedAssetCrossReference",
|
|
93
|
+
"ContextCrossReference", "SuppressedContextCrossReference",
|
|
94
|
+
"WorkspaceCrossReference", "SuppressedWorkspaceCrossReference",
|
|
95
|
+
"Values", "DataContainers", "CurrentTasks", "Terms"]:
|
|
96
|
+
if rel_name not in self._data:
|
|
97
|
+
self._data[rel_name] = []
|
|
98
|
+
|
|
99
|
+
# Initialize nested entities list
|
|
100
|
+
if "Entity" not in self._data:
|
|
101
|
+
self._data["Entity"] = []
|
|
102
|
+
|
|
103
|
+
# ===== Product Cross-Reference Methods =====
|
|
104
|
+
|
|
105
|
+
def add_product_reference(self, product_id: Optional[str] = None,
|
|
106
|
+
type_: Optional[str] = None,
|
|
107
|
+
qualifier_id: Optional[str] = None,
|
|
108
|
+
mount_location: Optional[str] = None,
|
|
109
|
+
ref_object: Optional['ProductCrossReference'] = None) -> None:
|
|
110
|
+
"""Add ``ProductCrossReference``.
|
|
111
|
+
|
|
112
|
+
Fields: ``ProductID``, ``Type``, ``QualifierID``, ``MountLocation``.
|
|
113
|
+
"""
|
|
114
|
+
from .relations import ProductCrossReference
|
|
115
|
+
|
|
116
|
+
if ref_object is not None:
|
|
117
|
+
ref = ref_object
|
|
118
|
+
else:
|
|
119
|
+
ref = ProductCrossReference({
|
|
120
|
+
"ProductID": product_id,
|
|
121
|
+
"Type": type_,
|
|
122
|
+
"QualifierID": qualifier_id,
|
|
123
|
+
"MountLocation": mount_location
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
if not isinstance(self._data["ProductCrossReference"], list):
|
|
127
|
+
self._data["ProductCrossReference"] = []
|
|
128
|
+
self._data["ProductCrossReference"].append(ref)
|
|
129
|
+
|
|
130
|
+
def delete_product_reference(self, product_id: Optional[str] = None,
|
|
131
|
+
type_: Optional[str] = None,
|
|
132
|
+
qualifier_id: Optional[str] = None,
|
|
133
|
+
mount_location: Optional[str] = None,
|
|
134
|
+
delete_ref_object: Optional['DeleteProductCrossReference'] = None) -> None:
|
|
135
|
+
"""Add ``DeleteProductCrossReference``.
|
|
136
|
+
|
|
137
|
+
Fields: ``ProductID``, ``Type``, ``QualifierID``, ``MountLocation``.
|
|
138
|
+
"""
|
|
139
|
+
from .deletion import DeleteProductCrossReference
|
|
140
|
+
|
|
141
|
+
if delete_ref_object is not None:
|
|
142
|
+
delete_ref = delete_ref_object
|
|
143
|
+
else:
|
|
144
|
+
delete_ref = DeleteProductCrossReference({
|
|
145
|
+
"ProductID": product_id,
|
|
146
|
+
"Type": type_,
|
|
147
|
+
"QualifierID": qualifier_id,
|
|
148
|
+
"MountLocation": mount_location
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
if not isinstance(self._data["DeleteProductCrossReference"], list):
|
|
152
|
+
self._data["DeleteProductCrossReference"] = []
|
|
153
|
+
self._data["DeleteProductCrossReference"].append(delete_ref)
|
|
154
|
+
|
|
155
|
+
# ===== Classification Cross-Reference Methods =====
|
|
156
|
+
|
|
157
|
+
def add_classification_reference(self, classification_id: Optional[str] = None,
|
|
158
|
+
type_: Optional[str] = None,
|
|
159
|
+
qualifier_id: Optional[str] = None,
|
|
160
|
+
mount_location: Optional[str] = None,
|
|
161
|
+
ref_object: Optional['ClassificationCrossReference'] = None) -> None:
|
|
162
|
+
"""Add ``ClassificationCrossReference``.
|
|
163
|
+
|
|
164
|
+
Fields: ``ClassificationID``, ``Type``, ``QualifierID``,
|
|
165
|
+
``MountLocation``.
|
|
166
|
+
"""
|
|
167
|
+
from .relations import ClassificationCrossReference
|
|
168
|
+
|
|
169
|
+
if ref_object is not None:
|
|
170
|
+
ref = ref_object
|
|
171
|
+
else:
|
|
172
|
+
ref = ClassificationCrossReference({
|
|
173
|
+
"ClassificationID": classification_id,
|
|
174
|
+
"Type": type_,
|
|
175
|
+
"QualifierID": qualifier_id,
|
|
176
|
+
"MountLocation": mount_location
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
if not isinstance(self._data["ClassificationCrossReference"], list):
|
|
180
|
+
self._data["ClassificationCrossReference"] = []
|
|
181
|
+
self._data["ClassificationCrossReference"].append(ref)
|
|
182
|
+
|
|
183
|
+
def delete_classification_reference(self, classification_id: Optional[str] = None,
|
|
184
|
+
type_: Optional[str] = None,
|
|
185
|
+
qualifier_id: Optional[str] = None,
|
|
186
|
+
mount_location: Optional[str] = None,
|
|
187
|
+
delete_ref_object: Optional['DeleteClassificationCrossReference'] = None) -> None:
|
|
188
|
+
"""Add ``DeleteClassificationCrossReference``.
|
|
189
|
+
|
|
190
|
+
Fields: ``ClassificationID``, ``Type``, ``QualifierID``,
|
|
191
|
+
``MountLocation``.
|
|
192
|
+
"""
|
|
193
|
+
from .deletion import DeleteClassificationCrossReference
|
|
194
|
+
|
|
195
|
+
if delete_ref_object is not None:
|
|
196
|
+
delete_ref = delete_ref_object
|
|
197
|
+
else:
|
|
198
|
+
delete_ref = DeleteClassificationCrossReference({
|
|
199
|
+
"ClassificationID": classification_id,
|
|
200
|
+
"Type": type_,
|
|
201
|
+
"QualifierID": qualifier_id,
|
|
202
|
+
"MountLocation": mount_location
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
if not isinstance(self._data["DeleteClassificationCrossReference"], list):
|
|
206
|
+
self._data["DeleteClassificationCrossReference"] = []
|
|
207
|
+
self._data["DeleteClassificationCrossReference"].append(delete_ref)
|
|
208
|
+
|
|
209
|
+
# ===== Entity Cross-Reference Methods =====
|
|
210
|
+
|
|
211
|
+
def add_entity_reference(self, entity_id: Optional[str] = None,
|
|
212
|
+
type_: Optional[str] = None,
|
|
213
|
+
qualifier_id: Optional[str] = None,
|
|
214
|
+
mount_location: Optional[str] = None,
|
|
215
|
+
ref_object: Optional['EntityCrossReference'] = None) -> None:
|
|
216
|
+
"""Add ``EntityCrossReference``.
|
|
217
|
+
|
|
218
|
+
Fields: ``EntityID``, ``Type``, ``QualifierID``, ``MountLocation``.
|
|
219
|
+
"""
|
|
220
|
+
from .relations import EntityCrossReference
|
|
221
|
+
|
|
222
|
+
if ref_object is not None:
|
|
223
|
+
ref = ref_object
|
|
224
|
+
else:
|
|
225
|
+
ref = EntityCrossReference({
|
|
226
|
+
"EntityID": entity_id,
|
|
227
|
+
"Type": type_,
|
|
228
|
+
"QualifierID": qualifier_id,
|
|
229
|
+
"MountLocation": mount_location
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
if not isinstance(self._data["EntityCrossReference"], list):
|
|
233
|
+
self._data["EntityCrossReference"] = []
|
|
234
|
+
self._data["EntityCrossReference"].append(ref)
|
|
235
|
+
|
|
236
|
+
def delete_entity_reference(self, entity_id: Optional[str] = None,
|
|
237
|
+
type_: Optional[str] = None,
|
|
238
|
+
qualifier_id: Optional[str] = None,
|
|
239
|
+
mount_location: Optional[str] = None,
|
|
240
|
+
delete_ref_object: Optional['DeleteEntityCrossReference'] = None) -> None:
|
|
241
|
+
"""Add ``DeleteEntityCrossReference``.
|
|
242
|
+
|
|
243
|
+
Fields: ``EntityID``, ``Type``, ``QualifierID``, ``MountLocation``.
|
|
244
|
+
"""
|
|
245
|
+
from .deletion import DeleteEntityCrossReference
|
|
246
|
+
|
|
247
|
+
if delete_ref_object is not None:
|
|
248
|
+
delete_ref = delete_ref_object
|
|
249
|
+
else:
|
|
250
|
+
delete_ref = DeleteEntityCrossReference({
|
|
251
|
+
"EntityID": entity_id,
|
|
252
|
+
"Type": type_,
|
|
253
|
+
"QualifierID": qualifier_id,
|
|
254
|
+
"MountLocation": mount_location
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
if not isinstance(self._data["DeleteEntityCrossReference"], list):
|
|
258
|
+
self._data["DeleteEntityCrossReference"] = []
|
|
259
|
+
self._data["DeleteEntityCrossReference"].append(delete_ref)
|
|
260
|
+
|
|
261
|
+
# ===== Asset Cross-Reference Methods =====
|
|
262
|
+
|
|
263
|
+
def add_asset_reference(self, asset_id: Optional[str] = None,
|
|
264
|
+
type_: Optional[str] = None,
|
|
265
|
+
qualifier_id: Optional[str] = None,
|
|
266
|
+
ref_object: Optional['AssetCrossReference'] = None) -> None:
|
|
267
|
+
"""Add ``AssetCrossReference``.
|
|
268
|
+
|
|
269
|
+
Fields: ``AssetID``, ``Type``, ``QualifierID``.
|
|
270
|
+
"""
|
|
271
|
+
from .relations import AssetCrossReference
|
|
272
|
+
|
|
273
|
+
if ref_object is not None:
|
|
274
|
+
ref = ref_object
|
|
275
|
+
else:
|
|
276
|
+
ref = AssetCrossReference({
|
|
277
|
+
"AssetID": asset_id,
|
|
278
|
+
"Type": type_,
|
|
279
|
+
"QualifierID": qualifier_id
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
if not isinstance(self._data["AssetCrossReference"], list):
|
|
283
|
+
self._data["AssetCrossReference"] = []
|
|
284
|
+
self._data["AssetCrossReference"].append(ref)
|
|
285
|
+
|
|
286
|
+
def delete_asset_reference(self, asset_id: Optional[str] = None,
|
|
287
|
+
type_: Optional[str] = None,
|
|
288
|
+
qualifier_id: Optional[str] = None,
|
|
289
|
+
delete_ref_object: Optional['DeleteAssetCrossReference'] = None) -> None:
|
|
290
|
+
"""Add ``DeleteAssetCrossReference``.
|
|
291
|
+
|
|
292
|
+
Fields: ``AssetID``, ``Type``, ``QualifierID``.
|
|
293
|
+
"""
|
|
294
|
+
from .deletion import DeleteAssetCrossReference
|
|
295
|
+
|
|
296
|
+
if delete_ref_object is not None:
|
|
297
|
+
delete_ref = delete_ref_object
|
|
298
|
+
else:
|
|
299
|
+
delete_ref = DeleteAssetCrossReference({
|
|
300
|
+
"AssetID": asset_id,
|
|
301
|
+
"Type": type_,
|
|
302
|
+
"QualifierID": qualifier_id
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
if not isinstance(self._data["DeleteAssetCrossReference"], list):
|
|
306
|
+
self._data["DeleteAssetCrossReference"] = []
|
|
307
|
+
self._data["DeleteAssetCrossReference"].append(delete_ref)
|
|
308
|
+
|
|
309
|
+
# ===== Nested Entity Methods =====
|
|
310
|
+
|
|
311
|
+
def add_nested_entity(self, entity: Optional['Entity'] = None,
|
|
312
|
+
**kwargs) -> None:
|
|
313
|
+
"""Add nested ``Entity`` object.
|
|
314
|
+
|
|
315
|
+
Pass either ``entity`` or kwargs for ``Entity(...)``.
|
|
316
|
+
"""
|
|
317
|
+
if entity is not None:
|
|
318
|
+
nested = entity
|
|
319
|
+
else:
|
|
320
|
+
nested = Entity(kwargs)
|
|
321
|
+
|
|
322
|
+
if not isinstance(self._data["Entity"], list):
|
|
323
|
+
self._data["Entity"] = []
|
|
324
|
+
self._data["Entity"].append(nested)
|
|
325
|
+
|
|
326
|
+
def add_current_task(self,
|
|
327
|
+
task_data: Optional[Dict[str, Any]] = None,
|
|
328
|
+
task_object: Optional['Task'] = None,
|
|
329
|
+
current_tasks_object: Optional['CurrentTasks'] = None) -> None:
|
|
330
|
+
"""Add ``CurrentTasks`` with task entries.
|
|
331
|
+
|
|
332
|
+
Task keys: ``STEPWorkflowID``, ``StateID``, ``AssigneeID``,
|
|
333
|
+
``AssignedToGroup``, ``EntryTime``, optional ``Deadline``, ``Priority``,
|
|
334
|
+
``StatusID``.
|
|
335
|
+
"""
|
|
336
|
+
from .complex_elements import CurrentTasks, Task
|
|
337
|
+
|
|
338
|
+
if current_tasks_object is not None:
|
|
339
|
+
entry: Any = current_tasks_object
|
|
340
|
+
else:
|
|
341
|
+
task = task_object or Task(task_data or {})
|
|
342
|
+
entry = CurrentTasks({"Task": [task]})
|
|
343
|
+
|
|
344
|
+
if not isinstance(self._data.get("CurrentTasks"), list):
|
|
345
|
+
self._data["CurrentTasks"] = []
|
|
346
|
+
self._data["CurrentTasks"].append(entry)
|
|
347
|
+
|
|
348
|
+
def add_term(self,
|
|
349
|
+
term_data: Optional[Dict[str, Any]] = None,
|
|
350
|
+
term_object: Optional['Term'] = None,
|
|
351
|
+
terms_object: Optional['Terms'] = None) -> None:
|
|
352
|
+
"""Add ``Terms`` with one or more term entries.
|
|
353
|
+
|
|
354
|
+
Term keys: ``TermsListID``, ``MinimumQuantity``, ``MaximumQuantity``,
|
|
355
|
+
``StartDate``, ``EndDate``, ``LeadTime``, ``UnitID``, ``LotSize`` and
|
|
356
|
+
optional text value via ``value``.
|
|
357
|
+
"""
|
|
358
|
+
from .complex_elements import Terms, Term
|
|
359
|
+
|
|
360
|
+
if terms_object is not None:
|
|
361
|
+
entry: Any = terms_object
|
|
362
|
+
else:
|
|
363
|
+
term = term_object or Term(term_data or {})
|
|
364
|
+
entry = Terms({"Term": [term]})
|
|
365
|
+
|
|
366
|
+
if not isinstance(self._data.get("Terms"), list):
|
|
367
|
+
self._data["Terms"] = []
|
|
368
|
+
self._data["Terms"].append(entry)
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""Metadata and configuration models for STEP XML Client.
|
|
2
|
+
|
|
3
|
+
Defines metadata and configuration classes for STEP MDM systems including user types,
|
|
4
|
+
contexts, qualifiers, dimensions, tags, units, and other configuration elements.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Optional, Any, Dict, TYPE_CHECKING
|
|
8
|
+
from . import BaseObject
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class UserType(BaseObject):
|
|
15
|
+
"""User type - object type definition in STEP MDM.
|
|
16
|
+
|
|
17
|
+
User types define customizable object classifications with attributes, validation rules,
|
|
18
|
+
icons, and category information. User types control the structure and behavior of
|
|
19
|
+
products, assets, classifications, and entities.
|
|
20
|
+
|
|
21
|
+
Supports:
|
|
22
|
+
- Multiple names (multi-language)
|
|
23
|
+
- Custom icons and templates
|
|
24
|
+
- Attribute and dimension associations
|
|
25
|
+
- Validation rules
|
|
26
|
+
- Category classification
|
|
27
|
+
- Revisability and link policies
|
|
28
|
+
- Boolean state tracking (Selected, Referenced, Changed, Deleted)
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
ID: Unique user type identifier
|
|
32
|
+
AllowOverlappingTerms: Whether overlapping terms are allowed
|
|
33
|
+
AllowQuarkTemplate: Support for Quark templates
|
|
34
|
+
AllowInDesignTemplate: Support for InDesign templates
|
|
35
|
+
Revisability: Revision tracking policy
|
|
36
|
+
IsCategory: Whether this type represents a category
|
|
37
|
+
DefaultProfileConfiguration: Default profile configuration
|
|
38
|
+
ClassificationOwnsProductLinks: Classification ownership semantics
|
|
39
|
+
NamePattern: Pattern for naming instances
|
|
40
|
+
IDPattern: Pattern for ID generation
|
|
41
|
+
ManuallySorted: Whether instances are manually sorted
|
|
42
|
+
ReferenceTargetLockPolicy: Link policy
|
|
43
|
+
Name: User type name (localized)
|
|
44
|
+
Icon: Icon representation
|
|
45
|
+
VisibleTermFields: Visible fields for search
|
|
46
|
+
MetaData: Metadata
|
|
47
|
+
DimensionLink: Dimension associations
|
|
48
|
+
UserTypeLink: Links to other user types
|
|
49
|
+
AttributeLink: Attribute associations
|
|
50
|
+
Validation: Validation rules
|
|
51
|
+
MIMEType: Associated MIME types
|
|
52
|
+
"""
|
|
53
|
+
_GROUP_NAME: str = 'usertypes'
|
|
54
|
+
_TAG_NAME: str = 'UserType'
|
|
55
|
+
_ATTRIBUTE_NAMES: List[str] = [
|
|
56
|
+
"ID", "AllowOverlappingTerms", "AllowQuarkTemplate",
|
|
57
|
+
"AllowInDesignTemplate", "Revisability", "IsCategory",
|
|
58
|
+
"DefaultProfileConfiguration", "ClassificationOwnsProductLinks",
|
|
59
|
+
"NamePattern", "IDPattern", "ManuallySorted",
|
|
60
|
+
"ReferenceTargetLockPolicy", "Selected", "Referenced",
|
|
61
|
+
"Changed", "Deleted"
|
|
62
|
+
]
|
|
63
|
+
_TEXT_NAMES: List[str] = ["Name"]
|
|
64
|
+
_CHILDREN_NAMES: List[str] = [
|
|
65
|
+
"Icon",
|
|
66
|
+
"VisibleTermFields",
|
|
67
|
+
"MetaData",
|
|
68
|
+
"DimensionLink",
|
|
69
|
+
"UserTypeLink",
|
|
70
|
+
"AttributeLink",
|
|
71
|
+
"Validation",
|
|
72
|
+
"MIMEType"
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
76
|
+
super().__init__(data)
|
|
77
|
+
# Initialize link lists if not provided
|
|
78
|
+
for link_name in ["DimensionLink", "UserTypeLink", "AttributeLink", "MIMEType"]:
|
|
79
|
+
if link_name not in self._data:
|
|
80
|
+
self._data[link_name] = []
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class LinkType(BaseObject):
|
|
84
|
+
"""LinkType - defines the type of cross-reference between objects.
|
|
85
|
+
|
|
86
|
+
Link types specify valid relationship types (e.g., CA=Classification-to-Attribute,
|
|
87
|
+
PA=Product-to-Attribute) for organizing cross-references.
|
|
88
|
+
|
|
89
|
+
Simple metadata element with minimal structure.
|
|
90
|
+
"""
|
|
91
|
+
_GROUP_NAME: str = 'linktypes'
|
|
92
|
+
_TAG_NAME: str = 'LinkType'
|
|
93
|
+
_ATTRIBUTE_NAMES: List[str] = ["LinkTypeID"]
|
|
94
|
+
_TEXT_NAMES: List[str] = []
|
|
95
|
+
_CHILDREN_NAMES: List[str] = []
|
|
96
|
+
|
|
97
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
98
|
+
super().__init__(data)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class Tag(BaseObject):
|
|
102
|
+
"""Tag - flexible categorization element independent of hierarchies.
|
|
103
|
+
|
|
104
|
+
Tags enable custom classification and filtering of objects
|
|
105
|
+
outside the standard product/classification hierarchies.
|
|
106
|
+
|
|
107
|
+
Supports:
|
|
108
|
+
- Multi-language names
|
|
109
|
+
- Metadata tracking
|
|
110
|
+
"""
|
|
111
|
+
_GROUP_NAME: str = 'tags'
|
|
112
|
+
_TAG_NAME: str = 'Tag'
|
|
113
|
+
_ATTRIBUTE_NAMES: List[str] = ["ID"]
|
|
114
|
+
_TEXT_NAMES: List[str] = ["Name"]
|
|
115
|
+
_CHILDREN_NAMES: List[str] = ["MetaData"]
|
|
116
|
+
|
|
117
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
118
|
+
super().__init__(data)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class TagGroup(BaseObject):
|
|
122
|
+
"""TagGroup - hierarchical grouping of tags.
|
|
123
|
+
|
|
124
|
+
Organizes tags into logical collections with parent/child relationships.
|
|
125
|
+
|
|
126
|
+
Supports:
|
|
127
|
+
- Nested tag groups (hierarchies)
|
|
128
|
+
- Multi-language names
|
|
129
|
+
- Tag collection
|
|
130
|
+
- Metadata tracking
|
|
131
|
+
"""
|
|
132
|
+
_GROUP_NAME: str = 'taggroups'
|
|
133
|
+
_TAG_NAME: str = 'TagGroup'
|
|
134
|
+
_ATTRIBUTE_NAMES: List[str] = ["ID"]
|
|
135
|
+
_TEXT_NAMES: List[str] = ["Name"]
|
|
136
|
+
_CHILDREN_NAMES: List[str] = ["MetaData", "TagGroup", "Tag"]
|
|
137
|
+
|
|
138
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
139
|
+
super().__init__(data)
|
|
140
|
+
# Initialize nested tag groups and tags lists
|
|
141
|
+
if "TagGroup" not in self._data:
|
|
142
|
+
self._data["TagGroup"] = []
|
|
143
|
+
if "Tag" not in self._data:
|
|
144
|
+
self._data["Tag"] = []
|
|
145
|
+
|
|
146
|
+
def add_nested_tag_group(self, tag_group: Optional['TagGroup'] = None,
|
|
147
|
+
**kwargs) -> None:
|
|
148
|
+
"""Add nested tag group.
|
|
149
|
+
|
|
150
|
+
Can be called two ways:
|
|
151
|
+
1. With object: add_nested_tag_group(tag_group=group_obj)
|
|
152
|
+
2. With parameters: add_nested_tag_group(ID="TG002", Name="Nested Group")
|
|
153
|
+
"""
|
|
154
|
+
if tag_group is not None:
|
|
155
|
+
group = tag_group
|
|
156
|
+
else:
|
|
157
|
+
group = TagGroup(kwargs)
|
|
158
|
+
|
|
159
|
+
if not isinstance(self._data["TagGroup"], list):
|
|
160
|
+
self._data["TagGroup"] = []
|
|
161
|
+
self._data["TagGroup"].append(group)
|
|
162
|
+
|
|
163
|
+
def add_tag(self, tag: Optional['Tag'] = None,
|
|
164
|
+
**kwargs) -> None:
|
|
165
|
+
"""Add a tag to this group.
|
|
166
|
+
|
|
167
|
+
Can be called two ways:
|
|
168
|
+
1. With object: add_tag(tag=tag_obj)
|
|
169
|
+
2. With parameters: add_tag(ID="T001", Name="Tag Name")
|
|
170
|
+
"""
|
|
171
|
+
if tag is not None:
|
|
172
|
+
t = tag
|
|
173
|
+
else:
|
|
174
|
+
t = Tag(kwargs)
|
|
175
|
+
|
|
176
|
+
if not isinstance(self._data["Tag"], list):
|
|
177
|
+
self._data["Tag"] = []
|
|
178
|
+
self._data["Tag"].append(t)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class Unit(BaseObject):
|
|
182
|
+
"""Unit - defines a measurement unit for quantitative attributes.
|
|
183
|
+
|
|
184
|
+
Units represent measurement standards (meters, kilograms, liters, etc.)
|
|
185
|
+
used for quantitative attribute values.
|
|
186
|
+
|
|
187
|
+
Supports:
|
|
188
|
+
- Unit symbol (m, kg, l, etc.)
|
|
189
|
+
- Conversion formula to base unit
|
|
190
|
+
- Metadata tracking
|
|
191
|
+
"""
|
|
192
|
+
_GROUP_NAME: str = 'units'
|
|
193
|
+
_TAG_NAME: str = 'Unit'
|
|
194
|
+
_ATTRIBUTE_NAMES: List[str] = ["ID", "Name", "Symbol", "Formula"]
|
|
195
|
+
_TEXT_NAMES: List[str] = []
|
|
196
|
+
_CHILDREN_NAMES: List[str] = ["MetaData"]
|
|
197
|
+
|
|
198
|
+
def __init__(self, data: Dict[str, Any]) -> None:
|
|
199
|
+
super().__init__(data)
|