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.
Files changed (251) hide show
  1. LOGS/Auxiliary/CheckClassName.py +1075 -0
  2. LOGS/Auxiliary/Constants.py +99 -0
  3. LOGS/Auxiliary/CustomEntityClassGenerator.py +254 -0
  4. LOGS/Auxiliary/CustomFieldClassGenerator.py +115 -0
  5. LOGS/Auxiliary/CustomFieldValueTypeChecker.py +168 -0
  6. LOGS/Auxiliary/CustomSectionClassGenerator.py +113 -0
  7. LOGS/Auxiliary/CustomTypeClassGenerator.py +147 -0
  8. LOGS/Auxiliary/DateTimeConverter.py +66 -0
  9. LOGS/Auxiliary/Decorators.py +109 -0
  10. LOGS/Auxiliary/Exceptions.py +341 -0
  11. LOGS/Auxiliary/LOGSErrorResponse.py +89 -0
  12. LOGS/Auxiliary/MinimalModelGenerator.py +236 -0
  13. LOGS/Auxiliary/ParameterHelper.py +56 -0
  14. LOGS/Auxiliary/ReplaceMessage.py +13 -0
  15. LOGS/Auxiliary/Tools.py +432 -0
  16. LOGS/Auxiliary/__init__.py +15 -0
  17. LOGS/Converter/Conversion.py +248 -0
  18. LOGS/Converter/Converter.py +96 -0
  19. LOGS/Converter/ConverterParameter.py +88 -0
  20. LOGS/Converter/DateTimeRange.py +58 -0
  21. LOGS/Converter/ExportParameters.py +89 -0
  22. LOGS/Converter/__init__.py +13 -0
  23. LOGS/Entities/Attachment.py +84 -0
  24. LOGS/Entities/AttachmentMinimal.py +8 -0
  25. LOGS/Entities/AttachmentRequestParameter.py +42 -0
  26. LOGS/Entities/Attachments.py +53 -0
  27. LOGS/Entities/AutoloadFileInfo.py +12 -0
  28. LOGS/Entities/AutoloadStatusError.py +7 -0
  29. LOGS/Entities/AxisNaming.py +33 -0
  30. LOGS/Entities/AxisZoom.py +33 -0
  31. LOGS/Entities/Bridge.py +165 -0
  32. LOGS/Entities/BridgeClientInfo.py +93 -0
  33. LOGS/Entities/BridgeMinimal.py +8 -0
  34. LOGS/Entities/BridgeRequestParameter.py +49 -0
  35. LOGS/Entities/BridgeType.py +7 -0
  36. LOGS/Entities/Bridges.py +12 -0
  37. LOGS/Entities/CustomField.py +243 -0
  38. LOGS/Entities/CustomFieldMinimal.py +8 -0
  39. LOGS/Entities/CustomFieldModels.py +111 -0
  40. LOGS/Entities/CustomFieldRequestParameter.py +69 -0
  41. LOGS/Entities/CustomFieldSearchQuery.py +40 -0
  42. LOGS/Entities/CustomFields.py +12 -0
  43. LOGS/Entities/CustomType.py +212 -0
  44. LOGS/Entities/CustomTypeMinimal.py +8 -0
  45. LOGS/Entities/CustomTypeRequestParameter.py +60 -0
  46. LOGS/Entities/CustomTypeSection.py +63 -0
  47. LOGS/Entities/CustomTypes.py +12 -0
  48. LOGS/Entities/DataFormat.py +97 -0
  49. LOGS/Entities/DataFormatInstrument.py +18 -0
  50. LOGS/Entities/DataFormatInstrumentMinimal.py +8 -0
  51. LOGS/Entities/DataFormatInstrumentRequestParameter.py +17 -0
  52. LOGS/Entities/DataFormatInstruments.py +16 -0
  53. LOGS/Entities/DataFormatMinimal.py +18 -0
  54. LOGS/Entities/DataFormatRequestParameter.py +21 -0
  55. LOGS/Entities/DataFormats.py +12 -0
  56. LOGS/Entities/DataSource.py +218 -0
  57. LOGS/Entities/DataSourceConnectionStatus.py +12 -0
  58. LOGS/Entities/DataSourceMinimal.py +8 -0
  59. LOGS/Entities/DataSourceRequestParameter.py +57 -0
  60. LOGS/Entities/DataSourceStatus.py +108 -0
  61. LOGS/Entities/DataSourceStatusIterator.py +16 -0
  62. LOGS/Entities/DataSourceStatusRequestParameter.py +31 -0
  63. LOGS/Entities/DataSources.py +12 -0
  64. LOGS/Entities/Dataset.py +439 -0
  65. LOGS/Entities/DatasetBase.py +196 -0
  66. LOGS/Entities/DatasetCreator.py +148 -0
  67. LOGS/Entities/DatasetInfo.py +147 -0
  68. LOGS/Entities/DatasetMatchTypes.py +157 -0
  69. LOGS/Entities/DatasetMatching.py +196 -0
  70. LOGS/Entities/DatasetMinimal.py +8 -0
  71. LOGS/Entities/DatasetModels.py +33 -0
  72. LOGS/Entities/DatasetRequestParameter.py +92 -0
  73. LOGS/Entities/DatasetTemplate.py +23 -0
  74. LOGS/Entities/DatasetUploadParameter.py +14 -0
  75. LOGS/Entities/Datasets.py +142 -0
  76. LOGS/Entities/Datatrack.py +179 -0
  77. LOGS/Entities/DatatrackFormattedTable.py +25 -0
  78. LOGS/Entities/DatatrackGeneric.py +34 -0
  79. LOGS/Entities/DatatrackImage.py +25 -0
  80. LOGS/Entities/DatatrackNumericArray.py +30 -0
  81. LOGS/Entities/DatatrackNumericMatrix.py +98 -0
  82. LOGS/Entities/Entities.py +71 -0
  83. LOGS/Entities/EntitiesRequestParameter.py +18 -0
  84. LOGS/Entities/EntityOriginWriteModelWithId.py +15 -0
  85. LOGS/Entities/FileEntry.py +138 -0
  86. LOGS/Entities/FileExcludePattern.py +8 -0
  87. LOGS/Entities/FormatMetaData.py +56 -0
  88. LOGS/Entities/FormattedTable/DatatypeFormattedTable.py +135 -0
  89. LOGS/Entities/FormattedTable/DatatypeFormattedTableCell.py +108 -0
  90. LOGS/Entities/FormattedTable/DatatypeFormattedTableSettings.py +11 -0
  91. LOGS/Entities/FormattedTable/__init__.py +9 -0
  92. LOGS/Entities/HierarchyLeaf.py +15 -0
  93. LOGS/Entities/HierarchyNode.py +40 -0
  94. LOGS/Entities/ILiteraryTypedEntity.py +19 -0
  95. LOGS/Entities/InventoryItem.py +102 -0
  96. LOGS/Entities/InventoryItemMinimal.py +25 -0
  97. LOGS/Entities/InventoryItemRequestParameter.py +58 -0
  98. LOGS/Entities/InventoryItems.py +12 -0
  99. LOGS/Entities/LabNotebook.py +33 -0
  100. LOGS/Entities/LabNotebookEntries.py +16 -0
  101. LOGS/Entities/LabNotebookEntry.py +106 -0
  102. LOGS/Entities/LabNotebookEntryContent/BasicAttribute.py +15 -0
  103. LOGS/Entities/LabNotebookEntryContent/EntityAttribute.py +85 -0
  104. LOGS/Entities/LabNotebookEntryContent/EntryContentBlockquote.py +13 -0
  105. LOGS/Entities/LabNotebookEntryContent/EntryContentBulletList.py +17 -0
  106. LOGS/Entities/LabNotebookEntryContent/EntryContentCallout.py +40 -0
  107. LOGS/Entities/LabNotebookEntryContent/EntryContentContentPlaceholderNode.py +31 -0
  108. LOGS/Entities/LabNotebookEntryContent/EntryContentConverter.py +207 -0
  109. LOGS/Entities/LabNotebookEntryContent/EntryContentDocument.py +8 -0
  110. LOGS/Entities/LabNotebookEntryContent/EntryContentEntity.py +13 -0
  111. LOGS/Entities/LabNotebookEntryContent/EntryContentEntityMention.py +31 -0
  112. LOGS/Entities/LabNotebookEntryContent/EntryContentHeading.py +33 -0
  113. LOGS/Entities/LabNotebookEntryContent/EntryContentHorizontalRule.py +12 -0
  114. LOGS/Entities/LabNotebookEntryContent/EntryContentItem.py +37 -0
  115. LOGS/Entities/LabNotebookEntryContent/EntryContentListItem.py +49 -0
  116. LOGS/Entities/LabNotebookEntryContent/EntryContentOrderedList.py +31 -0
  117. LOGS/Entities/LabNotebookEntryContent/EntryContentParagraph.py +13 -0
  118. LOGS/Entities/LabNotebookEntryContent/EntryContentTable.py +17 -0
  119. LOGS/Entities/LabNotebookEntryContent/EntryContentTableCell.py +40 -0
  120. LOGS/Entities/LabNotebookEntryContent/EntryContentTableRow.py +8 -0
  121. LOGS/Entities/LabNotebookEntryContent/EntryContentTaskList.py +17 -0
  122. LOGS/Entities/LabNotebookEntryContent/EntryContentTaskListItem.py +31 -0
  123. LOGS/Entities/LabNotebookEntryContent/EntryContentText.py +33 -0
  124. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithAttribute.py +23 -0
  125. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithContent.py +38 -0
  126. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithTextAttribute.py +16 -0
  127. LOGS/Entities/LabNotebookEntryContent/TextAttribute.py +46 -0
  128. LOGS/Entities/LabNotebookEntryContent/TextMarkAtributes.py +64 -0
  129. LOGS/Entities/LabNotebookEntryContent/TextMarkConverter.py +45 -0
  130. LOGS/Entities/LabNotebookEntryContent/TextMarks.py +71 -0
  131. LOGS/Entities/LabNotebookEntryContent/__init__.py +34 -0
  132. LOGS/Entities/LabNotebookEntryMinimal.py +8 -0
  133. LOGS/Entities/LabNotebookEntryRequestParameter.py +59 -0
  134. LOGS/Entities/LabNotebookExperiment.py +58 -0
  135. LOGS/Entities/LabNotebookExperimentMinimal.py +8 -0
  136. LOGS/Entities/LabNotebookExperimentRequestParameter.py +52 -0
  137. LOGS/Entities/LabNotebookExperiments.py +16 -0
  138. LOGS/Entities/LabNotebookMinimal.py +8 -0
  139. LOGS/Entities/LabNotebookModels.py +14 -0
  140. LOGS/Entities/LabNotebookRequestParameter.py +42 -0
  141. LOGS/Entities/LabNotebookTemplate.py +42 -0
  142. LOGS/Entities/LabNotebookTemplateMinimal.py +8 -0
  143. LOGS/Entities/LabNotebookTemplateRequestParameter.py +38 -0
  144. LOGS/Entities/LabNotebookTemplates.py +16 -0
  145. LOGS/Entities/LabNotebooks.py +12 -0
  146. LOGS/Entities/Method.py +66 -0
  147. LOGS/Entities/MethodMinimal.py +8 -0
  148. LOGS/Entities/MethodRequestParameter.py +16 -0
  149. LOGS/Entities/Methods.py +12 -0
  150. LOGS/Entities/Origin.py +53 -0
  151. LOGS/Entities/OriginMinimal.py +8 -0
  152. LOGS/Entities/OriginRequestParameter.py +28 -0
  153. LOGS/Entities/Origins.py +12 -0
  154. LOGS/Entities/ParserLog.py +49 -0
  155. LOGS/Entities/Permission.py +9 -0
  156. LOGS/Entities/Person.py +145 -0
  157. LOGS/Entities/PersonCategory.py +12 -0
  158. LOGS/Entities/PersonMinimal.py +8 -0
  159. LOGS/Entities/PersonRequestParameter.py +58 -0
  160. LOGS/Entities/Persons.py +12 -0
  161. LOGS/Entities/Project.py +52 -0
  162. LOGS/Entities/ProjectMinimal.py +8 -0
  163. LOGS/Entities/ProjectPersonPermission.py +102 -0
  164. LOGS/Entities/ProjectRequestParameter.py +58 -0
  165. LOGS/Entities/Projects.py +12 -0
  166. LOGS/Entities/Role.py +94 -0
  167. LOGS/Entities/RoleMinimal.py +8 -0
  168. LOGS/Entities/RoleRequestParameter.py +40 -0
  169. LOGS/Entities/Roles.py +12 -0
  170. LOGS/Entities/RunState.py +9 -0
  171. LOGS/Entities/Sample.py +53 -0
  172. LOGS/Entities/SampleMinimal.py +8 -0
  173. LOGS/Entities/SampleRequestParameter.py +54 -0
  174. LOGS/Entities/Samples.py +12 -0
  175. LOGS/Entities/SharedContent.py +87 -0
  176. LOGS/Entities/SharedContentMinimal.py +8 -0
  177. LOGS/Entities/SharedContentRequestParameter.py +38 -0
  178. LOGS/Entities/SharedContents.py +12 -0
  179. LOGS/Entities/Signature.py +60 -0
  180. LOGS/Entities/Track.py +93 -0
  181. LOGS/Entities/TrackData.py +20 -0
  182. LOGS/Entities/TrackImage.py +21 -0
  183. LOGS/Entities/TrackImageData.py +20 -0
  184. LOGS/Entities/TrackMatrix.py +28 -0
  185. LOGS/Entities/TrackMatrixData.py +22 -0
  186. LOGS/Entities/TrackSettings.py +55 -0
  187. LOGS/Entities/TrackTable.py +21 -0
  188. LOGS/Entities/TrackTableData.py +22 -0
  189. LOGS/Entities/TrackXY.py +40 -0
  190. LOGS/Entities/TrackXYComplex.py +51 -0
  191. LOGS/Entities/TrackXYComplexData.py +50 -0
  192. LOGS/Entities/TrackXYData.py +31 -0
  193. LOGS/Entities/Vendor.py +40 -0
  194. LOGS/Entities/VendorMinimal.py +8 -0
  195. LOGS/Entities/VendorRequestParameter.py +17 -0
  196. LOGS/Entities/Vendors.py +12 -0
  197. LOGS/Entities/__init__.py +118 -0
  198. LOGS/Entity/ConnectedEntity.py +170 -0
  199. LOGS/Entity/Entity.py +203 -0
  200. LOGS/Entity/EntityConnector.py +70 -0
  201. LOGS/Entity/EntityIterator.py +263 -0
  202. LOGS/Entity/EntityMinimal.py +141 -0
  203. LOGS/Entity/EntityMinimalWithIntId.py +36 -0
  204. LOGS/Entity/EntityMinimalWithStrId.py +36 -0
  205. LOGS/Entity/EntityMinimalWithType.py +47 -0
  206. LOGS/Entity/EntityRequestParameter.py +104 -0
  207. LOGS/Entity/EntitySortBy.py +69 -0
  208. LOGS/Entity/EntityWithIntId.py +26 -0
  209. LOGS/Entity/EntityWithStrId.py +26 -0
  210. LOGS/Entity/IGenericEntityOrderBy.py +55 -0
  211. LOGS/Entity/IdIterator.py +207 -0
  212. LOGS/Entity/SerializableContent.py +834 -0
  213. LOGS/Entity/__init__.py +23 -0
  214. LOGS/Interfaces/ICustomFieldValue.py +92 -0
  215. LOGS/Interfaces/ICustomSectionValue.py +161 -0
  216. LOGS/Interfaces/ICustomTypeValue.py +152 -0
  217. LOGS/Interfaces/ICustomValue.py +28 -0
  218. LOGS/Interfaces/IEntityInterface.py +7 -0
  219. LOGS/Interfaces/IEntryRecord.py +57 -0
  220. LOGS/Interfaces/IHierarchicalEntity.py +41 -0
  221. LOGS/Interfaces/IHierarchyType.py +63 -0
  222. LOGS/Interfaces/ILockableEntity.py +52 -0
  223. LOGS/Interfaces/IModificationRecord.py +56 -0
  224. LOGS/Interfaces/INamedEntity.py +25 -0
  225. LOGS/Interfaces/IOwnedEntity.py +27 -0
  226. LOGS/Interfaces/IPaginationRequest.py +11 -0
  227. LOGS/Interfaces/IPermissionedEntity.py +72 -0
  228. LOGS/Interfaces/IProjectBased.py +27 -0
  229. LOGS/Interfaces/ISessionedEntity.py +59 -0
  230. LOGS/Interfaces/ISignableEntity.py +49 -0
  231. LOGS/Interfaces/ISoftDeletable.py +28 -0
  232. LOGS/Interfaces/ITypedEntity.py +129 -0
  233. LOGS/Interfaces/IUniqueEntity.py +61 -0
  234. LOGS/Interfaces/IVersionedEntity.py +39 -0
  235. LOGS/Interfaces/__init__.py +7 -0
  236. LOGS/LOGS.py +1436 -0
  237. LOGS/LOGSConnection.py +647 -0
  238. LOGS/LOGSOptions.py +11 -0
  239. LOGS/Parameters/Color.py +92 -0
  240. LOGS/Parameters/ParameterBase.py +55 -0
  241. LOGS/Parameters/ParameterConverter.py +24 -0
  242. LOGS/Parameters/ParameterElement.py +99 -0
  243. LOGS/Parameters/ParameterList.py +52 -0
  244. LOGS/Parameters/ParameterTable.py +64 -0
  245. LOGS/Parameters/__init__.py +13 -0
  246. LOGS/ServerMetaData.py +120 -0
  247. LOGS/__init__.py +12 -0
  248. logs_py-4.0.7.dist-info/METADATA +51 -0
  249. logs_py-4.0.7.dist-info/RECORD +251 -0
  250. logs_py-4.0.7.dist-info/WHEEL +5 -0
  251. logs_py-4.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,56 @@
