logs-py 2.9.6__py3-none-any.whl → 3.0.1__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.
Potentially problematic release.
This version of logs-py might be problematic. Click here for more details.
- LOGS/Auxiliary/DateTimeConverter.py +11 -1
- LOGS/Auxiliary/Exceptions.py +40 -4
- LOGS/Auxiliary/LOGSErrorResponse.py +4 -1
- LOGS/Auxiliary/MinimalModelGenerator.py +88 -28
- LOGS/Auxiliary/Tools.py +11 -0
- LOGS/Converter/Conversion.py +248 -0
- LOGS/Converter/Converter.py +96 -0
- LOGS/Converter/ConverterParameter.py +88 -0
- LOGS/Converter/ExportParamters.py +89 -0
- LOGS/Converter/__init__.py +13 -0
- LOGS/Entities/Bridge.py +6 -3
- LOGS/Entities/CustomField.py +96 -91
- LOGS/Entities/CustomFieldModels.py +57 -0
- LOGS/Entities/CustomFieldRelations.py +10 -0
- LOGS/Entities/CustomFieldRequestParameter.py +43 -15
- LOGS/Entities/CustomFieldValue.py +88 -0
- LOGS/Entities/CustomFieldValueConverter.py +66 -0
- LOGS/Entities/CustomType.py +187 -0
- LOGS/Entities/CustomTypeEntityType.py +11 -0
- LOGS/Entities/CustomTypeMinimal.py +8 -0
- LOGS/Entities/CustomTypeRelations.py +59 -0
- LOGS/Entities/CustomTypeRequestParameter.py +61 -0
- LOGS/Entities/CustomTypeSection.py +39 -0
- LOGS/Entities/CustomTypes.py +12 -0
- LOGS/Entities/DataSource.py +28 -14
- LOGS/Entities/Dataset.py +274 -136
- LOGS/Entities/DatasetCreator.py +23 -72
- LOGS/Entities/DatasetInfo.py +23 -2
- LOGS/Entities/DatasetModels.py +31 -0
- LOGS/Entities/DatasetRequestParameter.py +45 -32
- LOGS/Entities/Datatrack.py +74 -30
- LOGS/Entities/DatatrackFormattedTable.py +25 -0
- LOGS/Entities/DatatrackGeneric.py +34 -0
- LOGS/Entities/DatatrackImage.py +25 -0
- LOGS/Entities/DatatrackNumericArray.py +9 -39
- LOGS/Entities/DatatrackNumericMatrix.py +86 -0
- LOGS/Entities/DocumentRequestParameter.py +2 -2
- LOGS/Entities/EntitiesRequestParameter.py +2 -2
- LOGS/Entities/Experiment.py +3 -3
- LOGS/Entities/FileExcludePattern.py +8 -0
- LOGS/Entities/FormatFormat.py +22 -1
- LOGS/Entities/FormatFormatRequestParameter.py +2 -1
- LOGS/Entities/FormatFormats.py +1 -1
- 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/ILiterarTypedEntity.py +19 -0
- LOGS/Entities/Instrument.py +3 -3
- LOGS/Entities/Inventories.py +12 -0
- LOGS/Entities/Inventory.py +95 -0
- LOGS/Entities/InventoryMinimal.py +20 -0
- LOGS/Entities/InventoryRelations.py +23 -0
- LOGS/Entities/InventoryRequestParameter.py +53 -0
- LOGS/Entities/LabNotebook.py +37 -0
- LOGS/Entities/LabNotebookEntry.py +47 -24
- 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/LabNotebookEntryRequestParameter.py +2 -0
- LOGS/Entities/LabNotebookExperiment.py +52 -0
- LOGS/Entities/LabNotebookExperimentMinimal.py +8 -0
- LOGS/Entities/LabNotebookExperimentRequestParameter.py +49 -0
- LOGS/Entities/LabNotebookExperiments.py +16 -0
- LOGS/Entities/LabNotebookMinimal.py +19 -0
- LOGS/Entities/LabNotebookModels.py +14 -0
- LOGS/Entities/LabNotebookRequestParameter.py +43 -0
- LOGS/Entities/LabNotebooks.py +12 -0
- LOGS/Entities/Method.py +3 -3
- LOGS/Entities/ParserLog.py +4 -0
- LOGS/Entities/Person.py +2 -2
- LOGS/Entities/PersonRequestParameter.py +1 -0
- LOGS/Entities/Project.py +7 -7
- LOGS/Entities/{ProjectUserPermission.py → ProjectPersonPermission.py} +14 -4
- LOGS/Entities/Role.py +3 -3
- LOGS/Entities/RunState.py +1 -0
- LOGS/Entities/Sample.py +36 -57
- LOGS/Entities/SampleRequestParameter.py +30 -15
- LOGS/Entities/Track.py +8 -4
- LOGS/Entities/TrackData.py +11 -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/TrackTable.py +21 -0
- LOGS/Entities/TrackTableData.py +22 -0
- LOGS/Entities/TrackXY.py +5 -1
- LOGS/Entities/TrackXYComplex.py +1 -1
- LOGS/Entities/__init__.py +26 -7
- LOGS/Entity/ConnectedEntity.py +39 -1
- LOGS/Entity/Entity.py +9 -14
- LOGS/Entity/SerializeableContent.py +62 -5
- LOGS/Interfaces/IHierarchyType.py +63 -0
- LOGS/Interfaces/IPermissionedEntity.py +29 -5
- LOGS/Interfaces/IProjectBased.py +1 -1
- LOGS/Interfaces/ITypedEntity.py +69 -12
- LOGS/Interfaces/IVersionedEntity.py +39 -0
- LOGS/LOGS.py +137 -46
- LOGS/LOGSConnection.py +52 -24
- LOGS/LOGSOptions.py +8 -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/__init__.py +1 -0
- {logs_py-2.9.6.dist-info → logs_py-3.0.1.dist-info}/METADATA +2 -1
- logs_py-3.0.1.dist-info/RECORD +263 -0
- LOGS/Entities/CustomFieldEnums.py +0 -25
- LOGS/Entities/DatasetType.py +0 -7
- LOGS/Entities/DatasetTypeMinimal.py +0 -8
- LOGS/Entities/SampleType.py +0 -34
- LOGS/Entities/SampleTypeMinimal.py +0 -8
- LOGS/Entities/SampleTypeRequestParameter.py +0 -8
- LOGS/Entities/SampleTypes.py +0 -12
- logs_py-2.9.6.dist-info/RECORD +0 -183
- {logs_py-2.9.6.dist-info → logs_py-3.0.1.dist-info}/WHEEL +0 -0
- {logs_py-2.9.6.dist-info → logs_py-3.0.1.dist-info}/top_level.txt +0 -0
LOGS/LOGS.py
CHANGED
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
"""
|
|
3
3
|
A library to access the LOGS API via Python
|
|
4
4
|
"""
|
|
5
|
-
# +---------------+-----------+--------------+-------------------------+
|
|
6
|
-
# | When | Version | Who | What |
|
|
7
|
-
# +===============+===========+==============+=========================+
|
|
8
|
-
# | 2021-07-16 | 0.1 | Sina Kazemi | First version |
|
|
9
|
-
# +---------------+-----------+--------------+-------------------------+
|
|
10
|
-
# | 2021-09-18 | 1.0 | Sina Kazemi | First official release |
|
|
11
|
-
# +---------------+-----------+--------------+-------------------------+
|
|
12
5
|
|
|
13
6
|
import json
|
|
14
7
|
import os
|
|
@@ -36,13 +29,15 @@ from LOGS.Auxiliary import (
|
|
|
36
29
|
Tools,
|
|
37
30
|
formatErrorMessage,
|
|
38
31
|
)
|
|
39
|
-
from LOGS.Entities import SampleType
|
|
40
32
|
from LOGS.Entities.Bridge import Bridge
|
|
41
33
|
from LOGS.Entities.BridgeRequestParameter import BridgeRequestParameter
|
|
42
34
|
from LOGS.Entities.Bridges import Bridges
|
|
43
35
|
from LOGS.Entities.CustomField import CustomField
|
|
44
36
|
from LOGS.Entities.CustomFieldRequestParameter import CustomFieldRequestParameter
|
|
45
37
|
from LOGS.Entities.CustomFields import CustomFields
|
|
38
|
+
from LOGS.Entities.CustomType import CustomType
|
|
39
|
+
from LOGS.Entities.CustomTypeRequestParameter import CustomTypeRequestParameter
|
|
40
|
+
from LOGS.Entities.CustomTypes import CustomTypes
|
|
46
41
|
from LOGS.Entities.Dataset import Dataset
|
|
47
42
|
from LOGS.Entities.DatasetCreator import DatasetCreator
|
|
48
43
|
from LOGS.Entities.DatasetMatching import DatasetMatching
|
|
@@ -83,11 +78,22 @@ from LOGS.Entities.FormatVendors import FormatVendors
|
|
|
83
78
|
from LOGS.Entities.Instrument import Instrument
|
|
84
79
|
from LOGS.Entities.InstrumentRequestParameter import InstrumentRequestParameter
|
|
85
80
|
from LOGS.Entities.Instruments import Instruments
|
|
81
|
+
from LOGS.Entities.Inventories import Inventories
|
|
82
|
+
from LOGS.Entities.Inventory import Inventory
|
|
83
|
+
from LOGS.Entities.InventoryRequestParameter import InventoryRequestParameter
|
|
84
|
+
from LOGS.Entities.LabNotebook import LabNotebook
|
|
86
85
|
from LOGS.Entities.LabNotebookEntries import LabNotebookEntries
|
|
87
86
|
from LOGS.Entities.LabNotebookEntry import LabNotebookEntry
|
|
88
87
|
from LOGS.Entities.LabNotebookEntryRequestParameter import (
|
|
89
88
|
LabNotebookEntryRequestParameter,
|
|
90
89
|
)
|
|
90
|
+
from LOGS.Entities.LabNotebookExperiment import LabNotebookExperiment
|
|
91
|
+
from LOGS.Entities.LabNotebookExperimentRequestParameter import (
|
|
92
|
+
LabNotebookExperimentRequestParameter,
|
|
93
|
+
)
|
|
94
|
+
from LOGS.Entities.LabNotebookExperiments import LabNotebookExperiments
|
|
95
|
+
from LOGS.Entities.LabNotebookRequestParameter import LabNotebookRequestParameter
|
|
96
|
+
from LOGS.Entities.LabNotebooks import LabNotebooks
|
|
91
97
|
from LOGS.Entities.Method import Method
|
|
92
98
|
from LOGS.Entities.MethodRequestParameter import MethodRequestParameter
|
|
93
99
|
from LOGS.Entities.Methods import Methods
|
|
@@ -106,39 +112,41 @@ from LOGS.Entities.Roles import Roles
|
|
|
106
112
|
from LOGS.Entities.Sample import Sample
|
|
107
113
|
from LOGS.Entities.SampleRequestParameter import SampleRequestParameter
|
|
108
114
|
from LOGS.Entities.Samples import Samples
|
|
109
|
-
from LOGS.Entities.SampleTypeRequestParameter import SampleTypeRequestParameter
|
|
110
|
-
from LOGS.Entities.SampleTypes import SampleTypes
|
|
111
115
|
from LOGS.Entity import Entity, EntityIterator, IEntityWithIntId
|
|
112
116
|
from LOGS.Entity.ConnectedEntity import ConnectedEntity
|
|
113
117
|
from LOGS.Interfaces.ISoftDeletable import ISoftDeletable
|
|
114
118
|
from LOGS.Interfaces.IUniqueEntity import IUniqueEntity
|
|
115
119
|
from LOGS.LOGSConnection import LOGSConnection
|
|
120
|
+
from LOGS.LOGSOptions import LOGSOptions
|
|
116
121
|
from LOGS.ServerMetaData import ServerMetaData
|
|
117
122
|
|
|
118
123
|
_T = TypeVar(
|
|
119
124
|
"_T",
|
|
120
|
-
Document,
|
|
121
|
-
Person,
|
|
122
|
-
Project,
|
|
123
|
-
Sample,
|
|
124
|
-
Dataset,
|
|
125
125
|
Bridge,
|
|
126
|
+
CustomField,
|
|
127
|
+
CustomType,
|
|
128
|
+
Dataset,
|
|
126
129
|
DataSource,
|
|
130
|
+
Document,
|
|
127
131
|
Equipment,
|
|
128
132
|
Experiment,
|
|
133
|
+
Format,
|
|
134
|
+
FormatFormat,
|
|
135
|
+
FormatInstrument,
|
|
136
|
+
FormatMethod,
|
|
137
|
+
FormatVendor,
|
|
138
|
+
IEntityWithIntId,
|
|
129
139
|
Instrument,
|
|
130
|
-
|
|
140
|
+
Inventory,
|
|
141
|
+
LabNotebook,
|
|
131
142
|
LabNotebookEntry,
|
|
132
|
-
|
|
143
|
+
LabNotebookExperiment,
|
|
144
|
+
Method,
|
|
133
145
|
Origin,
|
|
134
|
-
|
|
146
|
+
Person,
|
|
147
|
+
Project,
|
|
135
148
|
Role,
|
|
136
|
-
|
|
137
|
-
FormatMethod,
|
|
138
|
-
FormatInstrument,
|
|
139
|
-
FormatFormat,
|
|
140
|
-
CustomField,
|
|
141
|
-
SampleType,
|
|
149
|
+
Sample,
|
|
142
150
|
)
|
|
143
151
|
|
|
144
152
|
|
|
@@ -147,32 +155,36 @@ class LOGS:
|
|
|
147
155
|
|
|
148
156
|
_connection: LOGSConnection
|
|
149
157
|
_entities: List[Type] = [
|
|
150
|
-
Document,
|
|
151
|
-
Person,
|
|
152
|
-
Project,
|
|
153
|
-
Sample,
|
|
154
|
-
Dataset,
|
|
155
158
|
Bridge,
|
|
159
|
+
CustomField,
|
|
160
|
+
CustomType,
|
|
161
|
+
Dataset,
|
|
156
162
|
DataSource,
|
|
163
|
+
Document,
|
|
157
164
|
Equipment,
|
|
158
165
|
Experiment,
|
|
159
166
|
Instrument,
|
|
160
|
-
|
|
167
|
+
Inventory,
|
|
168
|
+
LabNotebook,
|
|
161
169
|
LabNotebookEntry,
|
|
170
|
+
LabNotebookExperiment,
|
|
171
|
+
Method,
|
|
162
172
|
Origin,
|
|
163
|
-
|
|
164
|
-
|
|
173
|
+
Person,
|
|
174
|
+
Project,
|
|
175
|
+
Sample,
|
|
165
176
|
]
|
|
166
177
|
_entityByName = {t.__name__: t for t in _entities}
|
|
167
178
|
_defaultConfigFile: str = "logs.json"
|
|
168
179
|
_currentUser: Person
|
|
180
|
+
_cacheDir: Optional[str] = None
|
|
169
181
|
|
|
170
182
|
def __init__(
|
|
171
183
|
self,
|
|
172
184
|
url: Optional[str] = None,
|
|
173
185
|
apiKey: Optional[str] = None,
|
|
174
186
|
configFile: Optional[str] = None,
|
|
175
|
-
|
|
187
|
+
options: Optional[LOGSOptions] = None,
|
|
176
188
|
verify: bool = True,
|
|
177
189
|
):
|
|
178
190
|
"""Checks the connection to the server on creation
|
|
@@ -185,6 +197,10 @@ class LOGS:
|
|
|
185
197
|
:raises: Exception: The URL does not define a group.
|
|
186
198
|
:raises: Exception: Server cannot be reached.
|
|
187
199
|
"""
|
|
200
|
+
self._options = Tools.checkAndConvert(
|
|
201
|
+
options, LOGSOptions, "options", initOnNone=True
|
|
202
|
+
)
|
|
203
|
+
|
|
188
204
|
_url = url
|
|
189
205
|
_apiKey = apiKey
|
|
190
206
|
|
|
@@ -212,13 +228,11 @@ class LOGS:
|
|
|
212
228
|
"The API key to access the server %a must be provided" % _url
|
|
213
229
|
)
|
|
214
230
|
|
|
215
|
-
self.verbose = verbose
|
|
216
231
|
self.promptPrefix = "LOGSAPI>"
|
|
217
232
|
|
|
218
233
|
self._connection = LOGSConnection(
|
|
219
|
-
url=_url, apiKey=_apiKey,
|
|
234
|
+
url=_url, apiKey=_apiKey, options=self._options, verify=verify
|
|
220
235
|
)
|
|
221
|
-
|
|
222
236
|
self._currentUser = self._fetchCurrentUser()
|
|
223
237
|
|
|
224
238
|
def _fetchCurrentUser(self) -> Person:
|
|
@@ -263,8 +277,23 @@ class LOGS:
|
|
|
263
277
|
size /= 1024.0
|
|
264
278
|
return "%.1f%s%s" % (size, "Yi", suffix)
|
|
265
279
|
|
|
280
|
+
def getDatasetDir(self, dataset: Dataset):
|
|
281
|
+
if self.cacheDir:
|
|
282
|
+
if not os.path.isdir(self.cacheDir):
|
|
283
|
+
raise LOGSException(
|
|
284
|
+
f"Specified cache directory '{self.cacheDir}' cannot be opened or is not a directory."
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
dataDir = os.path.join(self.cacheDir, dataset.cacheId)
|
|
288
|
+
if dataDir and not os.path.exists(dataDir):
|
|
289
|
+
os.mkdir(dataDir)
|
|
290
|
+
return dataDir
|
|
291
|
+
return None
|
|
292
|
+
|
|
266
293
|
def _fetchEntity(self, entityType: Type[_T], id: Union[int, str]) -> _T:
|
|
267
294
|
e = entityType(id=cast(Any, id), connection=self._connection)
|
|
295
|
+
if isinstance(e, Dataset):
|
|
296
|
+
e.cacheDir = self.getDatasetDir(e)
|
|
268
297
|
e.fetch()
|
|
269
298
|
return e
|
|
270
299
|
|
|
@@ -947,6 +976,42 @@ class LOGS:
|
|
|
947
976
|
)
|
|
948
977
|
return DataSources(connection=self._connection, parameters=parameter)
|
|
949
978
|
|
|
979
|
+
def labNotebook(self, id: int) -> LabNotebook:
|
|
980
|
+
return self._fetchEntity(LabNotebook, id)
|
|
981
|
+
|
|
982
|
+
def labNotebooks(
|
|
983
|
+
self, parameter: Optional[LabNotebookRequestParameter] = None
|
|
984
|
+
) -> LabNotebooks:
|
|
985
|
+
if parameter and not isinstance(parameter, LabNotebookRequestParameter):
|
|
986
|
+
raise LOGSException(
|
|
987
|
+
"Parameter for %s.LabNotebooks must be of type %a. (Got %a)"
|
|
988
|
+
% (
|
|
989
|
+
type(self).__name__,
|
|
990
|
+
LabNotebookRequestParameter.__name__,
|
|
991
|
+
type(parameter).__name__,
|
|
992
|
+
)
|
|
993
|
+
)
|
|
994
|
+
return LabNotebooks(connection=self._connection, parameters=parameter)
|
|
995
|
+
|
|
996
|
+
def labNotebookExperiment(self, id: int) -> LabNotebookExperiment:
|
|
997
|
+
return self._fetchEntity(LabNotebookExperiment, id)
|
|
998
|
+
|
|
999
|
+
def labNotebookExperiments(
|
|
1000
|
+
self, parameter: Optional[LabNotebookExperimentRequestParameter] = None
|
|
1001
|
+
) -> LabNotebookExperiments:
|
|
1002
|
+
if parameter and not isinstance(
|
|
1003
|
+
parameter, LabNotebookExperimentRequestParameter
|
|
1004
|
+
):
|
|
1005
|
+
raise LOGSException(
|
|
1006
|
+
"Parameter for %s.LabNotebookExperiments must be of type %a. (Got %a)"
|
|
1007
|
+
% (
|
|
1008
|
+
type(self).__name__,
|
|
1009
|
+
LabNotebookExperimentRequestParameter.__name__,
|
|
1010
|
+
type(parameter).__name__,
|
|
1011
|
+
)
|
|
1012
|
+
)
|
|
1013
|
+
return LabNotebookExperiments(connection=self._connection, parameters=parameter)
|
|
1014
|
+
|
|
950
1015
|
def labNotebookEntry(self, id: int) -> LabNotebookEntry:
|
|
951
1016
|
return self._fetchEntity(LabNotebookEntry, id)
|
|
952
1017
|
|
|
@@ -1049,22 +1114,39 @@ class LOGS:
|
|
|
1049
1114
|
)
|
|
1050
1115
|
return CustomFields(connection=self._connection, parameters=parameter)
|
|
1051
1116
|
|
|
1052
|
-
def
|
|
1053
|
-
return self._fetchEntity(
|
|
1117
|
+
def customType(self, id: int) -> CustomType:
|
|
1118
|
+
return self._fetchEntity(CustomType, id)
|
|
1054
1119
|
|
|
1055
|
-
def
|
|
1056
|
-
self, parameter: Optional[
|
|
1057
|
-
) ->
|
|
1058
|
-
if parameter and not isinstance(parameter,
|
|
1120
|
+
def customTypes(
|
|
1121
|
+
self, parameter: Optional[CustomTypeRequestParameter] = None
|
|
1122
|
+
) -> CustomTypes:
|
|
1123
|
+
if parameter and not isinstance(parameter, CustomTypeRequestParameter):
|
|
1059
1124
|
raise LOGSException(
|
|
1060
|
-
"Parameter for %s.
|
|
1125
|
+
"Parameter for %s.CustomTypes must be of type %a. (Got %a)"
|
|
1061
1126
|
% (
|
|
1062
1127
|
type(self).__name__,
|
|
1063
|
-
|
|
1128
|
+
CustomTypeRequestParameter.__name__,
|
|
1064
1129
|
type(parameter).__name__,
|
|
1065
1130
|
)
|
|
1066
1131
|
)
|
|
1067
|
-
return
|
|
1132
|
+
return CustomTypes(connection=self._connection, parameters=parameter)
|
|
1133
|
+
|
|
1134
|
+
def inventory(self, id: int) -> Inventory:
|
|
1135
|
+
return self._fetchEntity(Inventory, id)
|
|
1136
|
+
|
|
1137
|
+
def inventories(
|
|
1138
|
+
self, parameter: Optional[InventoryRequestParameter] = None
|
|
1139
|
+
) -> Inventories:
|
|
1140
|
+
if parameter and not isinstance(parameter, InventoryRequestParameter):
|
|
1141
|
+
raise LOGSException(
|
|
1142
|
+
"Parameter for %s.Inventories must be of type %a. (Got %a)"
|
|
1143
|
+
% (
|
|
1144
|
+
type(self).__name__,
|
|
1145
|
+
InventoryRequestParameter.__name__,
|
|
1146
|
+
type(parameter).__name__,
|
|
1147
|
+
)
|
|
1148
|
+
)
|
|
1149
|
+
return Inventories(connection=self._connection, parameters=parameter)
|
|
1068
1150
|
|
|
1069
1151
|
def entity(self, uid: str):
|
|
1070
1152
|
return Entities(connection=self._connection).fetch(uid=uid)
|
|
@@ -1127,6 +1209,13 @@ class LOGS:
|
|
|
1127
1209
|
return self._currentUser
|
|
1128
1210
|
|
|
1129
1211
|
@property
|
|
1212
|
+
def cacheDir(self) -> Optional[str]:
|
|
1213
|
+
return self._cacheDir
|
|
1214
|
+
|
|
1215
|
+
@cacheDir.setter
|
|
1216
|
+
def cacheDir(self, value):
|
|
1217
|
+
self._cacheDir = Tools.checkAndConvert(value, str, "cacheDir")
|
|
1218
|
+
|
|
1130
1219
|
def version(self) -> Optional[str]:
|
|
1131
1220
|
return self._connection.metadata.version
|
|
1132
1221
|
|
|
@@ -1143,4 +1232,6 @@ if __name__ == "__main__":
|
|
|
1143
1232
|
# api_key = "8V6oQ804t2nPgGPDJIk4CuneRI5q48ERUxgEpk+YqXzX9uLuMUySycHkeXP6DefN"
|
|
1144
1233
|
# url = "http://localhost:900/sandbox"
|
|
1145
1234
|
|
|
1146
|
-
logs = LOGS(
|
|
1235
|
+
logs = LOGS(
|
|
1236
|
+
_url, api_key, options=LOGSOptions(showRequestUrl=True, showRequestBody=False)
|
|
1237
|
+
)
|
LOGS/LOGSConnection.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import random
|
|
2
3
|
import re
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from enum import Enum
|
|
@@ -10,6 +11,7 @@ from requests import Response
|
|
|
10
11
|
from LOGS.Auxiliary import LOGSException, Tools
|
|
11
12
|
from LOGS.Auxiliary.LOGSErrorResponse import LOGSErrorResponse
|
|
12
13
|
from LOGS.Entities.FileEntry import FileEntry
|
|
14
|
+
from LOGS.LOGSOptions import LOGSOptions
|
|
13
15
|
from LOGS.ServerMetaData import ServerMetaData
|
|
14
16
|
|
|
15
17
|
|
|
@@ -32,7 +34,7 @@ class LOGSConnection:
|
|
|
32
34
|
"""Python class to access the LOGS web API"""
|
|
33
35
|
|
|
34
36
|
_noErrorStates = set([200, 201, 204])
|
|
35
|
-
_compatibleAPIVersions = set(["
|
|
37
|
+
_compatibleAPIVersions = set(["3.0"])
|
|
36
38
|
# _compatibleAPIVersions = set(["1.1"])
|
|
37
39
|
__urlRe = re.compile(r"(?:(https*)\:\/\/)*([^\/:]+)(?:\:(\d+))*(?:\/(.*))*")
|
|
38
40
|
__urlApiRe = re.compile(r"api\/(\d+\.\d+)")
|
|
@@ -45,7 +47,7 @@ class LOGSConnection:
|
|
|
45
47
|
url: str,
|
|
46
48
|
apiKey: str,
|
|
47
49
|
use_internal: bool = False,
|
|
48
|
-
|
|
50
|
+
options: Optional[LOGSOptions] = None,
|
|
49
51
|
verify: bool = True,
|
|
50
52
|
):
|
|
51
53
|
"""Checks the connection to the server on creation
|
|
@@ -58,13 +60,14 @@ class LOGSConnection:
|
|
|
58
60
|
:raises Exception: The URL does not define a group.
|
|
59
61
|
:raises Exception: Server cannot be reached.
|
|
60
62
|
"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
self._options = Tools.checkAndConvert(
|
|
64
|
+
options, LOGSOptions, "options", initOnNone=True
|
|
65
|
+
)
|
|
63
66
|
self.promptPrefix = "LOGSAPI>"
|
|
64
67
|
|
|
65
68
|
self.url = url
|
|
66
69
|
|
|
67
|
-
if self.
|
|
70
|
+
if self._options.showServerInfo:
|
|
68
71
|
self.printServerStatus()
|
|
69
72
|
|
|
70
73
|
self._apiKey = apiKey
|
|
@@ -127,8 +130,10 @@ class LOGSConnection:
|
|
|
127
130
|
result, error = self.getEndpoint(testEndpoint)
|
|
128
131
|
url = result["url"] if isinstance(result, dict) else self.url
|
|
129
132
|
if error:
|
|
130
|
-
raise LOGSException(
|
|
131
|
-
|
|
133
|
+
raise LOGSException(
|
|
134
|
+
"Could not connect to '%s': %s" % (url, "\n".join(error.errors))
|
|
135
|
+
)
|
|
136
|
+
if self._options.showServerInfo:
|
|
132
137
|
print(
|
|
133
138
|
self.promptPrefix,
|
|
134
139
|
"Connection to server '%s://%s%s' successful."
|
|
@@ -236,7 +241,7 @@ class LOGSConnection:
|
|
|
236
241
|
|
|
237
242
|
:return: The respose of the server and the error code.
|
|
238
243
|
"""
|
|
239
|
-
if self.
|
|
244
|
+
if self._options.showRequestUrl:
|
|
240
245
|
paramString = ""
|
|
241
246
|
if parameters:
|
|
242
247
|
paramString = " ".join(
|
|
@@ -282,7 +287,7 @@ class LOGSConnection:
|
|
|
282
287
|
:return: The respose of the server and the error code.
|
|
283
288
|
"""
|
|
284
289
|
|
|
285
|
-
if self.
|
|
290
|
+
if self._options.showRequestUrl:
|
|
286
291
|
print(self.promptPrefix, "DELETE: %s" % url)
|
|
287
292
|
|
|
288
293
|
response = requests.delete(
|
|
@@ -305,9 +310,12 @@ class LOGSConnection:
|
|
|
305
310
|
:return: The respose of the server and the error code.
|
|
306
311
|
"""
|
|
307
312
|
|
|
308
|
-
if self.
|
|
313
|
+
if self._options.showRequestUrl:
|
|
309
314
|
print(self.promptPrefix, "PUT: %s" % url)
|
|
310
315
|
|
|
316
|
+
if self._options.showRequestBody:
|
|
317
|
+
print(self.promptPrefix, "BODY: %s" % self.__convertBody(data))
|
|
318
|
+
|
|
311
319
|
response = requests.put(
|
|
312
320
|
url, headers=self.getHeader(), json=data, verify=self._verify
|
|
313
321
|
)
|
|
@@ -336,9 +344,14 @@ class LOGSConnection:
|
|
|
336
344
|
data: List[MultipartEntry] = [],
|
|
337
345
|
responseType: ResponseTypes = ResponseTypes.JSON,
|
|
338
346
|
):
|
|
339
|
-
if self.
|
|
347
|
+
if self._options.showRequestUrl:
|
|
340
348
|
print(self.promptPrefix, "POST: %s" % url)
|
|
341
349
|
|
|
350
|
+
if self._options.showRequestBody:
|
|
351
|
+
seperator = "-" * 29 + "".join(
|
|
352
|
+
[str(random.randint(0, 9)) for _ in range(29)]
|
|
353
|
+
)
|
|
354
|
+
|
|
342
355
|
files = []
|
|
343
356
|
for entry in data:
|
|
344
357
|
content: Any = ""
|
|
@@ -348,6 +361,22 @@ class LOGSConnection:
|
|
|
348
361
|
content = read.read()
|
|
349
362
|
else:
|
|
350
363
|
content = json.dumps(entry.content)
|
|
364
|
+
|
|
365
|
+
if self._options.showRequestBody:
|
|
366
|
+
print(self.promptPrefix, "BODY: %s" % seperator)
|
|
367
|
+
print(
|
|
368
|
+
self.promptPrefix,
|
|
369
|
+
"BODY: %s"
|
|
370
|
+
% "Content-Disposition: form-data; name='entry.fileName'",
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
c = (
|
|
374
|
+
str(content[:100]) + "..."
|
|
375
|
+
if isinstance(content, bytes) and len(content) > 100
|
|
376
|
+
else content
|
|
377
|
+
)
|
|
378
|
+
print(self.promptPrefix, "BODY: %s" % c)
|
|
379
|
+
|
|
351
380
|
files.append((entry.name, (entry.fileName, content)))
|
|
352
381
|
|
|
353
382
|
#### For checking the request
|
|
@@ -378,19 +407,7 @@ class LOGSConnection:
|
|
|
378
407
|
|
|
379
408
|
:return: The respose of the server and the error code.
|
|
380
409
|
"""
|
|
381
|
-
if self.
|
|
382
|
-
paramString = ""
|
|
383
|
-
if parameters:
|
|
384
|
-
paramString = " ".join(
|
|
385
|
-
("%s:%s" % (k, v))
|
|
386
|
-
for k, v in parameters.items()
|
|
387
|
-
if v != None and v != ""
|
|
388
|
-
)
|
|
389
|
-
print(
|
|
390
|
-
self.promptPrefix,
|
|
391
|
-
"GET: %s %s" % (url, "{" + paramString + "}" if paramString else ""),
|
|
392
|
-
)
|
|
393
|
-
if self.verbose:
|
|
410
|
+
if self._options.showRequestUrl:
|
|
394
411
|
paramString = ""
|
|
395
412
|
if parameters:
|
|
396
413
|
paramString = " ".join(
|
|
@@ -403,6 +420,9 @@ class LOGSConnection:
|
|
|
403
420
|
"POST: %s %s" % (url, "{" + paramString + "}" if paramString else ""),
|
|
404
421
|
)
|
|
405
422
|
|
|
423
|
+
if self._options.showRequestBody:
|
|
424
|
+
print(self.promptPrefix, "BODY: %s" % self.__convertBody(data))
|
|
425
|
+
|
|
406
426
|
response = requests.post(
|
|
407
427
|
url,
|
|
408
428
|
headers=self.getHeader(),
|
|
@@ -502,6 +522,14 @@ class LOGSConnection:
|
|
|
502
522
|
# # print(">", params)
|
|
503
523
|
# return {"customFields[%s]" % k: v for k, v in params.items()}
|
|
504
524
|
|
|
525
|
+
@classmethod
|
|
526
|
+
def __convertBody(cls, body) -> str:
|
|
527
|
+
if body == None:
|
|
528
|
+
return "None"
|
|
529
|
+
if isinstance(body, dict) or isinstance(body, list):
|
|
530
|
+
return json.dumps(body)
|
|
531
|
+
return body
|
|
532
|
+
|
|
505
533
|
def __convertResponse(
|
|
506
534
|
self,
|
|
507
535
|
response: Response,
|
LOGS/LOGSOptions.py
ADDED
LOGS/Parameters/Color.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from LOGS.Entity.SerializeableContent import SerializeableContent
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SingleColor(SerializeableContent):
|
|
7
|
+
_color: str
|
|
8
|
+
_offset: Optional[float]
|
|
9
|
+
_value: Optional[float]
|
|
10
|
+
|
|
11
|
+
@classmethod
|
|
12
|
+
def bgrIntSigned32bit_to_hexcolor(cls, bgrInt: int):
|
|
13
|
+
b = bgrInt & 2**8 - 1
|
|
14
|
+
g = (bgrInt >> 8) & 2**8 - 1
|
|
15
|
+
r = (bgrInt >> 16) & 2**8 - 1
|
|
16
|
+
return "#%02x%02x%02x" % (r, g, b)
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def color(self) -> str:
|
|
20
|
+
return self._color
|
|
21
|
+
|
|
22
|
+
@color.setter
|
|
23
|
+
def color(self, value):
|
|
24
|
+
self._color = value
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def offset(self) -> Optional[float]:
|
|
28
|
+
return self._offset
|
|
29
|
+
|
|
30
|
+
@offset.setter
|
|
31
|
+
def offset(self, value):
|
|
32
|
+
value = self.checkAndConvert(
|
|
33
|
+
value, fieldName="offset", fieldType=float, allowNone=True
|
|
34
|
+
)
|
|
35
|
+
if value < 0:
|
|
36
|
+
raise Exception("Color offset value must be >= 0. (Got %f)" % value)
|
|
37
|
+
if value > 1:
|
|
38
|
+
raise Exception("Color offset value must be <= 1. (Got %f)" % value)
|
|
39
|
+
self._offset = value
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def value(self) -> Optional[float]:
|
|
43
|
+
return self._value
|
|
44
|
+
|
|
45
|
+
@value.setter
|
|
46
|
+
def value(self, value):
|
|
47
|
+
self._value = value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Color(SerializeableContent):
|
|
51
|
+
_colors: List[SingleColor]
|
|
52
|
+
_discrete: Optional[bool]
|
|
53
|
+
_reverse: Optional[bool]
|
|
54
|
+
|
|
55
|
+
def __init__(self, ref=None):
|
|
56
|
+
if ref != None:
|
|
57
|
+
if isinstance(ref, str):
|
|
58
|
+
ref = {"colors": [ref]}
|
|
59
|
+
elif isinstance(ref, list):
|
|
60
|
+
ref = {"colors": ref}
|
|
61
|
+
|
|
62
|
+
super().__init__(ref)
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def bgrIntSigned32bit_to_hexcolor(cls, bgrInt: int):
|
|
66
|
+
return SingleColor.bgrIntSigned32bit_to_hexcolor(bgrInt=bgrInt)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def colors(self) -> List[SingleColor]:
|
|
70
|
+
return self._colors
|
|
71
|
+
|
|
72
|
+
@colors.setter
|
|
73
|
+
def colors(self, value):
|
|
74
|
+
self._colors = self.checkListAndConvert(
|
|
75
|
+
value, fieldType=SingleColor, fieldName="colors"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def discrete(self) -> Optional[bool]:
|
|
80
|
+
return self._discrete
|
|
81
|
+
|
|
82
|
+
@discrete.setter
|
|
83
|
+
def discrete(self, value):
|
|
84
|
+
self._discrete = bool(value)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def reverse(self) -> Optional[bool]:
|
|
88
|
+
return self._reverse
|
|
89
|
+
|
|
90
|
+
@reverse.setter
|
|
91
|
+
def reverse(self, value):
|
|
92
|
+
self._reverse = bool(value)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
from LOGS.Entity.SerializeableContent import SerializeableContent
|
|
4
|
+
from LOGS.Parameters.Color import Color
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ParameterBase(SerializeableContent):
|
|
8
|
+
_name: str = ""
|
|
9
|
+
_tracks: Optional[List[str]] = None
|
|
10
|
+
_colors: List[Color] = []
|
|
11
|
+
_active: bool = True
|
|
12
|
+
_type: str = "None"
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def name(self) -> str:
|
|
16
|
+
return self._name
|
|
17
|
+
|
|
18
|
+
@name.setter
|
|
19
|
+
def name(self, value):
|
|
20
|
+
self._name = self.checkAndConvert(value, fieldType=str, fieldName="name")
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def tracks(self) -> Optional[List[str]]:
|
|
24
|
+
return self._tracks
|
|
25
|
+
|
|
26
|
+
@tracks.setter
|
|
27
|
+
def tracks(self, value):
|
|
28
|
+
self._tracks = self.checkListAndConvert(
|
|
29
|
+
value, fieldType=str, fieldName="tracks"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def active(self) -> bool:
|
|
34
|
+
return self._active
|
|
35
|
+
|
|
36
|
+
@active.setter
|
|
37
|
+
def active(self, value):
|
|
38
|
+
self._active = bool(value)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def colors(self) -> Optional[List[Color]]:
|
|
42
|
+
if len(self._colors) < 1:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
return self._colors
|
|
46
|
+
|
|
47
|
+
@colors.setter
|
|
48
|
+
def colors(self, value):
|
|
49
|
+
self._colors = self.checkListAndConvert(
|
|
50
|
+
value, fieldType=Color, fieldName="colors"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def type(self) -> str:
|
|
55
|
+
return self._type
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import cast
|
|
2
|
+
|
|
3
|
+
from LOGS.Parameters.ParameterBase import ParameterBase
|
|
4
|
+
from LOGS.Parameters.ParameterElement import ParameterElement
|
|
5
|
+
from LOGS.Parameters.ParameterList import ParameterList
|
|
6
|
+
from LOGS.Parameters.ParameterTable import ParameterTable
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ParameterConverter:
|
|
10
|
+
@classmethod
|
|
11
|
+
def convert(cls, parameter):
|
|
12
|
+
if not isinstance(parameter, dict) or "type" not in parameter:
|
|
13
|
+
return cast(ParameterBase, None)
|
|
14
|
+
|
|
15
|
+
if parameter["type"] == "parameter":
|
|
16
|
+
return ParameterElement(parameter)
|
|
17
|
+
|
|
18
|
+
if parameter["type"] == "list":
|
|
19
|
+
return ParameterList(parameter)
|
|
20
|
+
|
|
21
|
+
if parameter["type"] == "table":
|
|
22
|
+
return ParameterTable(parameter)
|
|
23
|
+
|
|
24
|
+
return cast(ParameterBase, None)
|