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.

Files changed (147) hide show
  1. LOGS/Auxiliary/DateTimeConverter.py +11 -1
  2. LOGS/Auxiliary/Exceptions.py +40 -4
  3. LOGS/Auxiliary/LOGSErrorResponse.py +4 -1
  4. LOGS/Auxiliary/MinimalModelGenerator.py +88 -28
  5. LOGS/Auxiliary/Tools.py +11 -0
  6. LOGS/Converter/Conversion.py +248 -0
  7. LOGS/Converter/Converter.py +96 -0
  8. LOGS/Converter/ConverterParameter.py +88 -0
  9. LOGS/Converter/ExportParamters.py +89 -0
  10. LOGS/Converter/__init__.py +13 -0
  11. LOGS/Entities/Bridge.py +6 -3
  12. LOGS/Entities/CustomField.py +96 -91
  13. LOGS/Entities/CustomFieldModels.py +57 -0
  14. LOGS/Entities/CustomFieldRelations.py +10 -0
  15. LOGS/Entities/CustomFieldRequestParameter.py +43 -15
  16. LOGS/Entities/CustomFieldValue.py +88 -0
  17. LOGS/Entities/CustomFieldValueConverter.py +66 -0
  18. LOGS/Entities/CustomType.py +187 -0
  19. LOGS/Entities/CustomTypeEntityType.py +11 -0
  20. LOGS/Entities/CustomTypeMinimal.py +8 -0
  21. LOGS/Entities/CustomTypeRelations.py +59 -0
  22. LOGS/Entities/CustomTypeRequestParameter.py +61 -0
  23. LOGS/Entities/CustomTypeSection.py +39 -0
  24. LOGS/Entities/CustomTypes.py +12 -0
  25. LOGS/Entities/DataSource.py +28 -14
  26. LOGS/Entities/Dataset.py +274 -136
  27. LOGS/Entities/DatasetCreator.py +23 -72
  28. LOGS/Entities/DatasetInfo.py +23 -2
  29. LOGS/Entities/DatasetModels.py +31 -0
  30. LOGS/Entities/DatasetRequestParameter.py +45 -32
  31. LOGS/Entities/Datatrack.py +74 -30
  32. LOGS/Entities/DatatrackFormattedTable.py +25 -0
  33. LOGS/Entities/DatatrackGeneric.py +34 -0
  34. LOGS/Entities/DatatrackImage.py +25 -0
  35. LOGS/Entities/DatatrackNumericArray.py +9 -39
  36. LOGS/Entities/DatatrackNumericMatrix.py +86 -0
  37. LOGS/Entities/DocumentRequestParameter.py +2 -2
  38. LOGS/Entities/EntitiesRequestParameter.py +2 -2
  39. LOGS/Entities/Experiment.py +3 -3
  40. LOGS/Entities/FileExcludePattern.py +8 -0
  41. LOGS/Entities/FormatFormat.py +22 -1
  42. LOGS/Entities/FormatFormatRequestParameter.py +2 -1
  43. LOGS/Entities/FormatFormats.py +1 -1
  44. LOGS/Entities/FormattedTable/DatatypeFormattedTable.py +135 -0
  45. LOGS/Entities/FormattedTable/DatatypeFormattedTableCell.py +108 -0
  46. LOGS/Entities/FormattedTable/DatatypeFormattedTableSettings.py +11 -0
  47. LOGS/Entities/FormattedTable/__init__.py +9 -0
  48. LOGS/Entities/ILiterarTypedEntity.py +19 -0
  49. LOGS/Entities/Instrument.py +3 -3
  50. LOGS/Entities/Inventories.py +12 -0
  51. LOGS/Entities/Inventory.py +95 -0
  52. LOGS/Entities/InventoryMinimal.py +20 -0
  53. LOGS/Entities/InventoryRelations.py +23 -0
  54. LOGS/Entities/InventoryRequestParameter.py +53 -0
  55. LOGS/Entities/LabNotebook.py +37 -0
  56. LOGS/Entities/LabNotebookEntry.py +47 -24
  57. LOGS/Entities/LabNotebookEntryContent/BasicAttribute.py +15 -0
  58. LOGS/Entities/LabNotebookEntryContent/EntityAttribute.py +85 -0
  59. LOGS/Entities/LabNotebookEntryContent/EntryContentBlockquote.py +13 -0
  60. LOGS/Entities/LabNotebookEntryContent/EntryContentBulletList.py +17 -0
  61. LOGS/Entities/LabNotebookEntryContent/EntryContentCallout.py +40 -0
  62. LOGS/Entities/LabNotebookEntryContent/EntryContentContentPlaceholderNode.py +31 -0
  63. LOGS/Entities/LabNotebookEntryContent/EntryContentConverter.py +207 -0
  64. LOGS/Entities/LabNotebookEntryContent/EntryContentDocument.py +8 -0
  65. LOGS/Entities/LabNotebookEntryContent/EntryContentEntity.py +13 -0
  66. LOGS/Entities/LabNotebookEntryContent/EntryContentEntityMention.py +31 -0
  67. LOGS/Entities/LabNotebookEntryContent/EntryContentHeading.py +33 -0
  68. LOGS/Entities/LabNotebookEntryContent/EntryContentHorizontalRule.py +12 -0
  69. LOGS/Entities/LabNotebookEntryContent/EntryContentItem.py +37 -0
  70. LOGS/Entities/LabNotebookEntryContent/EntryContentListItem.py +49 -0
  71. LOGS/Entities/LabNotebookEntryContent/EntryContentOrderedList.py +31 -0
  72. LOGS/Entities/LabNotebookEntryContent/EntryContentParagraph.py +13 -0
  73. LOGS/Entities/LabNotebookEntryContent/EntryContentTable.py +17 -0
  74. LOGS/Entities/LabNotebookEntryContent/EntryContentTableCell.py +40 -0
  75. LOGS/Entities/LabNotebookEntryContent/EntryContentTableRow.py +8 -0
  76. LOGS/Entities/LabNotebookEntryContent/EntryContentTaskList.py +17 -0
  77. LOGS/Entities/LabNotebookEntryContent/EntryContentTaskListItem.py +31 -0
  78. LOGS/Entities/LabNotebookEntryContent/EntryContentText.py +33 -0
  79. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithAttribute.py +23 -0
  80. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithContent.py +38 -0
  81. LOGS/Entities/LabNotebookEntryContent/IEntryContentWithTextAttribute.py +16 -0
  82. LOGS/Entities/LabNotebookEntryContent/TextAttribute.py +46 -0
  83. LOGS/Entities/LabNotebookEntryContent/TextMarkAtributes.py +64 -0
  84. LOGS/Entities/LabNotebookEntryContent/TextMarkConverter.py +45 -0
  85. LOGS/Entities/LabNotebookEntryContent/TextMarks.py +71 -0
  86. LOGS/Entities/LabNotebookEntryContent/__init__.py +34 -0
  87. LOGS/Entities/LabNotebookEntryRequestParameter.py +2 -0
  88. LOGS/Entities/LabNotebookExperiment.py +52 -0
  89. LOGS/Entities/LabNotebookExperimentMinimal.py +8 -0
  90. LOGS/Entities/LabNotebookExperimentRequestParameter.py +49 -0
  91. LOGS/Entities/LabNotebookExperiments.py +16 -0
  92. LOGS/Entities/LabNotebookMinimal.py +19 -0
  93. LOGS/Entities/LabNotebookModels.py +14 -0
  94. LOGS/Entities/LabNotebookRequestParameter.py +43 -0
  95. LOGS/Entities/LabNotebooks.py +12 -0
  96. LOGS/Entities/Method.py +3 -3
  97. LOGS/Entities/ParserLog.py +4 -0
  98. LOGS/Entities/Person.py +2 -2
  99. LOGS/Entities/PersonRequestParameter.py +1 -0
  100. LOGS/Entities/Project.py +7 -7
  101. LOGS/Entities/{ProjectUserPermission.py → ProjectPersonPermission.py} +14 -4
  102. LOGS/Entities/Role.py +3 -3
  103. LOGS/Entities/RunState.py +1 -0
  104. LOGS/Entities/Sample.py +36 -57
  105. LOGS/Entities/SampleRequestParameter.py +30 -15
  106. LOGS/Entities/Track.py +8 -4
  107. LOGS/Entities/TrackData.py +11 -0
  108. LOGS/Entities/TrackImage.py +21 -0
  109. LOGS/Entities/TrackImageData.py +20 -0
  110. LOGS/Entities/TrackMatrix.py +28 -0
  111. LOGS/Entities/TrackMatrixData.py +22 -0
  112. LOGS/Entities/TrackTable.py +21 -0
  113. LOGS/Entities/TrackTableData.py +22 -0
  114. LOGS/Entities/TrackXY.py +5 -1
  115. LOGS/Entities/TrackXYComplex.py +1 -1
  116. LOGS/Entities/__init__.py +26 -7
  117. LOGS/Entity/ConnectedEntity.py +39 -1
  118. LOGS/Entity/Entity.py +9 -14
  119. LOGS/Entity/SerializeableContent.py +62 -5
  120. LOGS/Interfaces/IHierarchyType.py +63 -0
  121. LOGS/Interfaces/IPermissionedEntity.py +29 -5
  122. LOGS/Interfaces/IProjectBased.py +1 -1
  123. LOGS/Interfaces/ITypedEntity.py +69 -12
  124. LOGS/Interfaces/IVersionedEntity.py +39 -0
  125. LOGS/LOGS.py +137 -46
  126. LOGS/LOGSConnection.py +52 -24
  127. LOGS/LOGSOptions.py +8 -0
  128. LOGS/Parameters/Color.py +92 -0
  129. LOGS/Parameters/ParameterBase.py +55 -0
  130. LOGS/Parameters/ParameterConverter.py +24 -0
  131. LOGS/Parameters/ParameterElement.py +99 -0
  132. LOGS/Parameters/ParameterList.py +52 -0
  133. LOGS/Parameters/ParameterTable.py +64 -0
  134. LOGS/Parameters/__init__.py +13 -0
  135. LOGS/__init__.py +1 -0
  136. {logs_py-2.9.6.dist-info → logs_py-3.0.1.dist-info}/METADATA +2 -1
  137. logs_py-3.0.1.dist-info/RECORD +263 -0
  138. LOGS/Entities/CustomFieldEnums.py +0 -25
  139. LOGS/Entities/DatasetType.py +0 -7
  140. LOGS/Entities/DatasetTypeMinimal.py +0 -8
  141. LOGS/Entities/SampleType.py +0 -34
  142. LOGS/Entities/SampleTypeMinimal.py +0 -8
  143. LOGS/Entities/SampleTypeRequestParameter.py +0 -8
  144. LOGS/Entities/SampleTypes.py +0 -12
  145. logs_py-2.9.6.dist-info/RECORD +0 -183
  146. {logs_py-2.9.6.dist-info → logs_py-3.0.1.dist-info}/WHEEL +0 -0
  147. {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
- Method,
140
+ Inventory,
141
+ LabNotebook,
131
142
  LabNotebookEntry,
132
- IEntityWithIntId,
143
+ LabNotebookExperiment,
144
+ Method,
133
145
  Origin,
134
- Format,
146
+ Person,
147
+ Project,
135
148
  Role,
136
- FormatVendor,
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
- Method,
167
+ Inventory,
168
+ LabNotebook,
161
169
  LabNotebookEntry,
170
+ LabNotebookExperiment,
171
+ Method,
162
172
  Origin,
163
- CustomField,
164
- SampleType,
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
- verbose: bool = False,
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, verbose=verbose, verify=verify
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 sampleType(self, id: str) -> SampleType:
1053
- return self._fetchEntity(SampleType, id)
1117
+ def customType(self, id: int) -> CustomType:
1118
+ return self._fetchEntity(CustomType, id)
1054
1119
 
1055
- def sampleTypes(
1056
- self, parameter: Optional[SampleTypeRequestParameter] = None
1057
- ) -> SampleTypes:
1058
- if parameter and not isinstance(parameter, SampleTypeRequestParameter):
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.SampleTypes must be of type %a. (Got %a)"
1125
+ "Parameter for %s.CustomTypes must be of type %a. (Got %a)"
1061
1126
  % (
1062
1127
  type(self).__name__,
1063
- SampleTypeRequestParameter.__name__,
1128
+ CustomTypeRequestParameter.__name__,
1064
1129
  type(parameter).__name__,
1065
1130
  )
1066
1131
  )
1067
- return SampleTypes(connection=self._connection, parameters=parameter)
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(_url, api_key, verbose=True)
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(["2.0"])
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
- verbose: bool = False,
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
- self.verbose = verbose
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.verbose:
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("Could not connect to '%s': %s" % (url, error))
131
- if self.verbose:
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.verbose:
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.verbose:
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.verbose:
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.verbose:
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.verbose:
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
@@ -0,0 +1,8 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class LOGSOptions:
6
+ showRequestUrl: bool = False
7
+ showRequestBody: bool = False
8
+ showServerInfo: bool = False
@@ -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)