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
LOGS/LOGS.py ADDED
@@ -0,0 +1,1436 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ A library to access the LOGS API via Python
4
+ """
5
+
6
+ import json
7
+ import os
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Any,
11
+ Dict,
12
+ List,
13
+ Optional,
14
+ Sequence,
15
+ Type,
16
+ TypeVar,
17
+ Union,
18
+ cast,
19
+ overload,
20
+ )
21
+ from uuid import UUID
22
+
23
+ from LOGS.Auxiliary import (
24
+ Constants,
25
+ EntityCreatingException,
26
+ EntityDeletingException,
27
+ EntityNotFoundException,
28
+ EntityUpdatingException,
29
+ LOGSException,
30
+ Tools,
31
+ )
32
+ from LOGS.Auxiliary.CustomEntityClassGenerator import CustomEntityClassGenerator
33
+ from LOGS.Entities.Attachment import Attachment
34
+ from LOGS.Entities.AttachmentRequestParameter import AttachmentRequestParameter
35
+ from LOGS.Entities.Attachments import Attachments
36
+ from LOGS.Entities.Bridge import Bridge
37
+ from LOGS.Entities.BridgeRequestParameter import BridgeRequestParameter
38
+ from LOGS.Entities.Bridges import Bridges
39
+ from LOGS.Entities.CustomField import CustomField
40
+ from LOGS.Entities.CustomFieldRequestParameter import CustomFieldRequestParameter
41
+ from LOGS.Entities.CustomFields import CustomFields
42
+ from LOGS.Entities.CustomType import CustomType
43
+ from LOGS.Entities.CustomTypeRequestParameter import CustomTypeRequestParameter
44
+ from LOGS.Entities.CustomTypes import CustomTypes
45
+ from LOGS.Entities.DataFormat import DataFormat
46
+ from LOGS.Entities.DataFormatInstrument import DataFormatInstrument
47
+ from LOGS.Entities.DataFormatInstrumentRequestParameter import (
48
+ DataFormatInstrumentRequestParameter,
49
+ )
50
+ from LOGS.Entities.DataFormatInstruments import DataFormatInstruments
51
+ from LOGS.Entities.DataFormatRequestParameter import DataFormatRequestParameter
52
+ from LOGS.Entities.DataFormats import DataFormats
53
+ from LOGS.Entities.Dataset import Dataset
54
+ from LOGS.Entities.DatasetCreator import DatasetCreator
55
+ from LOGS.Entities.DatasetMatching import DatasetMatching
56
+ from LOGS.Entities.DatasetMatchTypes import DatasetsUpdatableFiles
57
+ from LOGS.Entities.DatasetRequestParameter import DatasetRequestParameter
58
+ from LOGS.Entities.Datasets import Datasets
59
+ from LOGS.Entities.DataSource import DataSource
60
+ from LOGS.Entities.DataSourceRequestParameter import DataSourceRequestParameter
61
+ from LOGS.Entities.DataSources import DataSources
62
+ from LOGS.Entities.Entities import Entities
63
+ from LOGS.Entities.EntitiesRequestParameter import EntitiesRequestParameter
64
+ from LOGS.Entities.EntityOriginWriteModelWithId import EntityOriginWriteModelWithId
65
+ from LOGS.Entities.FileEntry import FileEntry
66
+ from LOGS.Entities.InventoryItem import InventoryItem
67
+ from LOGS.Entities.InventoryItemRequestParameter import InventoryItemRequestParameter
68
+ from LOGS.Entities.InventoryItems import InventoryItems
69
+ from LOGS.Entities.LabNotebook import LabNotebook
70
+ from LOGS.Entities.LabNotebookEntries import LabNotebookEntries
71
+ from LOGS.Entities.LabNotebookEntry import LabNotebookEntry
72
+ from LOGS.Entities.LabNotebookEntryRequestParameter import (
73
+ LabNotebookEntryRequestParameter,
74
+ )
75
+ from LOGS.Entities.LabNotebookExperiment import LabNotebookExperiment
76
+ from LOGS.Entities.LabNotebookExperimentRequestParameter import (
77
+ LabNotebookExperimentRequestParameter,
78
+ )
79
+ from LOGS.Entities.LabNotebookExperiments import LabNotebookExperiments
80
+ from LOGS.Entities.LabNotebookRequestParameter import LabNotebookRequestParameter
81
+ from LOGS.Entities.LabNotebooks import LabNotebooks
82
+ from LOGS.Entities.LabNotebookTemplate import LabNotebookTemplate
83
+ from LOGS.Entities.LabNotebookTemplateRequestParameter import (
84
+ LabNotebookTemplateRequestParameter,
85
+ )
86
+ from LOGS.Entities.LabNotebookTemplates import LabNotebookTemplates
87
+ from LOGS.Entities.Method import Method
88
+ from LOGS.Entities.MethodRequestParameter import MethodRequestParameter
89
+ from LOGS.Entities.Methods import Methods
90
+ from LOGS.Entities.Origin import Origin
91
+ from LOGS.Entities.OriginRequestParameter import OriginRequestParameter
92
+ from LOGS.Entities.Origins import Origins
93
+ from LOGS.Entities.Person import Person
94
+ from LOGS.Entities.PersonRequestParameter import PersonRequestParameter
95
+ from LOGS.Entities.Persons import Persons
96
+ from LOGS.Entities.Project import Project
97
+ from LOGS.Entities.ProjectRequestParameter import ProjectRequestParameter
98
+ from LOGS.Entities.Projects import Projects
99
+ from LOGS.Entities.Role import Role
100
+ from LOGS.Entities.RoleRequestParameter import RoleRequestParameter
101
+ from LOGS.Entities.Roles import Roles
102
+ from LOGS.Entities.Sample import Sample
103
+ from LOGS.Entities.SampleRequestParameter import SampleRequestParameter
104
+ from LOGS.Entities.Samples import Samples
105
+ from LOGS.Entities.SharedContent import SharedContent
106
+ from LOGS.Entities.SharedContentRequestParameter import SharedContentRequestParameter
107
+ from LOGS.Entities.SharedContents import SharedContents
108
+ from LOGS.Entities.Vendor import Vendor
109
+ from LOGS.Entities.VendorRequestParameter import VendorRequestParameter
110
+ from LOGS.Entities.Vendors import Vendors
111
+ from LOGS.Entity import Entity, EntityIterator
112
+ from LOGS.Entity.ConnectedEntity import ConnectedEntity
113
+ from LOGS.Interfaces.ISoftDeletable import ISoftDeletable
114
+ from LOGS.Interfaces.ITypedEntity import ITypedEntity
115
+ from LOGS.Interfaces.IUniqueEntity import IUniqueEntity
116
+ from LOGS.LOGSConnection import LOGSConnection
117
+ from LOGS.LOGSOptions import LOGSOptions
118
+ from LOGS.ServerMetaData import ServerMetaData
119
+
120
+ if TYPE_CHECKING:
121
+ from LOGS.Entities.DataFormatMinimal import DataFormatMinimal
122
+ from LOGS.Entities.ProjectMinimal import ProjectMinimal
123
+
124
+ _T = TypeVar("_T", bound=Union[Constants.ENTITIES, Entity])
125
+
126
+
127
+ class test:
128
+ pass
129
+
130
+
131
+ class LOGS:
132
+ """Python class to access the LOGS web API"""
133
+
134
+ _connection: LOGSConnection
135
+ _entities: Sequence[Type[Constants.ENTITIES]] = [
136
+ Bridge,
137
+ CustomField,
138
+ CustomType,
139
+ Dataset,
140
+ DataSource,
141
+ InventoryItem,
142
+ LabNotebook,
143
+ LabNotebookEntry,
144
+ LabNotebookExperiment,
145
+ Origin,
146
+ Person,
147
+ Project,
148
+ Sample,
149
+ DataFormat,
150
+ Role,
151
+ Vendor,
152
+ DataFormatInstrument,
153
+ Method,
154
+ Attachment,
155
+ ]
156
+ _entityByName = {t.__name__: t for t in _entities}
157
+ _defaultConfigFile: str = "logs.json"
158
+ _currentUser: Person
159
+ _cacheDir: Optional[str] = None
160
+
161
+ def __init__(
162
+ self,
163
+ url: Optional[str] = None,
164
+ apiKey: Optional[str] = None,
165
+ configFile: Optional[str] = None,
166
+ options: Optional[LOGSOptions] = None,
167
+ verify: bool = True,
168
+ ):
169
+ """Checks the connection to the server on creation
170
+
171
+ :param url: URL to specific LOGS group (e.g. https://mylogs/mygroup or https://mylogs:80/mygroup/api/0.1)
172
+ :param api_key: The API key that grants access to LOGS (you need to generate on in LOGS and copy it)
173
+ :param verbose: If set you see some information about the server connection. Defaults to False.
174
+
175
+ :raises: Exception: URL does not defined or is invalid.
176
+ :raises: Exception: The URL does not define a group.
177
+ :raises: Exception: Server cannot be reached.
178
+ """
179
+ self._options = Tools.checkAndConvert(
180
+ options, LOGSOptions, "options", initOnNone=True
181
+ )
182
+
183
+ _url = url
184
+ _apiKey = apiKey
185
+
186
+ if not configFile and os.path.isfile(self._defaultConfigFile):
187
+ configFile = self._defaultConfigFile
188
+
189
+ if configFile:
190
+ config = self._readConfig(configFile)
191
+ if "url" in config:
192
+ _url = config["url"]
193
+ if "apiKey" in config:
194
+ _apiKey = config["apiKey"]
195
+ if "proxyTargetUrl" in config:
196
+ self._options.proxyTargetUrl = config["proxyTargetUrl"]
197
+
198
+ if url:
199
+ _url = url
200
+
201
+ if apiKey:
202
+ _apiKey = apiKey
203
+
204
+ if not _url:
205
+ raise LOGSException("The url to the LOGS server must be provided.")
206
+
207
+ if not _apiKey:
208
+ raise LOGSException(
209
+ "The API key to access the server %a must be provided" % _url
210
+ )
211
+
212
+ self.promptPrefix = "LOGSAPI>"
213
+
214
+ self._connection = LOGSConnection(
215
+ url=_url, apiKey=_apiKey, options=self._options, verify=verify
216
+ )
217
+ self._currentUser = self._fetchCurrentUser()
218
+
219
+ def _fetchCurrentUser(self) -> Person:
220
+ data, responseError = self._connection.getEndpoint(["session"])
221
+ if responseError:
222
+ raise LOGSException(responseError=responseError)
223
+
224
+ if not isinstance(data, dict):
225
+ raise LOGSException(
226
+ "Unexpected response from session endpoint. Could not get current user."
227
+ )
228
+
229
+ person = None
230
+ if "person" in data:
231
+ personClass = self.getTypedEntityClass(None, Person)
232
+ person = personClass(data["person"], connection=self._connection)
233
+
234
+ if not person or not person.id:
235
+ raise LOGSException(
236
+ "Unexpected response from session endpoint. Could not get current user."
237
+ )
238
+
239
+ return person
240
+
241
+ def _readConfig(self, path: str) -> dict:
242
+ if not os.path.isfile(path):
243
+ raise LOGSException("Could not find config file %a" % path)
244
+
245
+ with open(path, "r") as f:
246
+ try:
247
+ config = json.load(f)
248
+ except json.JSONDecodeError as e:
249
+ raise LOGSException(
250
+ "Could not read config from file %a: %s" % (path, str(e))
251
+ )
252
+ return config
253
+
254
+ @classmethod
255
+ def getHumanReadableSize(cls, size: float, suffix="B"):
256
+ for unit in Constants.byteUnits:
257
+ if abs(size) < 1024.0:
258
+ return "%3.1f%s%s" % (size, unit, suffix)
259
+ size /= 1024.0
260
+ return "%.1f%s%s" % (size, "Yi", suffix)
261
+
262
+ def getDatasetDir(self, dataset: Dataset):
263
+ if self.cacheDir:
264
+ if not os.path.isdir(self.cacheDir):
265
+ raise LOGSException(
266
+ f"Specified cache directory '{self.cacheDir}' cannot be opened or is not a directory."
267
+ )
268
+
269
+ dataDir = os.path.join(self.cacheDir, dataset.cacheId)
270
+ if dataDir and not os.path.exists(dataDir):
271
+ os.mkdir(dataDir)
272
+ return dataDir
273
+ return None
274
+
275
+ def _fetchEntity(self, entityType: Type[_T], id: Union[int, str]) -> _T:
276
+ e = cast(Type[Entity], entityType)(id=id, connection=self._connection)
277
+ if isinstance(e, Dataset):
278
+ e.cacheDir = self.getDatasetDir(e)
279
+ e.fetch()
280
+ if isinstance(e, ITypedEntity):
281
+ e = e._getTypedInstance()
282
+
283
+ return cast(_T, e)
284
+
285
+ def _restoreEntitiesByTypeName(self, typeDict: Dict[str, Any]):
286
+ for typeName, entities in typeDict.items():
287
+ if not entities:
288
+ continue
289
+ t = self._entityByName.get(typeName, None)
290
+ if not t:
291
+ continue
292
+ self._restoreEntities(cast(Any, t), entities)
293
+
294
+ def _restoreEntities(
295
+ self, entityType: Type[Entity], entities: List[Constants.ENTITIES]
296
+ ):
297
+ if not entityType._endpoint:
298
+ raise NotImplementedError(
299
+ "Restoring of entity type %a is not implemented."
300
+ % (
301
+ type(self).__name__
302
+ if type(self).__name__ != Entity.__name__
303
+ else "unknown"
304
+ )
305
+ )
306
+
307
+ if len(entities) < 1:
308
+ return
309
+ elif len(entities) == 1:
310
+ if not entities[0].id:
311
+ raise EntityNotFoundException(entities[0])
312
+
313
+ data, responseError = self._connection.postEndpoint(
314
+ entityType._endpoint + ["restore", str(entities[0].id)],
315
+ data=entities[0].toDict(),
316
+ )
317
+ if (
318
+ isinstance(data, dict)
319
+ and "results" in data
320
+ and isinstance(data["results"], list)
321
+ and len(data["results"]) > 0
322
+ ):
323
+ entities[0].override(data["results"][0])
324
+ else:
325
+ data, responseError = self._connection.postEndpoint(
326
+ entityType._endpoint + ["bulk_restore"],
327
+ data=[e.id for e in entities],
328
+ )
329
+ if (
330
+ isinstance(data, dict)
331
+ and "results" in data
332
+ and isinstance(data["results"], list)
333
+ ):
334
+ for i, d in enumerate(data["results"]):
335
+ entities[i].override(d)
336
+
337
+ if responseError:
338
+ raise EntityUpdatingException(entity=entities, responseError=responseError)
339
+
340
+ def _updateEntitiesByTypeName(self, typeDict: Dict[str, Any]):
341
+ for typeName, entities in typeDict.items():
342
+ if not entities:
343
+ continue
344
+ t = self._entityByName.get(typeName, None)
345
+ if not t:
346
+ continue
347
+ self._updateEntities(cast(Any, t), entities)
348
+
349
+ def _updateEntities(
350
+ self, entityType: Type[Entity], entities: List[Constants.ENTITIES]
351
+ ):
352
+ if not entityType._endpoint:
353
+ raise NotImplementedError(
354
+ "Updating of entity type %a is not implemented."
355
+ % (
356
+ type(self).__name__
357
+ if type(self).__name__ != Entity.__name__
358
+ else "unknown"
359
+ )
360
+ )
361
+
362
+ if len(entities) < 1:
363
+ return
364
+ elif len(entities) == 1:
365
+ if not entities[0].id:
366
+ raise EntityNotFoundException(entities[0])
367
+
368
+ data, responseError = self._connection.putEndpoint(
369
+ entityType._endpoint + [str(entities[0].id)],
370
+ data=entities[0]._toDictWithSlack(),
371
+ )
372
+ if (
373
+ isinstance(data, dict)
374
+ and "results" in data
375
+ and isinstance(data["results"], list)
376
+ and len(data["results"]) > 0
377
+ ):
378
+ entities[0].override(data["results"][0])
379
+ else:
380
+ data, responseError = self._connection.postEndpoint(
381
+ entityType._endpoint + ["bulk_edit"],
382
+ data=[e._toDictWithSlack() for e in entities],
383
+ )
384
+ if (
385
+ isinstance(data, dict)
386
+ and "results" in data
387
+ and isinstance(data["results"], list)
388
+ ):
389
+ for i, d in enumerate(data["results"]):
390
+ entities[i].override(d)
391
+
392
+ if responseError:
393
+ raise EntityUpdatingException(entity=entities, responseError=responseError)
394
+
395
+ def _createDataset(self, dataset: Union[Dataset, Attachment]):
396
+ data = DatasetCreator(connection=self._connection, dataset=dataset).create()
397
+ # TODO: The following is not optimal. DatasetCreator should directly set the dataset properties (add dataset write model to multipart)
398
+ if (
399
+ "results" in data
400
+ and isinstance(data["results"], list)
401
+ and len(data["results"]) == 1
402
+ ):
403
+ dataset._connection = self._connection
404
+ dataset.override(data["results"][0])
405
+
406
+ def _createEntitiesByTypeName(self, typeDict: Dict[str, Entity]):
407
+ for typeName, entities in typeDict.items():
408
+ if not entities:
409
+ continue
410
+ t = self._entityByName.get(typeName, None)
411
+
412
+ if not t:
413
+ continue
414
+
415
+ self._createEntities(cast(Any, t), cast(Any, entities))
416
+
417
+ def _addOriginToEntity(
418
+ self, endpoint: List[str], entity: Optional[EntityOriginWriteModelWithId]
419
+ ):
420
+ return self._addOriginToEntities(endpoint, [entity])
421
+
422
+ def _addOriginToEntities(
423
+ self,
424
+ endpoint: List[str],
425
+ entities: List[Optional[EntityOriginWriteModelWithId]],
426
+ ):
427
+ entities = [e for e in entities if e]
428
+ if len(entities) == 1:
429
+ data, responseError = self._connection.postEndpoint(
430
+ endpoint + ["origin"], data=[e.toDict() for e in entities if e]
431
+ )
432
+ if responseError:
433
+ indent = Constants.exceptionIndentation
434
+ message = ""
435
+ if isinstance(data, list):
436
+ message = "%sCould not add origin to %s %a" % (
437
+ (
438
+ "\n" + indent
439
+ if responseError and len(responseError.errorStringList) > 1
440
+ else ""
441
+ ),
442
+ Tools.plural("entity", entities),
443
+ Tools.eclipsesJoin(", ", [e.id for e in entities if e]),
444
+ )
445
+
446
+ # indent *= 2
447
+ if responseError:
448
+ message += ": " + responseError.errorString(indent)
449
+
450
+ raise LOGSException(message=message, responseError=responseError)
451
+
452
+ # for o in entities:
453
+ # print(">>>>>", o.toDict())
454
+ # data, errors = self._connection.postEndpoint(
455
+ # entityType._endpoint + ["bulk_create"],
456
+ # data=[e.toDict() for e in entities],
457
+ # )
458
+
459
+ def _createEntityOriginWriteModel(
460
+ self, entity: Union[Entity, IUniqueEntity]
461
+ ) -> Optional[EntityOriginWriteModelWithId]:
462
+ if isinstance(entity, IUniqueEntity) and (
463
+ entity._foreignUid or entity._foreignOrigin
464
+ ):
465
+ if isinstance(entity, Entity):
466
+ model = EntityOriginWriteModelWithId(
467
+ id=entity.id, uid=entity._foreignUid, origin=entity._foreignOrigin
468
+ )
469
+ if model.uid:
470
+ setattr(entity, "uid", model.uid)
471
+ if model.uid:
472
+ setattr(entity, "origin", model.origin)
473
+ return model
474
+
475
+ return None
476
+
477
+ def _createEntities(self, entityType: Type[Entity], entities: List[Entity]):
478
+ if not entityType._endpoint:
479
+ raise NotImplementedError(
480
+ "Creating of entity type %a is not implemented."
481
+ % (
482
+ entityType.__name__
483
+ if entityType.__name__ != Entity.__name__
484
+ else "unknown"
485
+ )
486
+ )
487
+
488
+ datasets = [e for e in entities if isinstance(e, Dataset)]
489
+ attachments = [e for e in entities if isinstance(e, Attachment)]
490
+ entities = [e for e in entities if not isinstance(e, (Dataset, Attachment))]
491
+
492
+ if len(datasets) > 0:
493
+ for dataset in datasets:
494
+ self._createDataset(dataset)
495
+ self._addOriginToEntity(
496
+ entityType._endpoint, self._createEntityOriginWriteModel(dataset)
497
+ )
498
+
499
+ if len(attachments) > 0:
500
+ for attachment in attachments:
501
+ self._createDataset(attachment)
502
+ self._addOriginToEntity(
503
+ entityType._endpoint, self._createEntityOriginWriteModel(attachment)
504
+ )
505
+
506
+ responseError = None
507
+ if len(entities) == 1:
508
+ data, responseError = self._connection.postEndpoint(
509
+ entityType._endpoint, data=entities[0].toDict()
510
+ )
511
+ if responseError:
512
+ raise EntityCreatingException(
513
+ entity=entities, responseError=responseError
514
+ )
515
+
516
+ entities[0]._connection = self._connection
517
+ entities[0].override(data)
518
+ self._addOriginToEntity(
519
+ entityType._endpoint, self._createEntityOriginWriteModel(entities[0])
520
+ )
521
+
522
+ elif len(entities) > 1:
523
+ data, responseError = self._connection.postEndpoint(
524
+ entityType._endpoint + ["bulk_create"],
525
+ data=[e.toDict() for e in entities],
526
+ )
527
+ if responseError:
528
+ raise EntityCreatingException(
529
+ entity=entities, responseError=responseError
530
+ )
531
+
532
+ if (
533
+ isinstance(data, dict)
534
+ and "results" in data
535
+ and isinstance(data["results"], list)
536
+ ):
537
+ for i, d in enumerate(data["results"]):
538
+ entities[i]._connection = self._connection
539
+ entities[i].override(d)
540
+ self._addOriginToEntities(
541
+ entityType._endpoint,
542
+ [self._createEntityOriginWriteModel(e) for e in entities],
543
+ )
544
+
545
+ def _deleteEntitiesByTypeName(
546
+ self,
547
+ typeDict: Dict[str, List[Union[Constants.ID_TYPE, None]]],
548
+ permanently: bool = False,
549
+ ):
550
+ for typeName, entities in typeDict.items():
551
+ if not entities:
552
+ continue
553
+ t = self._entityByName.get(typeName, None)
554
+ if not t:
555
+ continue
556
+ self._deleteEntities(cast(Any, t), [e for e in entities if e], permanently)
557
+
558
+ def _deleteEntities(
559
+ self,
560
+ entityType: Type[Entity],
561
+ entityIds: List[Constants.ID_TYPE],
562
+ permanently: bool = False,
563
+ ):
564
+ if not entityType._endpoint:
565
+ raise NotImplementedError(
566
+ "Deleting of entity type %a is not implemented."
567
+ % (
568
+ type(self).__name__
569
+ if type(self).__name__ != Entity.__name__
570
+ else "unknown"
571
+ )
572
+ )
573
+
574
+ if len(entityIds) < 1:
575
+ return
576
+ elif len(entityIds) == 1:
577
+ _, responseError = self._connection.deleteEndpoint(
578
+ entityType._endpoint + [str(entityIds[0])],
579
+ parameters={"deletePermanently": permanently} if permanently else {},
580
+ )
581
+ else:
582
+ _, responseError = self._connection.postEndpoint(
583
+ entityType._endpoint + ["bulk_delete"],
584
+ data=[id for id in entityIds],
585
+ parameters={"deletePermanently": permanently} if permanently else {},
586
+ )
587
+
588
+ if responseError:
589
+ raise EntityDeletingException(
590
+ entityIds=entityIds, responseError=responseError
591
+ )
592
+
593
+ @classmethod
594
+ def _collectTypes(cls, entities: Sequence) -> Dict[str, Any]:
595
+ result: Dict[str, Any] = {k: [] for k in cls._entityByName.keys()}
596
+ result["unknown"] = []
597
+
598
+ for entity in entities:
599
+ unknown = True
600
+
601
+ for k, v in cls._entityByName.items():
602
+ if isinstance(entity, v):
603
+ result[k].append(entity)
604
+ unknown = False
605
+ break
606
+
607
+ if unknown:
608
+ result["unknown"].append(entity)
609
+ return result
610
+
611
+ def printServerStatus(self):
612
+ self._connection.printServerStatus()
613
+
614
+ @overload
615
+ def restore(self, entities: Constants.ENTITIES): ...
616
+
617
+ @overload
618
+ def restore(self, entities: List[Constants.ENTITIES]): ...
619
+
620
+ # Implementation of overload
621
+ def restore(self, entities: Any):
622
+ def decorator(entities: Any):
623
+ types = self._collectTypes(entities)
624
+ if len(types["unknown"]) > 0:
625
+ raise EntityUpdatingException(
626
+ types["unknown"][0],
627
+ errors=[
628
+ "Entity type %a not valid for this action."
629
+ % type(types["unknown"][0]).__name__
630
+ ],
631
+ )
632
+
633
+ self._restoreEntitiesByTypeName(types)
634
+
635
+ if not isinstance(entities, list):
636
+ entities = [entities]
637
+ return decorator(entities)
638
+
639
+ @overload
640
+ def update(self, entities: Constants.ENTITIES): ...
641
+
642
+ @overload
643
+ def update(self, entities: List[Constants.ENTITIES]): ...
644
+
645
+ # Implementation of overload
646
+ def update(self, entities: Any):
647
+ def decorator(entities: Any):
648
+ types = self._collectTypes(entities)
649
+ if len(types["unknown"]) > 0:
650
+ raise EntityUpdatingException(
651
+ types["unknown"][0],
652
+ errors=[
653
+ "Entity type %a not valid for this action."
654
+ % type(types["unknown"][0]).__name__
655
+ ],
656
+ )
657
+
658
+ self._updateEntitiesByTypeName(types)
659
+
660
+ if not isinstance(entities, list):
661
+ entities = [entities]
662
+ return decorator(entities)
663
+
664
+ @overload
665
+ def create(self, entities: Constants.ENTITIES): ...
666
+
667
+ @overload
668
+ def create(self, entities: Sequence[Constants.ENTITIES]): ...
669
+
670
+ # Implementation of overload
671
+ def create(self, entities: Any):
672
+ def decorator(entities: Sequence[Entity]):
673
+ types = self._collectTypes(entities)
674
+ if len(types["unknown"]) > 0:
675
+ raise EntityCreatingException(
676
+ types["unknown"][0],
677
+ errors=[
678
+ "Entity type %a not valid for this action"
679
+ % type(types["unknown"][0]).__name__
680
+ ],
681
+ )
682
+
683
+ self._createEntitiesByTypeName(types)
684
+
685
+ if not isinstance(entities, list):
686
+ entities = [entities]
687
+ decorator(entities)
688
+
689
+ @overload
690
+ def delete(self, entities: Constants.ENTITIES, permanently=False): ...
691
+
692
+ @overload
693
+ def delete(self, entities: Sequence[Constants.ENTITIES], permanently=False): ...
694
+
695
+ # Implementation of overload
696
+ def delete(self, entities: Any = None, permanently=False):
697
+ def decorator(entities: Any):
698
+ types: Dict[str, List[Union[Constants.ID_TYPE, None]]] = self._collectTypes(
699
+ entities
700
+ )
701
+ typesIds = {
702
+ typeName: cast(List, [cast(Entity, e).id for e in entities if e])
703
+ for typeName, entities in types.items()
704
+ }
705
+ if len(types["unknown"]) > 0:
706
+ raise EntityDeletingException(
707
+ types["unknown"][0],
708
+ errors=[
709
+ "Entity type %a not valid for this action"
710
+ % type(types["unknown"][0]).__name__
711
+ ],
712
+ )
713
+
714
+ self._deleteEntitiesByTypeName(typesIds, permanently=permanently)
715
+
716
+ for entityList in types.values():
717
+ for entity in entityList:
718
+ if permanently and isinstance(entity, ConnectedEntity):
719
+ entity._connection = None
720
+ if isinstance(entity, ISoftDeletable):
721
+ entity.isDeleted = True
722
+
723
+ if isinstance(entities, EntityIterator):
724
+ raise LOGSException(
725
+ "An %a cannot be used for delete. Please convert it to a list first."
726
+ % EntityIterator.__name__
727
+ )
728
+ elif not isinstance(entities, list):
729
+ entities = [entities]
730
+ return decorator(entities)
731
+
732
+ @overload
733
+ def deleteById(
734
+ self, entityType: Type[Constants.ENTITIES], ids: int, permanently: bool = False
735
+ ): ...
736
+
737
+ @overload
738
+ def deleteById(
739
+ self, entityType: Type[Constants.ENTITIES], ids: str, permanently: bool = False
740
+ ): ...
741
+
742
+ @overload
743
+ def deleteById(
744
+ self,
745
+ entityType: Type[Constants.ENTITIES],
746
+ ids: Constants.ID_TYPE,
747
+ permanently: bool = False,
748
+ ): ...
749
+
750
+ @overload
751
+ def deleteById(
752
+ self,
753
+ entityType: Type[Constants.ENTITIES],
754
+ ids: List[int],
755
+ permanently: bool = False,
756
+ ): ...
757
+
758
+ @overload
759
+ def deleteById(
760
+ self,
761
+ entityType: Type[Constants.ENTITIES],
762
+ ids: List[str],
763
+ permanently: bool = False,
764
+ ): ...
765
+
766
+ @overload
767
+ def deleteById(
768
+ self,
769
+ entityType: Type[Constants.ENTITIES],
770
+ ids: List[Constants.ID_TYPE],
771
+ permanently: bool = False,
772
+ ): ...
773
+
774
+ # Implementation of overload
775
+ def deleteById(self, entityType=None, ids: Any = None, permanently: bool = False):
776
+ if not entityType:
777
+ raise Exception("Parameter 'entityType' must be provided.")
778
+
779
+ if not issubclass(entityType, Entity):
780
+ raise Exception(
781
+ f"Parameter 'entityType' must be a subclass of {Entity.__name__}."
782
+ )
783
+
784
+ def decorator(entityType: Any):
785
+ self._deleteEntities(entityType, ids, permanently=permanently)
786
+
787
+ if ids and not isinstance(ids, list):
788
+ ids = [ids]
789
+ return decorator(entityType)
790
+
791
+ def getTypedEntityClass(
792
+ self, customTypeOrId: Optional[Union[CustomType, int]], entityType: Type[_T]
793
+ ) -> Type[_T]:
794
+ if not issubclass(entityType, Entity):
795
+ raise Exception(
796
+ f"Type '{entityType.__name__}' is not an LOGS entity. (Got '{type(entityType).__name__}')"
797
+ )
798
+
799
+ if customTypeOrId is None:
800
+ return CustomEntityClassGenerator.generate(
801
+ None,
802
+ connection=self._connection,
803
+ limitToEntityType=entityType,
804
+ )
805
+ elif not issubclass(entityType, ITypedEntity):
806
+ raise Exception(
807
+ f"Entity type '{entityType.__name__}' is not a typed entity and cannot be used with custom types."
808
+ )
809
+
810
+ if isinstance(customTypeOrId, int):
811
+ customType = CustomEntityClassGenerator.fetchCustomType(
812
+ customTypeOrId, self._connection
813
+ )
814
+ elif isinstance(customTypeOrId, CustomType):
815
+ customType = customTypeOrId
816
+ else:
817
+ raise Exception(
818
+ f"Parameter 'customTypeOrId' must be of type {CustomType.__name__} or int. (Got '{type(customTypeOrId).__name__}')"
819
+ )
820
+
821
+ return CustomEntityClassGenerator.generate(
822
+ customType=customType,
823
+ connection=self._connection,
824
+ limitToEntityType=entityType,
825
+ )
826
+
827
+ def newSample(
828
+ self,
829
+ entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None,
830
+ ref=None,
831
+ name: str = "",
832
+ projects: Optional[List[Union["ProjectMinimal", "Project"]]] = None,
833
+ ) -> Sample:
834
+ return self.getTypedEntityClass(entityOrCustomTypeOrId, Sample)(
835
+ ref=ref, connection=self._connection, name=name, projects=projects
836
+ )
837
+
838
+ def sample(self, id: int) -> Sample:
839
+ return self._fetchEntity(Sample, id)
840
+
841
+ def samples(self, parameter: Optional[SampleRequestParameter] = None) -> Samples:
842
+ if parameter and not isinstance(parameter, SampleRequestParameter):
843
+ raise LOGSException(
844
+ "Parameter for %s.%s must be of type %a. (Got %a)"
845
+ % (
846
+ type(self).__name__,
847
+ self.samples.__name__,
848
+ SampleRequestParameter.__name__,
849
+ type(parameter).__name__,
850
+ )
851
+ )
852
+ return Samples(connection=self._connection, parameters=parameter)
853
+
854
+ def newProject(
855
+ self,
856
+ entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None,
857
+ ref=None,
858
+ name: str = "",
859
+ ) -> Project:
860
+ return self.getTypedEntityClass(entityOrCustomTypeOrId, Project)(
861
+ ref=ref, connection=self._connection, name=name
862
+ )
863
+
864
+ def project(self, id: int) -> Project:
865
+ return self._fetchEntity(Project, id)
866
+
867
+ def projects(self, parameter: Optional[ProjectRequestParameter] = None) -> Projects:
868
+ if parameter and not isinstance(parameter, ProjectRequestParameter):
869
+ raise LOGSException(
870
+ "Parameter for %s.%s must be of type %a. (Got %a)"
871
+ % (
872
+ type(self).__name__,
873
+ self.projects.__name__,
874
+ ProjectRequestParameter.__name__,
875
+ type(parameter).__name__,
876
+ )
877
+ )
878
+ return Projects(connection=self._connection, parameters=parameter)
879
+
880
+ def newDataset(
881
+ self,
882
+ entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None,
883
+ ref=None,
884
+ files: Optional[Sequence[Constants.FILE_TYPE]] = None,
885
+ formatOrFormatId: Optional[Union[str, "DataFormatMinimal"]] = None,
886
+ pathPrefixToStrip: Optional[str] = None,
887
+ pathPrefixToAdd: Optional[str] = None,
888
+ ) -> Dataset:
889
+ return self.getTypedEntityClass(entityOrCustomTypeOrId, Dataset)(
890
+ ref=ref,
891
+ connection=self._connection,
892
+ files=files,
893
+ formatOrFormatId=formatOrFormatId,
894
+ pathPrefixToStrip=pathPrefixToStrip,
895
+ pathPrefixToAdd=pathPrefixToAdd,
896
+ )
897
+
898
+ def dataset(self, id: int) -> Dataset:
899
+ return self._fetchEntity(Dataset, id)
900
+
901
+ def datasets(self, parameter: Optional[DatasetRequestParameter] = None) -> Datasets:
902
+ if parameter and not isinstance(parameter, DatasetRequestParameter):
903
+ raise LOGSException(
904
+ "Parameter for %s.%s must be of type %a. (Got %a)"
905
+ % (
906
+ type(self).__name__,
907
+ self.datasets.__name__,
908
+ DatasetRequestParameter.__name__,
909
+ type(parameter).__name__,
910
+ )
911
+ )
912
+ return Datasets(connection=self._connection, parameters=parameter)
913
+
914
+ def newAttachment(
915
+ self,
916
+ ref=None,
917
+ files: Optional[Sequence[Constants.FILE_TYPE]] = None,
918
+ pathPrefixToStrip: Optional[str] = None,
919
+ pathPrefixToAdd: Optional[str] = None,
920
+ ) -> Attachment:
921
+ return self.getTypedEntityClass(None, Attachment)(
922
+ ref=ref,
923
+ connection=self._connection,
924
+ files=files,
925
+ pathPrefixToStrip=pathPrefixToStrip,
926
+ pathPrefixToAdd=pathPrefixToAdd,
927
+ )
928
+
929
+ def attachment(self, id: int) -> Attachment:
930
+ return self._fetchEntity(Attachment, id)
931
+
932
+ def attachments(
933
+ self, parameter: Optional[AttachmentRequestParameter] = None
934
+ ) -> Attachments:
935
+ if parameter and not isinstance(parameter, AttachmentRequestParameter):
936
+ raise LOGSException(
937
+ "Parameter for %s.%s must be of type %a. (Got %a)"
938
+ % (
939
+ type(self).__name__,
940
+ self.attachments.__name__,
941
+ AttachmentRequestParameter.__name__,
942
+ type(parameter).__name__,
943
+ )
944
+ )
945
+ return Attachments(connection=self._connection, parameters=parameter)
946
+
947
+ def newPerson(
948
+ self, entityOrCustomTypeOrId: Optional[Union[CustomType, int]] = None, ref=None
949
+ ) -> Person:
950
+ return self.getTypedEntityClass(entityOrCustomTypeOrId, Person)(
951
+ ref=ref, connection=self._connection
952
+ )
953
+
954
+ def person(self, id: int) -> Person:
955
+ return self._fetchEntity(Person, id)
956
+
957
+ def persons(self, parameter: Optional[PersonRequestParameter] = None) -> Persons:
958
+ if parameter and not isinstance(parameter, PersonRequestParameter):
959
+ raise LOGSException(
960
+ "Parameter for %s.%s must be of type %a. (Got %a)"
961
+ % (
962
+ type(self).__name__,
963
+ self.persons.__name__,
964
+ PersonRequestParameter.__name__,
965
+ type(parameter).__name__,
966
+ )
967
+ )
968
+ return Persons(connection=self._connection, parameters=parameter)
969
+
970
+ def newOrigin(
971
+ self,
972
+ ref=None,
973
+ name: Optional[str] = None,
974
+ url: Optional[str] = None,
975
+ uid: Optional[UUID] = None,
976
+ ) -> Origin:
977
+ return self.getTypedEntityClass(None, Origin)(
978
+ ref=ref, connection=self._connection, name=name, url=url, uid=uid
979
+ )
980
+
981
+ def origin(self, id: int) -> Origin:
982
+ return self._fetchEntity(Origin, id)
983
+
984
+ def origins(self, parameter: Optional[OriginRequestParameter] = None) -> Origins:
985
+ if parameter and not isinstance(parameter, OriginRequestParameter):
986
+ raise LOGSException(
987
+ "Parameter for %s.%s must be of type %a. (Got %a)"
988
+ % (
989
+ type(self).__name__,
990
+ self.origins.__name__,
991
+ OriginRequestParameter.__name__,
992
+ type(parameter).__name__,
993
+ )
994
+ )
995
+ return Origins(connection=self._connection, parameters=parameter)
996
+
997
+ def newDataFormat(self, ref=None) -> DataFormat:
998
+ return self.getTypedEntityClass(None, DataFormat)(
999
+ ref=ref, connection=self._connection
1000
+ )
1001
+
1002
+ def dataFormat(self, id: str) -> DataFormat:
1003
+ return self._fetchEntity(DataFormat, id)
1004
+
1005
+ def dataFormats(
1006
+ self, parameter: Optional[DataFormatRequestParameter] = None
1007
+ ) -> DataFormats:
1008
+ if parameter and not isinstance(parameter, DataFormatRequestParameter):
1009
+ raise LOGSException(
1010
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1011
+ % (
1012
+ type(self).__name__,
1013
+ self.dataFormats.__name__,
1014
+ DataFormatRequestParameter.__name__,
1015
+ type(parameter).__name__,
1016
+ )
1017
+ )
1018
+ return DataFormats(connection=self._connection, parameters=parameter)
1019
+
1020
+ def newRole(self, ref=None) -> Role:
1021
+ return self.getTypedEntityClass(None, Role)(
1022
+ ref=ref, connection=self._connection
1023
+ )
1024
+
1025
+ def role(self, id: int) -> Role:
1026
+ return self._fetchEntity(Role, id)
1027
+
1028
+ def roles(self, parameter: Optional[RoleRequestParameter] = None) -> Roles:
1029
+ if parameter and not isinstance(parameter, RoleRequestParameter):
1030
+ raise LOGSException(
1031
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1032
+ % (
1033
+ type(self).__name__,
1034
+ self.roles.__name__,
1035
+ RoleRequestParameter.__name__,
1036
+ type(parameter).__name__,
1037
+ )
1038
+ )
1039
+ return Roles(connection=self._connection, parameters=parameter)
1040
+
1041
+ def newBridge(self, ref=None) -> Bridge:
1042
+ return self.getTypedEntityClass(None, Bridge)(
1043
+ ref=ref, connection=self._connection
1044
+ )
1045
+
1046
+ def bridge(self, id: int) -> Bridge:
1047
+ return self._fetchEntity(Bridge, id)
1048
+
1049
+ def bridges(self, parameter: Optional[BridgeRequestParameter] = None) -> Bridges:
1050
+ if parameter and not isinstance(parameter, BridgeRequestParameter):
1051
+ raise LOGSException(
1052
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1053
+ % (
1054
+ type(self).__name__,
1055
+ self.bridges.__name__,
1056
+ BridgeRequestParameter.__name__,
1057
+ type(parameter).__name__,
1058
+ )
1059
+ )
1060
+ return Bridges(connection=self._connection, parameters=parameter)
1061
+
1062
+ def newDataSource(self, ref=None) -> DataSource:
1063
+ return self.getTypedEntityClass(None, DataSource)(
1064
+ ref=ref, connection=self._connection
1065
+ )
1066
+
1067
+ def dataSource(self, id: int) -> DataSource:
1068
+ return self._fetchEntity(DataSource, id)
1069
+
1070
+ def dataSources(
1071
+ self, parameter: Optional[DataSourceRequestParameter] = None
1072
+ ) -> DataSources:
1073
+ if parameter and not isinstance(parameter, DataSourceRequestParameter):
1074
+ raise LOGSException(
1075
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1076
+ % (
1077
+ type(self).__name__,
1078
+ self.dataSources.__name__,
1079
+ DataSourceRequestParameter.__name__,
1080
+ type(parameter).__name__,
1081
+ )
1082
+ )
1083
+ return DataSources(connection=self._connection, parameters=parameter)
1084
+
1085
+ def newLabNotebook(self, ref=None) -> LabNotebook:
1086
+ return self.getTypedEntityClass(None, LabNotebook)(
1087
+ ref=ref, connection=self._connection
1088
+ )
1089
+
1090
+ def labNotebook(self, id: int) -> LabNotebook:
1091
+ return self._fetchEntity(LabNotebook, id)
1092
+
1093
+ def labNotebooks(
1094
+ self, parameter: Optional[LabNotebookRequestParameter] = None
1095
+ ) -> LabNotebooks:
1096
+ if parameter and not isinstance(parameter, LabNotebookRequestParameter):
1097
+ raise LOGSException(
1098
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1099
+ % (
1100
+ type(self).__name__,
1101
+ self.labNotebooks.__name__,
1102
+ LabNotebookRequestParameter.__name__,
1103
+ type(parameter).__name__,
1104
+ )
1105
+ )
1106
+ return LabNotebooks(connection=self._connection, parameters=parameter)
1107
+
1108
+ def newLabNotebookTemplate(self, ref=None) -> LabNotebookTemplate:
1109
+ return self.getTypedEntityClass(None, LabNotebookTemplate)(
1110
+ ref=ref, connection=self._connection
1111
+ )
1112
+
1113
+ def labNotebookTemplate(self, id: int) -> LabNotebookTemplate:
1114
+ return self._fetchEntity(LabNotebookTemplate, id)
1115
+
1116
+ def labNotebookTemplates(
1117
+ self, parameter: Optional[LabNotebookTemplateRequestParameter] = None
1118
+ ) -> LabNotebookTemplates:
1119
+ if parameter and not isinstance(parameter, LabNotebookTemplateRequestParameter):
1120
+ raise LOGSException(
1121
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1122
+ % (
1123
+ type(self).__name__,
1124
+ self.labNotebookTemplates.__name__,
1125
+ LabNotebookTemplateRequestParameter.__name__,
1126
+ type(parameter).__name__,
1127
+ )
1128
+ )
1129
+ return LabNotebookTemplates(connection=self._connection, parameters=parameter)
1130
+
1131
+ def newLabNotebookExperiment(self, ref=None) -> LabNotebookExperiment:
1132
+ return self.getTypedEntityClass(None, LabNotebookExperiment)(
1133
+ ref=ref, connection=self._connection
1134
+ )
1135
+
1136
+ def labNotebookExperiment(self, id: int) -> LabNotebookExperiment:
1137
+ return self._fetchEntity(LabNotebookExperiment, id)
1138
+
1139
+ def labNotebookExperiments(
1140
+ self, parameter: Optional[LabNotebookExperimentRequestParameter] = None
1141
+ ) -> LabNotebookExperiments:
1142
+ if parameter and not isinstance(
1143
+ parameter, LabNotebookExperimentRequestParameter
1144
+ ):
1145
+ raise LOGSException(
1146
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1147
+ % (
1148
+ type(self).__name__,
1149
+ self.labNotebookExperiments.__name__,
1150
+ LabNotebookExperimentRequestParameter.__name__,
1151
+ type(parameter).__name__,
1152
+ )
1153
+ )
1154
+ return LabNotebookExperiments(connection=self._connection, parameters=parameter)
1155
+
1156
+ def newLabNotebookEntry(self, ref=None) -> LabNotebookEntry:
1157
+ return self.getTypedEntityClass(None, LabNotebookEntry)(
1158
+ ref=ref, connection=self._connection
1159
+ )
1160
+
1161
+ def labNotebookEntry(self, id: int) -> LabNotebookEntry:
1162
+ return self._fetchEntity(LabNotebookEntry, id)
1163
+
1164
+ def labNotebookEntries(
1165
+ self, parameter: Optional[LabNotebookEntryRequestParameter] = None
1166
+ ) -> LabNotebookEntries:
1167
+ if parameter and not isinstance(parameter, LabNotebookEntryRequestParameter):
1168
+ raise LOGSException(
1169
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1170
+ % (
1171
+ type(self).__name__,
1172
+ self.labNotebookEntries.__name__,
1173
+ LabNotebookEntryRequestParameter.__name__,
1174
+ type(parameter).__name__,
1175
+ )
1176
+ )
1177
+ return LabNotebookEntries(connection=self._connection, parameters=parameter)
1178
+
1179
+ def newVendor(self, ref=None) -> Vendor:
1180
+ return self.getTypedEntityClass(None, Vendor)(
1181
+ ref=ref, connection=self._connection
1182
+ )
1183
+
1184
+ def vendor(self, id: int) -> Vendor:
1185
+ return self._fetchEntity(Vendor, id)
1186
+
1187
+ def vendors(self, parameter: Optional[VendorRequestParameter] = None) -> Vendors:
1188
+ if parameter and not isinstance(parameter, VendorRequestParameter):
1189
+ raise LOGSException(
1190
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1191
+ % (
1192
+ type(self).__name__,
1193
+ self.vendors.__name__,
1194
+ VendorRequestParameter.__name__,
1195
+ type(parameter).__name__,
1196
+ )
1197
+ )
1198
+ return Vendors(connection=self._connection, parameters=parameter)
1199
+
1200
+ def newMethod(self, ref=None) -> Method:
1201
+ return self.getTypedEntityClass(None, Method)(
1202
+ ref=ref, connection=self._connection
1203
+ )
1204
+
1205
+ def method(self, id: int) -> Method:
1206
+ return self._fetchEntity(Method, id)
1207
+
1208
+ def methods(self, parameter: Optional[MethodRequestParameter] = None) -> Methods:
1209
+ if parameter and not isinstance(parameter, MethodRequestParameter):
1210
+ raise LOGSException(
1211
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1212
+ % (
1213
+ type(self).__name__,
1214
+ self.methods.__name__,
1215
+ MethodRequestParameter.__name__,
1216
+ type(parameter).__name__,
1217
+ )
1218
+ )
1219
+ return Methods(connection=self._connection, parameters=parameter)
1220
+
1221
+ def newDataFormatInstrument(self, ref=None) -> DataFormatInstrument:
1222
+ return self.getTypedEntityClass(None, DataFormatInstrument)(
1223
+ ref=ref, connection=self._connection
1224
+ )
1225
+
1226
+ def dataFormatInstrument(self, id: int) -> DataFormatInstrument:
1227
+ return self._fetchEntity(DataFormatInstrument, id)
1228
+
1229
+ def dataFormatInstruments(
1230
+ self, parameter: Optional[DataFormatInstrumentRequestParameter] = None
1231
+ ) -> DataFormatInstruments:
1232
+ if parameter and not isinstance(
1233
+ parameter, DataFormatInstrumentRequestParameter
1234
+ ):
1235
+ raise LOGSException(
1236
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1237
+ % (
1238
+ type(self).__name__,
1239
+ self.dataFormatInstruments.__name__,
1240
+ DataFormatInstrumentRequestParameter.__name__,
1241
+ type(parameter).__name__,
1242
+ )
1243
+ )
1244
+ return DataFormatInstruments(connection=self._connection, parameters=parameter)
1245
+
1246
+ def newCustomField(self, ref=None) -> CustomField:
1247
+ return self.getTypedEntityClass(None, CustomField)(
1248
+ ref=ref, connection=self._connection
1249
+ )
1250
+
1251
+ def customField(self, id: int) -> CustomField:
1252
+ return self._fetchEntity(CustomField, id)
1253
+
1254
+ def customFields(
1255
+ self, parameter: Optional[CustomFieldRequestParameter] = None
1256
+ ) -> CustomFields:
1257
+ if parameter and not isinstance(parameter, CustomFieldRequestParameter):
1258
+ raise LOGSException(
1259
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1260
+ % (
1261
+ type(self).__name__,
1262
+ self.customFields.__name__,
1263
+ CustomFieldRequestParameter.__name__,
1264
+ type(parameter).__name__,
1265
+ )
1266
+ )
1267
+ return CustomFields(connection=self._connection, parameters=parameter)
1268
+
1269
+ def newCustomType(self, ref=None) -> CustomType:
1270
+ return self.getTypedEntityClass(None, CustomType)(
1271
+ ref=ref, connection=self._connection
1272
+ )
1273
+
1274
+ def customType(self, id: int) -> CustomType:
1275
+ return self._fetchEntity(CustomType, id)
1276
+
1277
+ def customTypes(
1278
+ self, parameter: Optional[CustomTypeRequestParameter] = None
1279
+ ) -> CustomTypes:
1280
+ if parameter and not isinstance(parameter, CustomTypeRequestParameter):
1281
+ raise LOGSException(
1282
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1283
+ % (
1284
+ type(self).__name__,
1285
+ self.customTypes.__name__,
1286
+ CustomTypeRequestParameter.__name__,
1287
+ type(parameter).__name__,
1288
+ )
1289
+ )
1290
+ return CustomTypes(connection=self._connection, parameters=parameter)
1291
+
1292
+ def newInventoryItem(
1293
+ self, customTypeOrId: Optional[Union[CustomType, int]] = None, ref=None
1294
+ ) -> InventoryItem:
1295
+ return self.getTypedEntityClass(customTypeOrId, InventoryItem)(
1296
+ ref=ref, connection=self._connection
1297
+ )
1298
+
1299
+ def inventoryItem(self, id: int) -> InventoryItem:
1300
+ return self._fetchEntity(InventoryItem, id)
1301
+
1302
+ def inventoryItems(
1303
+ self, parameter: Optional[InventoryItemRequestParameter] = None
1304
+ ) -> InventoryItems:
1305
+ if parameter and not isinstance(parameter, InventoryItemRequestParameter):
1306
+ raise LOGSException(
1307
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1308
+ % (
1309
+ type(self).__name__,
1310
+ self.inventoryItems.__name__,
1311
+ InventoryItemRequestParameter.__name__,
1312
+ type(parameter).__name__,
1313
+ )
1314
+ )
1315
+ return InventoryItems(connection=self._connection, parameters=parameter)
1316
+
1317
+ def newSharedContent(self, ref=None) -> SharedContent:
1318
+ return self.getTypedEntityClass(None, SharedContent)(
1319
+ ref=ref, connection=self._connection
1320
+ )
1321
+
1322
+ def sharedContent(self, id: int) -> SharedContent:
1323
+ return self._fetchEntity(SharedContent, id)
1324
+
1325
+ def sharedContents(
1326
+ self, parameter: Optional[SharedContentRequestParameter] = None
1327
+ ) -> SharedContents:
1328
+ if parameter and not isinstance(parameter, SharedContentRequestParameter):
1329
+ raise LOGSException(
1330
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1331
+ % (
1332
+ type(self).__name__,
1333
+ self.sharedContents.__name__,
1334
+ SharedContentRequestParameter.__name__,
1335
+ type(parameter).__name__,
1336
+ )
1337
+ )
1338
+ return SharedContents(connection=self._connection, parameters=parameter)
1339
+
1340
+ def entity(self, uid: str):
1341
+ return Entities(connection=self._connection).fetch(uid=uid)
1342
+
1343
+ def entities(
1344
+ self, parameter: Optional[EntitiesRequestParameter] = None
1345
+ ) -> Entities:
1346
+ if parameter and not isinstance(parameter, EntitiesRequestParameter):
1347
+ raise LOGSException(
1348
+ "Parameter for %s.%s must be of type %a. (Got %a)"
1349
+ % (
1350
+ type(self).__name__,
1351
+ self.entities.__name__,
1352
+ EntitiesRequestParameter.__name__,
1353
+ type(parameter).__name__,
1354
+ )
1355
+ )
1356
+ return Entities(connection=self._connection, parameters=parameter)
1357
+
1358
+ def datasetMatching(
1359
+ self,
1360
+ files: Union[Constants.FILE_TYPE, Sequence[Constants.FILE_TYPE]],
1361
+ formatIds: Optional[List[str]] = None,
1362
+ ignoreReadErrors=False,
1363
+ ) -> DatasetMatching:
1364
+ return DatasetMatching(
1365
+ connection=self._connection,
1366
+ files=files,
1367
+ formatIds=formatIds,
1368
+ ignoreReadErrors=ignoreReadErrors,
1369
+ )
1370
+
1371
+ def updatableDatasetFiles(
1372
+ self, files: Sequence[Constants.FILE_TYPE], formatIds: List[str]
1373
+ ):
1374
+ datasets = Datasets(
1375
+ connection=self._connection, parameters=cast(DatasetRequestParameter, {})
1376
+ ).findDatasetByFiles(files=files, formatIds=formatIds)
1377
+ for dataset in datasets:
1378
+ yield DatasetsUpdatableFiles(
1379
+ datasetId=dataset.logsId,
1380
+ files=[
1381
+ FileEntry(fullPath=file.fullPath, state=file.state)
1382
+ for file in dataset.files
1383
+ ],
1384
+ )
1385
+
1386
+ @property
1387
+ def instanceOrigin(self) -> Origin:
1388
+ return Origin(name="LOGS (%s)" % self.group, url=self.url, uid=self.uid)
1389
+
1390
+ @property
1391
+ def url(self) -> str:
1392
+ return self._connection.url
1393
+
1394
+ @property
1395
+ def apiUrl(self) -> str:
1396
+ return self._connection.apiUrl
1397
+
1398
+ @property
1399
+ def uid(self) -> Optional[UUID]:
1400
+ return self._connection.metadata.uid
1401
+
1402
+ @property
1403
+ def group(self) -> Optional[str]:
1404
+ return self._connection._group
1405
+
1406
+ @property
1407
+ def currentUser(self) -> Person:
1408
+ return self._currentUser
1409
+
1410
+ @property
1411
+ def cacheDir(self) -> Optional[str]:
1412
+ return self._cacheDir
1413
+
1414
+ @cacheDir.setter
1415
+ def cacheDir(self, value):
1416
+ self._cacheDir = Tools.checkAndConvert(value, str, "cacheDir")
1417
+
1418
+ def version(self) -> Optional[str]:
1419
+ return self._connection.metadata.version
1420
+
1421
+ @property
1422
+ def metadata(self) -> ServerMetaData:
1423
+ return self._connection.metadata
1424
+
1425
+
1426
+ if __name__ == "__main__":
1427
+ api_key = input("Please specify api key: ")
1428
+ _url = input("Please specify LOGS url: ")
1429
+
1430
+ # Example input:
1431
+ # api_key = "8V6oQ804t2nPgGPDJIk4CuneRI5q48ERUxgEpk+YqXzX9uLuMUySycHkeXP6DefN"
1432
+ # url = "http://localhost:900/sandbox"
1433
+
1434
+ logs = LOGS(
1435
+ _url, api_key, options=LOGSOptions(showRequestUrl=True, showRequestBody=False)
1436
+ )