logs-py 4.0.7__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.
- LOGS/Auxiliary/CheckClassName.py +1075 -0
- LOGS/Auxiliary/Constants.py +99 -0
- LOGS/Auxiliary/CustomEntityClassGenerator.py +254 -0
- LOGS/Auxiliary/CustomFieldClassGenerator.py +115 -0
- LOGS/Auxiliary/CustomFieldValueTypeChecker.py +168 -0
- LOGS/Auxiliary/CustomSectionClassGenerator.py +113 -0
- LOGS/Auxiliary/CustomTypeClassGenerator.py +147 -0
- LOGS/Auxiliary/DateTimeConverter.py +66 -0
- LOGS/Auxiliary/Decorators.py +109 -0
- LOGS/Auxiliary/Exceptions.py +341 -0
- LOGS/Auxiliary/LOGSErrorResponse.py +89 -0
- LOGS/Auxiliary/MinimalModelGenerator.py +236 -0
- LOGS/Auxiliary/ParameterHelper.py +56 -0
- LOGS/Auxiliary/ReplaceMessage.py +13 -0
- LOGS/Auxiliary/Tools.py +432 -0
- LOGS/Auxiliary/__init__.py +15 -0
- LOGS/Converter/Conversion.py +248 -0
- LOGS/Converter/Converter.py +96 -0
- LOGS/Converter/ConverterParameter.py +88 -0
- LOGS/Converter/DateTimeRange.py +58 -0
- LOGS/Converter/ExportParameters.py +89 -0
- LOGS/Converter/__init__.py +13 -0
- LOGS/Entities/Attachment.py +84 -0
- LOGS/Entities/AttachmentMinimal.py +8 -0
- LOGS/Entities/AttachmentRequestParameter.py +42 -0
- LOGS/Entities/Attachments.py +53 -0
- LOGS/Entities/AutoloadFileInfo.py +12 -0
- LOGS/Entities/AutoloadStatusError.py +7 -0
- LOGS/Entities/AxisNaming.py +33 -0
- LOGS/Entities/AxisZoom.py +33 -0
- LOGS/Entities/Bridge.py +165 -0
- LOGS/Entities/BridgeClientInfo.py +93 -0
- LOGS/Entities/BridgeMinimal.py +8 -0
- LOGS/Entities/BridgeRequestParameter.py +49 -0
- LOGS/Entities/BridgeType.py +7 -0
- LOGS/Entities/Bridges.py +12 -0
- LOGS/Entities/CustomField.py +243 -0
- LOGS/Entities/CustomFieldMinimal.py +8 -0
- LOGS/Entities/CustomFieldModels.py +111 -0
- LOGS/Entities/CustomFieldRequestParameter.py +69 -0
- LOGS/Entities/CustomFieldSearchQuery.py +40 -0
- LOGS/Entities/CustomFields.py +12 -0
- LOGS/Entities/CustomType.py +212 -0
- LOGS/Entities/CustomTypeMinimal.py +8 -0
- LOGS/Entities/CustomTypeRequestParameter.py +60 -0
- LOGS/Entities/CustomTypeSection.py +63 -0
- LOGS/Entities/CustomTypes.py +12 -0
- LOGS/Entities/DataFormat.py +97 -0
- LOGS/Entities/DataFormatInstrument.py +18 -0
- LOGS/Entities/DataFormatInstrumentMinimal.py +8 -0
- LOGS/Entities/DataFormatInstrumentRequestParameter.py +17 -0
- LOGS/Entities/DataFormatInstruments.py +16 -0
- LOGS/Entities/DataFormatMinimal.py +18 -0
- LOGS/Entities/DataFormatRequestParameter.py +21 -0
- LOGS/Entities/DataFormats.py +12 -0
- LOGS/Entities/DataSource.py +218 -0
- LOGS/Entities/DataSourceConnectionStatus.py +12 -0
- LOGS/Entities/DataSourceMinimal.py +8 -0
- LOGS/Entities/DataSourceRequestParameter.py +57 -0
- LOGS/Entities/DataSourceStatus.py +108 -0
- LOGS/Entities/DataSourceStatusIterator.py +16 -0
- LOGS/Entities/DataSourceStatusRequestParameter.py +31 -0
- LOGS/Entities/DataSources.py +12 -0
- LOGS/Entities/Dataset.py +439 -0
- LOGS/Entities/DatasetBase.py +196 -0
- LOGS/Entities/DatasetCreator.py +148 -0
- LOGS/Entities/DatasetInfo.py +147 -0
- LOGS/Entities/DatasetMatchTypes.py +157 -0
- LOGS/Entities/DatasetMatching.py +196 -0
- LOGS/Entities/DatasetMinimal.py +8 -0
- LOGS/Entities/DatasetModels.py +33 -0
- LOGS/Entities/DatasetRequestParameter.py +92 -0
- LOGS/Entities/DatasetTemplate.py +23 -0
- LOGS/Entities/DatasetUploadParameter.py +14 -0
- LOGS/Entities/Datasets.py +142 -0
- LOGS/Entities/Datatrack.py +179 -0
- LOGS/Entities/DatatrackFormattedTable.py +25 -0
- LOGS/Entities/DatatrackGeneric.py +34 -0
- LOGS/Entities/DatatrackImage.py +25 -0
- LOGS/Entities/DatatrackNumericArray.py +30 -0
- LOGS/Entities/DatatrackNumericMatrix.py +98 -0
- LOGS/Entities/Entities.py +71 -0
- LOGS/Entities/EntitiesRequestParameter.py +18 -0
- LOGS/Entities/EntityOriginWriteModelWithId.py +15 -0
- LOGS/Entities/FileEntry.py +138 -0
- LOGS/Entities/FileExcludePattern.py +8 -0
- LOGS/Entities/FormatMetaData.py +56 -0
- LOGS/Entities/FormattedTable/DatatypeFormattedTable.py +135 -0
- LOGS/Entities/FormattedTable/DatatypeFormattedTableCell.py +108 -0
- LOGS/Entities/FormattedTable/DatatypeFormattedTableSettings.py +11 -0
- LOGS/Entities/FormattedTable/__init__.py +9 -0
- LOGS/Entities/HierarchyLeaf.py +15 -0
- LOGS/Entities/HierarchyNode.py +40 -0
- LOGS/Entities/ILiteraryTypedEntity.py +19 -0
- LOGS/Entities/InventoryItem.py +102 -0
- LOGS/Entities/InventoryItemMinimal.py +25 -0
- LOGS/Entities/InventoryItemRequestParameter.py +58 -0
- LOGS/Entities/InventoryItems.py +12 -0
- LOGS/Entities/LabNotebook.py +33 -0
- LOGS/Entities/LabNotebookEntries.py +16 -0
- LOGS/Entities/LabNotebookEntry.py +106 -0
- LOGS/Entities/LabNotebookEntryContent/BasicAttribute.py +15 -0
- LOGS/Entities/LabNotebookEntryContent/EntityAttribute.py +85 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentBlockquote.py +13 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentBulletList.py +17 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentCallout.py +40 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentContentPlaceholderNode.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentConverter.py +207 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentDocument.py +8 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentEntity.py +13 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentEntityMention.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentHeading.py +33 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentHorizontalRule.py +12 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentItem.py +37 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentListItem.py +49 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentOrderedList.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentParagraph.py +13 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTable.py +17 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTableCell.py +40 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTableRow.py +8 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTaskList.py +17 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentTaskListItem.py +31 -0
- LOGS/Entities/LabNotebookEntryContent/EntryContentText.py +33 -0
- LOGS/Entities/LabNotebookEntryContent/IEntryContentWithAttribute.py +23 -0
- LOGS/Entities/LabNotebookEntryContent/IEntryContentWithContent.py +38 -0
- LOGS/Entities/LabNotebookEntryContent/IEntryContentWithTextAttribute.py +16 -0
- LOGS/Entities/LabNotebookEntryContent/TextAttribute.py +46 -0
- LOGS/Entities/LabNotebookEntryContent/TextMarkAtributes.py +64 -0
- LOGS/Entities/LabNotebookEntryContent/TextMarkConverter.py +45 -0
- LOGS/Entities/LabNotebookEntryContent/TextMarks.py +71 -0
- LOGS/Entities/LabNotebookEntryContent/__init__.py +34 -0
- LOGS/Entities/LabNotebookEntryMinimal.py +8 -0
- LOGS/Entities/LabNotebookEntryRequestParameter.py +59 -0
- LOGS/Entities/LabNotebookExperiment.py +58 -0
- LOGS/Entities/LabNotebookExperimentMinimal.py +8 -0
- LOGS/Entities/LabNotebookExperimentRequestParameter.py +52 -0
- LOGS/Entities/LabNotebookExperiments.py +16 -0
- LOGS/Entities/LabNotebookMinimal.py +8 -0
- LOGS/Entities/LabNotebookModels.py +14 -0
- LOGS/Entities/LabNotebookRequestParameter.py +42 -0
- LOGS/Entities/LabNotebookTemplate.py +42 -0
- LOGS/Entities/LabNotebookTemplateMinimal.py +8 -0
- LOGS/Entities/LabNotebookTemplateRequestParameter.py +38 -0
- LOGS/Entities/LabNotebookTemplates.py +16 -0
- LOGS/Entities/LabNotebooks.py +12 -0
- LOGS/Entities/Method.py +66 -0
- LOGS/Entities/MethodMinimal.py +8 -0
- LOGS/Entities/MethodRequestParameter.py +16 -0
- LOGS/Entities/Methods.py +12 -0
- LOGS/Entities/Origin.py +53 -0
- LOGS/Entities/OriginMinimal.py +8 -0
- LOGS/Entities/OriginRequestParameter.py +28 -0
- LOGS/Entities/Origins.py +12 -0
- LOGS/Entities/ParserLog.py +49 -0
- LOGS/Entities/Permission.py +9 -0
- LOGS/Entities/Person.py +145 -0
- LOGS/Entities/PersonCategory.py +12 -0
- LOGS/Entities/PersonMinimal.py +8 -0
- LOGS/Entities/PersonRequestParameter.py +58 -0
- LOGS/Entities/Persons.py +12 -0
- LOGS/Entities/Project.py +52 -0
- LOGS/Entities/ProjectMinimal.py +8 -0
- LOGS/Entities/ProjectPersonPermission.py +102 -0
- LOGS/Entities/ProjectRequestParameter.py +58 -0
- LOGS/Entities/Projects.py +12 -0
- LOGS/Entities/Role.py +94 -0
- LOGS/Entities/RoleMinimal.py +8 -0
- LOGS/Entities/RoleRequestParameter.py +40 -0
- LOGS/Entities/Roles.py +12 -0
- LOGS/Entities/RunState.py +9 -0
- LOGS/Entities/Sample.py +53 -0
- LOGS/Entities/SampleMinimal.py +8 -0
- LOGS/Entities/SampleRequestParameter.py +54 -0
- LOGS/Entities/Samples.py +12 -0
- LOGS/Entities/SharedContent.py +87 -0
- LOGS/Entities/SharedContentMinimal.py +8 -0
- LOGS/Entities/SharedContentRequestParameter.py +38 -0
- LOGS/Entities/SharedContents.py +12 -0
- LOGS/Entities/Signature.py +60 -0
- LOGS/Entities/Track.py +93 -0
- LOGS/Entities/TrackData.py +20 -0
- LOGS/Entities/TrackImage.py +21 -0
- LOGS/Entities/TrackImageData.py +20 -0
- LOGS/Entities/TrackMatrix.py +28 -0
- LOGS/Entities/TrackMatrixData.py +22 -0
- LOGS/Entities/TrackSettings.py +55 -0
- LOGS/Entities/TrackTable.py +21 -0
- LOGS/Entities/TrackTableData.py +22 -0
- LOGS/Entities/TrackXY.py +40 -0
- LOGS/Entities/TrackXYComplex.py +51 -0
- LOGS/Entities/TrackXYComplexData.py +50 -0
- LOGS/Entities/TrackXYData.py +31 -0
- LOGS/Entities/Vendor.py +40 -0
- LOGS/Entities/VendorMinimal.py +8 -0
- LOGS/Entities/VendorRequestParameter.py +17 -0
- LOGS/Entities/Vendors.py +12 -0
- LOGS/Entities/__init__.py +118 -0
- LOGS/Entity/ConnectedEntity.py +170 -0
- LOGS/Entity/Entity.py +203 -0
- LOGS/Entity/EntityConnector.py +70 -0
- LOGS/Entity/EntityIterator.py +263 -0
- LOGS/Entity/EntityMinimal.py +141 -0
- LOGS/Entity/EntityMinimalWithIntId.py +36 -0
- LOGS/Entity/EntityMinimalWithStrId.py +36 -0
- LOGS/Entity/EntityMinimalWithType.py +47 -0
- LOGS/Entity/EntityRequestParameter.py +104 -0
- LOGS/Entity/EntitySortBy.py +69 -0
- LOGS/Entity/EntityWithIntId.py +26 -0
- LOGS/Entity/EntityWithStrId.py +26 -0
- LOGS/Entity/IGenericEntityOrderBy.py +55 -0
- LOGS/Entity/IdIterator.py +207 -0
- LOGS/Entity/SerializableContent.py +834 -0
- LOGS/Entity/__init__.py +23 -0
- LOGS/Interfaces/ICustomFieldValue.py +92 -0
- LOGS/Interfaces/ICustomSectionValue.py +161 -0
- LOGS/Interfaces/ICustomTypeValue.py +152 -0
- LOGS/Interfaces/ICustomValue.py +28 -0
- LOGS/Interfaces/IEntityInterface.py +7 -0
- LOGS/Interfaces/IEntryRecord.py +57 -0
- LOGS/Interfaces/IHierarchicalEntity.py +41 -0
- LOGS/Interfaces/IHierarchyType.py +63 -0
- LOGS/Interfaces/ILockableEntity.py +52 -0
- LOGS/Interfaces/IModificationRecord.py +56 -0
- LOGS/Interfaces/INamedEntity.py +25 -0
- LOGS/Interfaces/IOwnedEntity.py +27 -0
- LOGS/Interfaces/IPaginationRequest.py +11 -0
- LOGS/Interfaces/IPermissionedEntity.py +72 -0
- LOGS/Interfaces/IProjectBased.py +27 -0
- LOGS/Interfaces/ISessionedEntity.py +59 -0
- LOGS/Interfaces/ISignableEntity.py +49 -0
- LOGS/Interfaces/ISoftDeletable.py +28 -0
- LOGS/Interfaces/ITypedEntity.py +129 -0
- LOGS/Interfaces/IUniqueEntity.py +61 -0
- LOGS/Interfaces/IVersionedEntity.py +39 -0
- LOGS/Interfaces/__init__.py +7 -0
- LOGS/LOGS.py +1436 -0
- LOGS/LOGSConnection.py +647 -0
- LOGS/LOGSOptions.py +11 -0
- LOGS/Parameters/Color.py +92 -0
- LOGS/Parameters/ParameterBase.py +55 -0
- LOGS/Parameters/ParameterConverter.py +24 -0
- LOGS/Parameters/ParameterElement.py +99 -0
- LOGS/Parameters/ParameterList.py +52 -0
- LOGS/Parameters/ParameterTable.py +64 -0
- LOGS/Parameters/__init__.py +13 -0
- LOGS/ServerMetaData.py +120 -0
- LOGS/__init__.py +12 -0
- logs_py-4.0.7.dist-info/METADATA +51 -0
- logs_py-4.0.7.dist-info/RECORD +251 -0
- logs_py-4.0.7.dist-info/WHEEL +5 -0
- logs_py-4.0.7.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from base64 import b64encode
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Type, cast
|
|
3
|
+
|
|
4
|
+
from LOGS.Auxiliary.CheckClassName import CheckClassName
|
|
5
|
+
from LOGS.Auxiliary.CustomFieldClassGenerator import CustomFieldClassGenerator
|
|
6
|
+
from LOGS.Auxiliary.Tools import Tools
|
|
7
|
+
from LOGS.Interfaces.ICustomSectionValue import ICustomSectionValue
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from LOGS.Entities.CustomTypeSection import CustomTypeSection
|
|
11
|
+
from LOGS.LOGSConnection import LOGSConnection
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CustomSectionClassGenerator:
|
|
15
|
+
|
|
16
|
+
_classCache: Dict[str, Type["ICustomSectionValue"]] = {}
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def _getCacheKey(cls, customTypeSection: str, connection: "LOGSConnection") -> str:
|
|
20
|
+
url = connection.getEndpointUrl(["custom_type_sections", customTypeSection])
|
|
21
|
+
return b64encode(url.encode()).decode()
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def generate(
|
|
25
|
+
cls,
|
|
26
|
+
section: "CustomTypeSection",
|
|
27
|
+
customTypeId: int,
|
|
28
|
+
sectionIndex: int,
|
|
29
|
+
connection: "LOGSConnection",
|
|
30
|
+
fieldName: Optional[str] = None,
|
|
31
|
+
) -> Type["ICustomSectionValue"]:
|
|
32
|
+
|
|
33
|
+
if not customTypeId >= 0:
|
|
34
|
+
raise ValueError(
|
|
35
|
+
f"Section customTypeId is missing for section in field '{fieldName}'."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if not sectionIndex >= 0:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
f"Section index is missing for section {sectionIndex} in field '{fieldName}'."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
id = ICustomSectionValue._generateId(customTypeId, sectionIndex)
|
|
44
|
+
cacheId = cls._getCacheKey(id, connection)
|
|
45
|
+
if cacheId in cls._classCache:
|
|
46
|
+
return cls._classCache[cacheId]
|
|
47
|
+
|
|
48
|
+
customFields = (
|
|
49
|
+
[
|
|
50
|
+
CustomFieldClassGenerator.generate(
|
|
51
|
+
customFieldId=c.id, fieldName=fieldName, connection=connection
|
|
52
|
+
)
|
|
53
|
+
for c in section.customFields
|
|
54
|
+
if c and c.id
|
|
55
|
+
]
|
|
56
|
+
if section.customFields
|
|
57
|
+
else []
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
name = (
|
|
61
|
+
CheckClassName.sanitizeClassName(section.name)
|
|
62
|
+
if section.name
|
|
63
|
+
else f"Section_TypeID{customTypeId}_Index{sectionIndex}"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
module = ".".join(
|
|
67
|
+
ICustomSectionValue.__module__.split(".")[:-1]
|
|
68
|
+
+ ["GeneratedCustomSectionValues"],
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
class CustomFieldProperty:
|
|
72
|
+
def __init__(self, name: str):
|
|
73
|
+
self.name = name
|
|
74
|
+
|
|
75
|
+
def __get__(self, instance: ICustomSectionValue, _):
|
|
76
|
+
return instance.getField(self.name)
|
|
77
|
+
|
|
78
|
+
def __set__(self, instance: ICustomSectionValue, value):
|
|
79
|
+
instance.setField(self.name, value)
|
|
80
|
+
|
|
81
|
+
def __init__(self, ref=None):
|
|
82
|
+
cast(Any, type(self).__bases__[0]).__init__(self, ref)
|
|
83
|
+
|
|
84
|
+
typeDict = {
|
|
85
|
+
"__init__": __init__,
|
|
86
|
+
"__module__": module,
|
|
87
|
+
"__doc__": f"This class represents the value of the LOGS custom field '{section.name}' (TypeID: {customTypeId} Index: {sectionIndex} )",
|
|
88
|
+
"_name": section.name,
|
|
89
|
+
"_customTypeId": customTypeId,
|
|
90
|
+
"_sectionIndex": sectionIndex,
|
|
91
|
+
"_fieldNames": [],
|
|
92
|
+
"_fieldTypes": {},
|
|
93
|
+
"_fieldIds": {},
|
|
94
|
+
"_noSerialize": ["fieldNames"],
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for f in customFields:
|
|
98
|
+
attrName = Tools.resolveKeyConflictWithPrefix(f.__name__, "_", typeDict)
|
|
99
|
+
|
|
100
|
+
typeDict["_" + attrName] = None
|
|
101
|
+
typeDict[attrName] = CustomFieldProperty(attrName)
|
|
102
|
+
typeDict["_fieldNames"].append(attrName)
|
|
103
|
+
typeDict["_fieldTypes"][attrName] = f
|
|
104
|
+
typeDict["_fieldIds"][f._id] = attrName
|
|
105
|
+
|
|
106
|
+
typeDict["_noSerialize"] += typeDict["_fieldNames"]
|
|
107
|
+
|
|
108
|
+
newClass: Type[ICustomSectionValue] = type(
|
|
109
|
+
name,
|
|
110
|
+
(ICustomSectionValue,),
|
|
111
|
+
typeDict,
|
|
112
|
+
)
|
|
113
|
+
return newClass
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from base64 import b64encode
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Type, TypeVar, Union, cast
|
|
3
|
+
|
|
4
|
+
from LOGS.Auxiliary.CheckClassName import CheckClassName
|
|
5
|
+
from LOGS.Auxiliary.Constants import Constants
|
|
6
|
+
from LOGS.Auxiliary.CustomSectionClassGenerator import CustomSectionClassGenerator
|
|
7
|
+
from LOGS.Auxiliary.Exceptions import EntityFetchingException
|
|
8
|
+
from LOGS.Auxiliary.Tools import Tools
|
|
9
|
+
from LOGS.Interfaces.ICustomSectionValue import ICustomSectionValue
|
|
10
|
+
from LOGS.Interfaces.ICustomTypeValue import ICustomTypeValue
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from LOGS.Entities.CustomType import CustomType
|
|
14
|
+
from LOGS.LOGSConnection import LOGSConnection
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_T = TypeVar("_T")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CustomTypeClassGenerator:
|
|
21
|
+
|
|
22
|
+
_classCache: Dict[str, Type["ICustomTypeValue"]] = {}
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def _getCacheKey(cls, customTypeOrId: int, connection: "LOGSConnection") -> str:
|
|
26
|
+
url = connection.getEndpointUrl(
|
|
27
|
+
["custom_types", str(customTypeOrId)],
|
|
28
|
+
)
|
|
29
|
+
return b64encode(url.encode()).decode()
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def generate(
|
|
33
|
+
cls,
|
|
34
|
+
customType: "CustomType",
|
|
35
|
+
connection: "LOGSConnection",
|
|
36
|
+
fieldName: Optional[str] = None,
|
|
37
|
+
):
|
|
38
|
+
|
|
39
|
+
if not customType or not customType.id:
|
|
40
|
+
raise ValueError(f"Custom type is missing for field '{fieldName}'.")
|
|
41
|
+
|
|
42
|
+
cacheId = cls._getCacheKey(customType.id, connection)
|
|
43
|
+
if cacheId in cls._classCache:
|
|
44
|
+
return cls._classCache[cacheId]
|
|
45
|
+
|
|
46
|
+
sections = (
|
|
47
|
+
[
|
|
48
|
+
CustomSectionClassGenerator.generate(
|
|
49
|
+
section,
|
|
50
|
+
customTypeId=customType.id,
|
|
51
|
+
sectionIndex=i,
|
|
52
|
+
connection=connection,
|
|
53
|
+
)
|
|
54
|
+
for i, section in enumerate(customType.sections)
|
|
55
|
+
]
|
|
56
|
+
if customType.sections
|
|
57
|
+
else []
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
name = (
|
|
61
|
+
CheckClassName.sanitizeClassName(customType.name)
|
|
62
|
+
if customType.name
|
|
63
|
+
else f"CustomType_ID{customType.id}"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
module = ".".join(
|
|
67
|
+
ICustomTypeValue.__module__.split(".")[:-1] + ["GeneratedCustomTypeValues"],
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
class SectionProperty:
|
|
71
|
+
def __init__(self, name: str):
|
|
72
|
+
self.name = name
|
|
73
|
+
|
|
74
|
+
def __get__(self, instance: ICustomSectionValue, _):
|
|
75
|
+
return instance.getField(self.name)
|
|
76
|
+
|
|
77
|
+
def __init__(self, ref=None):
|
|
78
|
+
cast(Any, type(self).__bases__[0]).__init__(self, ref)
|
|
79
|
+
|
|
80
|
+
typeDict = {
|
|
81
|
+
"__init__": __init__,
|
|
82
|
+
"__module__": module,
|
|
83
|
+
"__doc__": f"This class represents the value of the LOGS custom type '{customType.name}' (TypeID: {customType.id})",
|
|
84
|
+
"_name": customType.name,
|
|
85
|
+
"_id": customType.id,
|
|
86
|
+
"_fieldNames": [],
|
|
87
|
+
"_fieldTypes": {},
|
|
88
|
+
"_fieldIds": {},
|
|
89
|
+
"_noSerialize": ["fieldNames"],
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for s in sections:
|
|
93
|
+
attrName = Tools.resolveKeyConflictWithPrefix(s.__name__, "_", typeDict)
|
|
94
|
+
|
|
95
|
+
typeDict["_" + attrName] = None
|
|
96
|
+
typeDict[attrName] = SectionProperty(attrName)
|
|
97
|
+
typeDict["_fieldNames"].append(attrName)
|
|
98
|
+
typeDict["_fieldTypes"][attrName] = s
|
|
99
|
+
typeDict["_fieldIds"][s.getId()] = attrName
|
|
100
|
+
|
|
101
|
+
typeDict["_noSerialize"] += typeDict["_fieldNames"]
|
|
102
|
+
|
|
103
|
+
newClass: Type[ICustomTypeValue] = type(
|
|
104
|
+
name,
|
|
105
|
+
(ICustomTypeValue,),
|
|
106
|
+
typeDict,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return newClass
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def convert(
|
|
113
|
+
cls,
|
|
114
|
+
value: Any,
|
|
115
|
+
customTypeOrId: Union["CustomType", int],
|
|
116
|
+
connection: "LOGSConnection",
|
|
117
|
+
fieldName: Optional[str] = None,
|
|
118
|
+
) -> Optional["ICustomTypeValue"]:
|
|
119
|
+
from LOGS.Entities.CustomType import CustomType
|
|
120
|
+
|
|
121
|
+
if isinstance(value, ICustomTypeValue):
|
|
122
|
+
return value
|
|
123
|
+
|
|
124
|
+
if not isinstance(value, list):
|
|
125
|
+
raise ValueError(
|
|
126
|
+
f"Field '{fieldName}' cannot be converted from value of type '{type(value).__name__}'."
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if isinstance(customTypeOrId, int):
|
|
130
|
+
customType = CustomType(id=customTypeOrId, connection=connection)
|
|
131
|
+
try:
|
|
132
|
+
customType.fetch()
|
|
133
|
+
except EntityFetchingException as e:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Field '{fieldName}' cannot be converted:"
|
|
136
|
+
+ f"\n{Constants.exceptionIndentation}{str(e)}"
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
customType = customTypeOrId
|
|
140
|
+
|
|
141
|
+
c = cls.generate(customType, connection, fieldName)
|
|
142
|
+
try:
|
|
143
|
+
return c(value)
|
|
144
|
+
except Exception as e:
|
|
145
|
+
raise ValueError(
|
|
146
|
+
f"Field '{fieldName}' cannot be converted to '{c.__name__}': {str(e)}"
|
|
147
|
+
) from e
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import datetime as dt
|
|
2
|
+
import re
|
|
3
|
+
import time
|
|
4
|
+
from typing import List, cast
|
|
5
|
+
|
|
6
|
+
import pytz
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DateTimeConverter:
|
|
10
|
+
# When adding pattern here put the pattern with most information on top
|
|
11
|
+
_datePatterns = ["%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d"]
|
|
12
|
+
_timePatterns = ["%H:%M:%S.%f", "%H:%M:%S", "%H:%M"]
|
|
13
|
+
utc_offset_re = re.compile(r"([\+-])(\d+)$")
|
|
14
|
+
multiSpace_re = re.compile(r"( {2,})")
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def _getLocalTime(cls):
|
|
18
|
+
import platform
|
|
19
|
+
|
|
20
|
+
if platform.system() == "Windows":
|
|
21
|
+
from tzlocal.win32 import get_localzone_name
|
|
22
|
+
|
|
23
|
+
return pytz.timezone(get_localzone_name())
|
|
24
|
+
else:
|
|
25
|
+
return pytz.timezone(time.tzname[0])
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def convertTime(cls, entry: str):
|
|
29
|
+
entry = re.sub(cls.multiSpace_re, " ", entry)
|
|
30
|
+
match = cls.utc_offset_re.search(entry)
|
|
31
|
+
if match and len(match.group(2)) == 3:
|
|
32
|
+
entry = entry.replace(match.group(0), match.group(1) + "0" + match.group(2))
|
|
33
|
+
|
|
34
|
+
times: List[dt.time] = []
|
|
35
|
+
for pattern in set(cast(List[str], cls._timePatterns)):
|
|
36
|
+
try:
|
|
37
|
+
times.append(dt.datetime.strptime(entry, pattern).time())
|
|
38
|
+
except:
|
|
39
|
+
continue
|
|
40
|
+
if len(times) < 1:
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
return times[0]
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def convertDateTime(cls, entry: str):
|
|
47
|
+
entry = re.sub(cls.multiSpace_re, " ", entry)
|
|
48
|
+
match = cls.utc_offset_re.search(entry)
|
|
49
|
+
if match and len(match.group(2)) == 3:
|
|
50
|
+
entry = entry.replace(match.group(0), match.group(1) + "0" + match.group(2))
|
|
51
|
+
|
|
52
|
+
dates: List[dt.datetime] = []
|
|
53
|
+
for pattern in set(cast(List[str], cls._datePatterns)):
|
|
54
|
+
try:
|
|
55
|
+
dates.append(dt.datetime.strptime(entry, pattern))
|
|
56
|
+
except:
|
|
57
|
+
continue
|
|
58
|
+
if len(dates) < 1:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
d = dates[0]
|
|
62
|
+
if d.tzinfo == pytz.UTC or d.tzinfo is None:
|
|
63
|
+
local_tz = cls._getLocalTime()
|
|
64
|
+
d = d.replace(tzinfo=pytz.utc).astimezone(local_tz)
|
|
65
|
+
|
|
66
|
+
return d
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import types
|
|
2
|
+
from typing import Any, Callable, List, Type, TypeVar, Union, cast
|
|
3
|
+
|
|
4
|
+
TClass = TypeVar("TClass", bound=Callable[..., Any])
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class InitConstructor:
|
|
8
|
+
def _set_new_attribute(self, name, value):
|
|
9
|
+
# Never overwrites an existing attribute. Returns True if the
|
|
10
|
+
# attribute already exists.
|
|
11
|
+
if name in self.__dict__:
|
|
12
|
+
return True
|
|
13
|
+
setattr(self, name, value)
|
|
14
|
+
return False
|
|
15
|
+
|
|
16
|
+
def _new_constructor(self):
|
|
17
|
+
print("New Constructor")
|
|
18
|
+
|
|
19
|
+
def __call__(self, classInput: TClass) -> TClass:
|
|
20
|
+
print(classInput.__class__)
|
|
21
|
+
c = cast(Type, classInput)
|
|
22
|
+
|
|
23
|
+
print(c.__init__.__code__.co_varnames)
|
|
24
|
+
print(c.__init__.__defaults__)
|
|
25
|
+
print(c.__init__.__code__)
|
|
26
|
+
|
|
27
|
+
constructor = types.FunctionType(self._new_constructor.__code__, {})
|
|
28
|
+
|
|
29
|
+
return classInput
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Endpoint:
|
|
33
|
+
def __init__(self, path: Union[List[str], str]) -> None:
|
|
34
|
+
self.path = [path] if isinstance(path, str) else path
|
|
35
|
+
|
|
36
|
+
def __call__(self, classInput: TClass) -> TClass:
|
|
37
|
+
from LOGS.Entity.ConnectedEntity import ConnectedEntity
|
|
38
|
+
from LOGS.Entity.EntityConnector import EntityConnector
|
|
39
|
+
|
|
40
|
+
if not isinstance(classInput, type) or not issubclass(
|
|
41
|
+
classInput, (ConnectedEntity, EntityConnector)
|
|
42
|
+
):
|
|
43
|
+
raise Exception(
|
|
44
|
+
"%s decorator expect %a or %a type. (got type %a)"
|
|
45
|
+
% (
|
|
46
|
+
Endpoint.__name__,
|
|
47
|
+
ConnectedEntity.__name__,
|
|
48
|
+
EntityConnector.__name__,
|
|
49
|
+
classInput.__name__,
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
classInput._endpoint = self.path
|
|
54
|
+
|
|
55
|
+
return cast(TClass, classInput)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class UiEndpoint:
|
|
59
|
+
def __init__(self, path: Union[List[str], str]) -> None:
|
|
60
|
+
self.path = [path] if isinstance(path, str) else path
|
|
61
|
+
|
|
62
|
+
def __call__(self, classInput: TClass) -> TClass:
|
|
63
|
+
from LOGS.Entity.ConnectedEntity import ConnectedEntity
|
|
64
|
+
|
|
65
|
+
if not isinstance(classInput, type) or not issubclass(
|
|
66
|
+
classInput, (ConnectedEntity)
|
|
67
|
+
):
|
|
68
|
+
raise Exception(
|
|
69
|
+
"%s decorator expect %a type. (got type %a)"
|
|
70
|
+
% (Endpoint.__name__, ConnectedEntity.__name__, classInput.__name__)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
classInput._uiEndpoint = self.path
|
|
74
|
+
|
|
75
|
+
return cast(TClass, classInput)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class FullModel:
|
|
79
|
+
def __init__(self, fullEntity: Any) -> None:
|
|
80
|
+
self.fullEntity = fullEntity
|
|
81
|
+
|
|
82
|
+
def __call__(self, classInput: TClass) -> TClass:
|
|
83
|
+
if hasattr(classInput, "_fullEntityType"):
|
|
84
|
+
setattr(classInput, "_fullEntityType", self.fullEntity)
|
|
85
|
+
if hasattr(self.fullEntity, "_endpoint") and hasattr(classInput, "_endpoint"):
|
|
86
|
+
setattr(classInput, "_endpoint", getattr(self.fullEntity, "_endpoint"))
|
|
87
|
+
|
|
88
|
+
return classInput
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# --- Example for typed function decorator ---
|
|
92
|
+
# TFun = TypeVar("TFun", bound=Callable[..., Any])
|
|
93
|
+
|
|
94
|
+
# class FunctionDecorator:
|
|
95
|
+
# def __init__(self, path: Union[List[str], str]) -> None:
|
|
96
|
+
# self.path = [path] if isinstance(path, str) else path
|
|
97
|
+
|
|
98
|
+
# def __call__(self, func: TFun) -> TFun:
|
|
99
|
+
# path = self.path
|
|
100
|
+
|
|
101
|
+
# @wraps(func)
|
|
102
|
+
# def wrapper(*args, **kwargs) -> Any:
|
|
103
|
+
# # if isclass(classInput) and issubclass(classInput, ConnectedContent):
|
|
104
|
+
# # cast(ConnectedContent, classInput)._endpoint = path
|
|
105
|
+
# if hasattr(func, "_endpoint"):
|
|
106
|
+
# setattr(func, "_endpoint", path)
|
|
107
|
+
# return func(*args, **kwargs)
|
|
108
|
+
|
|
109
|
+
# return cast(TFun, wrapper)
|