1
+ import regex as re
2
+
3
+
4
+ class ParameterHelper:
5
+ floatRe = re.compile(r"^[\d\.\-\+e]+$")
6
+ intRe = re.compile(r"^\d+$")
7
+ splitRe = re.compile(r"[ \t,]+")
8
+ quotation = re.compile(r"^'(.*)'$")
9
+
10
+ def __init__(self, parameters):
11
+ if not isinstance(parameters, dict):
12
+ raise Exception("Parameter argument must be of type dict")
13
+ self.parameters = parameters
14
+
15
+ @classmethod
16
+ def isNumeric(cls, value):
17
+ vtype = "str"
18
+ if cls.floatRe.match(str(value)):
19
+ if cls.intRe.match(str(value)):
20
+ try:
21
+ value = int(value)
22
+ vtype = "int"
23
+ except:
24
+ pass
25
+ else:
26
+ try:
27
+ value = float(value)
28
+ vtype = "float"
29
+ except:
30
+ pass
31
+ return value, vtype
32
+
33
+ @classmethod
34
+ def removeUnit(cls, value):
35
+ if value == None:
36
+ return "-"
37
+ if not isinstance(value, str):
38
+ return value
39
+ v = cls.splitRe.split(value)
40
+ v, _ = cls.isNumeric(v[0])
41
+ return v
42
+
43
+ def get(self, key, removeUnit=False):
44
+ if key in self.parameters:
45
+ if isinstance(self.parameters[key], list):
46
+ return self.parameters[key]
47
+
48
+ value = self.parameters[key]
49
+ if isinstance(value, str):
50
+ match = self.quotation.match(value)
51
+ if match:
52
+ value = match.group(1)
53
+ if removeUnit:
54
+ value = self.removeUnit(value)
55
+ return value
56
+ return None
@@ -0,0 +1,13 @@
1
+ from typing import List, Optional, Union
2
+
3
+
4
+ class ReplaceMessage:
5
+ def __init__(self, message: str = "", path: Optional[List[Union[str, int]]] = None):
6
+ self.message = message
7
+ self.path = path if path else []
8
+
9
+ def __str__(self):
10
+ return self.message
11
+
12
+ def unshiftPath(self, pathEntry: Union[str, int]):
13
+ self.path.insert(0, pathEntry)
@@ -0,0 +1,432 @@
1
+ import dataclasses
2
+ import os
3
+ import random
4
+ import string
5
+ import sys
6
+ from datetime import datetime, time, timezone
7
+ from enum import Enum
8
+ from typing import Any, Callable, Dict, List, Optional, Set, Type, TypeVar, Union, cast
9
+ from unicodedata import normalize
10
+ from uuid import UUID
11
+
12
+ from regex import Regex
13
+
14
+ from LOGS.Auxiliary.DateTimeConverter import DateTimeConverter
15
+
16
+
17
+ class Unbuffered(object):
18
+ def __init__(self, stream):
19
+ self.stream = stream
20
+
21
+ def write(self, data):
22
+ self.stream.write(data)
23
+ self.stream.flush()
24
+
25
+ def writelines(self, data):
26
+ self.stream.writelines(data)
27
+ self.stream.flush()
28
+
29
+ def __getattr__(self, attr):
30
+ return getattr(self.stream, attr)
31
+
32
+
33
+ _T = TypeVar("_T")
34
+
35
+
36
+ class UnbufferedStdout(Unbuffered):
37
+ def __init__(self):
38
+ super().__init__(sys.stdout)
39
+
40
+
41
+ class Tools:
42
+ messageStrMaxLength = 25
43
+ __byteUnits = ["", "K", "M", "G", "T", "P", "E", "Z"]
44
+
45
+ @classmethod
46
+ def ObjectToString(cls, obj: Any) -> str:
47
+ name = getattr(obj, "name") if hasattr(obj, "name") else None
48
+ id = getattr(obj, "id") if hasattr(obj, "id") else None
49
+ i = " id:'%s'" % id if id is not None else ""
50
+ n = " name:'%s'" % name if name is not None else ""
51
+ return "<%s%s%s>" % (type(obj).__name__, i, n)
52
+
53
+ @classmethod
54
+ def unbufferStdout(cls):
55
+ unbuffered = UnbufferedStdout()
56
+ sys.stdout = cast(Any, unbuffered)
57
+
58
+ @classmethod
59
+ def getHumanReadableSize(cls, size, suffix="B"):
60
+ for unit in cls.__byteUnits:
61
+ if abs(size) < 1024.0:
62
+ return "%3.1f%s%s" % (size, unit, suffix)
63
+ size /= 1024.0
64
+ return "%.1f%s%s" % (size, "Yi", suffix)
65
+
66
+ @classmethod
67
+ def osPathSeparators(cls):
68
+ seps = []
69
+ for sep in os.path.sep, os.path.altsep:
70
+ if sep:
71
+ seps.append(sep)
72
+ return seps
73
+
74
+ @classmethod
75
+ def sanitizeFileName(cls, fileName: Optional[str], defaultName: str = "Unknown"):
76
+ if not fileName:
77
+ fileName = defaultName
78
+ # Sort out unicode characters
79
+ valid_filename = (
80
+ normalize("NFKD", fileName).encode("ascii", "ignore").decode("ascii")
81
+ )
82
+ # Replace path separators with underscores
83
+ for sep in cls.osPathSeparators():
84
+ valid_filename = valid_filename.replace(sep, "_")
85
+ # Ensure only valid characters
86
+ valid_chars = "-_.() {0}{1}".format(string.ascii_letters, string.digits)
87
+ valid_filename = "".join(ch for ch in valid_filename if ch in valid_chars)
88
+ # Ensure at least one letter or number to ignore names such as '..'
89
+ valid_chars = "{0}{1}".format(string.ascii_letters, string.digits)
90
+ test_filename = "".join(ch for ch in fileName if ch in valid_chars)
91
+ if len(test_filename) == 0:
92
+ # Replace empty file name or file path part with the following
93
+ valid_filename = defaultName
94
+ if valid_filename[0] not in string.ascii_letters:
95
+ valid_filename = "_" + valid_filename
96
+ return valid_filename
97
+
98
+ @classmethod
99
+ def timeToString(cls, dt: Optional[time]) -> str:
100
+ if dt is None:
101
+ return ""
102
+ return dt.strftime("%H:%M:%S") + f".{dt.microsecond:03d}"
103
+
104
+ @classmethod
105
+ def datetimeToUTCString(cls, dt: Optional[datetime]) -> str:
106
+ if dt is None:
107
+ return ""
108
+ dt = dt.astimezone(
109
+ timezone.utc
110
+ ) # we convert all datetimes to UTC for the LOGS server
111
+ return dt.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
112
+
113
+ @classmethod
114
+ def eclipsesJoin(cls, separator: str, items: List, maxCount: int = 3):
115
+ if len(items) > maxCount:
116
+ items = items[:maxCount]
117
+ return separator.join(items) + "..."
118
+
119
+ return separator.join(items)
120
+
121
+ @classmethod
122
+ def wordToPlural(cls, word: str):
123
+ if word[-1] == "y":
124
+ return word[:-1] + "ies"
125
+
126
+ return word + "s"
127
+
128
+ @classmethod
129
+ def plural(cls, word: str, count: Union[int, list, set]):
130
+ if isinstance(count, (list, set)):
131
+ count = len(count)
132
+
133
+ if count == 1:
134
+ return word
135
+
136
+ return cls.wordToPlural(word)
137
+
138
+ @classmethod
139
+ def numberPlural(cls, word: str, count: Union[int, List]):
140
+ if isinstance(count, list):
141
+ count = len(count)
142
+
143
+ if count < 1:
144
+ return "no %s" % cls.wordToPlural(word)
145
+
146
+ if count < 2:
147
+ return "%d %s" % (count, word)
148
+
149
+ return "%d %s" % (count, cls.wordToPlural(word))
150
+
151
+ @classmethod
152
+ def getTypeFromTypeEntry(cls, item: dict, types: list):
153
+ if isinstance(item, dict) and "type" in item:
154
+ type = item["type"]
155
+ for t in types:
156
+ if t._type == type:
157
+ return t
158
+ return None
159
+ else:
160
+ return None
161
+
162
+ _uidRegex = Regex(
163
+ r"^[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?[0-9a-f]{12}$"
164
+ )
165
+
166
+ @classmethod
167
+ def uuidConverter(cls, value):
168
+ if isinstance(value, UUID):
169
+ return value
170
+ else:
171
+ v = str(value)
172
+ if not cls._uidRegex.match(v):
173
+ raise Exception(
174
+ "The provided uid %a does not fit the format 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'"
175
+ )
176
+ return UUID(v)
177
+
178
+ @classmethod
179
+ def dataClassConverterGenerator(cls, dataClassType: type) -> Callable:
180
+
181
+ if dataclasses.is_dataclass(dataClassType):
182
+
183
+ def converter(value):
184
+ if isinstance(value, dataClassType):
185
+ return value
186
+ if isinstance(value, dict):
187
+ fieldTypes = set(f.name for f in dataclasses.fields(dataClassType))
188
+ fieldValues = {k: v for k, v in value.items() if k in fieldTypes}
189
+
190
+ return dataClassType(**fieldValues)
191
+ raise Exception(f"Cannot convert to type {dataClassType.__name__}")
192
+
193
+ return converter
194
+
195
+ return lambda value: None
196
+
197
+ @classmethod
198
+ def checkAndConvert(
199
+ cls,
200
+ value: Any,
201
+ fieldType: Union[Type[_T], str],
202
+ fieldName: Optional[str] = None,
203
+ converter: Optional[Callable[[Any], _T]] = None,
204
+ allowNone=False,
205
+ initOnNone=False,
206
+ ) -> _T:
207
+ if isinstance(fieldType, list):
208
+ fieldType = cast(Any, cls.getTypeFromTypeEntry(value, fieldType))
209
+
210
+ if not fieldType:
211
+ return value
212
+
213
+ if not isinstance(fieldType, type) and converter is None:
214
+ raise Exception(
215
+ f"Manual field type '{fieldType}' cannot be used without a converter definition."
216
+ )
217
+
218
+ if not converter:
219
+ if isinstance(fieldType, type) and isinstance(value, fieldType):
220
+ return value
221
+
222
+ if issubclass(cast(Type[_T], fieldType), Enum):
223
+ if allowNone and value == None:
224
+ return cast(Any, None)
225
+
226
+ try:
227
+ enum = cast(Any, fieldType)
228
+ return enum(value)
229
+ except ValueError:
230
+ raise Exception(
231
+ "Field %a cannot be converted to enum type %a. (Got invalid value %a)"
232
+ % (
233
+ fieldName,
234
+ cast(type, fieldType).__name__,
235
+ cls.truncString(str(value)),
236
+ )
237
+ )
238
+
239
+ if cast(type, fieldType).__name__ == datetime.__name__:
240
+ converter = cast(Callable, DateTimeConverter.convertDateTime)
241
+ elif cast(type, fieldType).__name__ == time.__name__:
242
+ converter = cast(Callable, DateTimeConverter.convertTime)
243
+ elif cast(type, fieldType).__name__ == UUID.__name__:
244
+ converter = cast(Callable, cls.uuidConverter)
245
+ elif dataclasses.is_dataclass(fieldType):
246
+ converter = cls.dataClassConverterGenerator(fieldType)
247
+ else:
248
+ converter = cast(Callable, fieldType)
249
+
250
+ if fieldName == None:
251
+ fieldName = "field"
252
+ fieldName = cast(str, fieldName)
253
+
254
+ if value == None:
255
+ if initOnNone and hasattr(fieldType, "__init__"):
256
+ return cast(Callable, fieldType)()
257
+ if allowNone:
258
+ return cast(Any, None)
259
+ else:
260
+ raise Exception("Field %a cannot be 'None'." % (fieldName))
261
+
262
+ typeName = (
263
+ cast(type, fieldType).__name__
264
+ if isinstance(fieldType, type)
265
+ else str(fieldType)
266
+ )
267
+
268
+ # print(f"{fieldName}({fieldType}) = {value}")
269
+ try:
270
+ value = converter(value)
271
+ except:
272
+ raise Exception(
273
+ "Field %a cannot be converted to type %a. (Got value %a of type %a)"
274
+ % (
275
+ fieldName,
276
+ typeName,
277
+ cls.truncString(str(value)),
278
+ type(value).__name__,
279
+ )
280
+ )
281
+
282
+ # print(f"{fieldName}({fieldType}) => {value}")
283
+
284
+ if value == None:
285
+ if allowNone:
286
+ return cast(Any, None)
287
+ else:
288
+ raise Exception("%s cannot be 'None'." % (fieldName))
289
+
290
+ return value
291
+
292
+ @classmethod
293
+ def checkListAndConvert(
294
+ cls,
295
+ value: Any,
296
+ fieldType: Union[Type[_T], str],
297
+ fieldName: Optional[str] = None,
298
+ converter: Optional[Callable[[Any], _T]] = None,
299
+ allowNone: bool = False,
300
+ singleToList: bool = False,
301
+ length: int = -1,
302
+ ) -> List[_T]:
303
+ if fieldName == None:
304
+ fieldName = "field"
305
+ fieldName = cast(str, fieldName)
306
+
307
+ if value == None:
308
+ value = []
309
+
310
+ if singleToList:
311
+ if not isinstance(value, (list, tuple)):
312
+ value = [value]
313
+
314
+ typeName = (
315
+ cast(type, fieldType).__name__
316
+ if isinstance(fieldType, type)
317
+ else str(fieldType)
318
+ )
319
+ if not isinstance(value, (list, tuple)):
320
+ raise Exception(
321
+ "%s must be of type 'list[%s]'. (Got type %a)"
322
+ % (fieldName, typeName, type(value).__name__)
323
+ )
324
+
325
+ if length >= 0 and len(value) != length:
326
+ raise Exception(
327
+ "%s must have length %d. (Got length %a)"
328
+ % (fieldName, length, len(value))
329
+ )
330
+
331
+ return [
332
+ cls.checkAndConvert(
333
+ f,
334
+ fieldType=fieldType,
335
+ fieldName="%s[%d]" % (fieldName, i),
336
+ converter=converter,
337
+ allowNone=allowNone,
338
+ )
339
+ for i, f in enumerate(value)
340
+ ]
341
+
342
+ @staticmethod
343
+ def checkDirectory(dir):
344
+ if not os.path.isdir(dir):
345
+ return "could not find directory '%s'" % dir
346
+
347
+ list_of_entries = []
348
+ try:
349
+ with os.scandir(dir) as entries:
350
+ for entry in entries:
351
+ list_of_entries.append(entry.name)
352
+ except PermissionError:
353
+ return "permission denied for directory '%s' on server" % dir
354
+ except:
355
+ return "could not access directory '%s'" % dir
356
+
357
+ return False
358
+
359
+ @staticmethod
360
+ def convertToNativeNewline(text: str):
361
+ return text.replace("\n", os.linesep)
362
+
363
+ @staticmethod
364
+ def namedSwitchConverter(switchList: List[str]) -> Dict[str, bool]:
365
+ result = {}
366
+ for s in switchList:
367
+ result[s] = True
368
+
369
+ return result
370
+
371
+ @staticmethod
372
+ def stringToId(s: str):
373
+ if not isinstance(s, str):
374
+ s = str(s)
375
+ return "".join([c if c.isalpha() or c.isdigit() else "_" for c in s]).rstrip()
376
+
377
+ @classmethod
378
+ def truncString(cls, text: str, length: int = 30) -> str:
379
+ return "%s%s" % (text[:length], "..." if len(text) > length else "")
380
+
381
+ @classmethod
382
+ def checkSubFieldAndConvert(
383
+ cls,
384
+ value: dict,
385
+ fieldType: Union[Type[_T], str],
386
+ fieldName: Union[str, None],
387
+ subFieldName: str,
388
+ allowNone=False,
389
+ ):
390
+ name = f"{fieldName}.{subFieldName}" if fieldName else None
391
+ v = value.get(subFieldName, None) if isinstance(value, dict) else None
392
+ return Tools.checkAndConvert(v, fieldType, name, allowNone=allowNone)
393
+
394
+ @classmethod
395
+ def resolveKeyConflictWithPrefix(
396
+ cls,
397
+ name: str,
398
+ prefix: str,
399
+ lookup: Union[Dict, Set],
400
+ separator="_",
401
+ startIndex=1,
402
+ ) -> str:
403
+ originalName = name
404
+ index = startIndex
405
+ while name in lookup or prefix + name in lookup:
406
+ name = f"{originalName}{separator}{index}"
407
+ index += 1
408
+ return name
409
+
410
+ @classmethod
411
+ def resolveKeyConflict(
412
+ cls, name: str, lookup: Union[Dict, Set], separator="_", startIndex=1
413
+ ) -> str:
414
+ originalName = name
415
+ index = startIndex
416
+ while name in lookup:
417
+ name = f"{originalName}{separator}{index}"
418
+ index += 1
419
+ return name
420
+
421
+ @classmethod
422
+ def generateRandomString(cls, len=10):
423
+ return "".join(map(lambda r: chr(random.randint(65, 90)), range(len)))
424
+
425
+ @classmethod
426
+ def gerundVerb(cls, verb: str):
427
+ if verb.endswith("ing"):
428
+ return verb
429
+ elif verb.endswith("e"):
430
+ verb = verb[:-1]
431
+
432
+ return verb + "ing"
@@ -0,0 +1,15 @@
1
+ """
2
+ This Module is written for the LOGS Repository.
3
+
4
+ It's objects can be used to access the LOGS public API
5
+ programatically via python scripts.
6
+ ...
7
+ """
8
+
9
+ from .Constants import *
10
+ from .DateTimeConverter import *
11
+ from .Decorators import *
12
+ from .Exceptions import *
13
+ from .MinimalModelGenerator import *
14
+ from .ReplaceMessage import *
15
+ from .Tools import *