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/LOGSConnection.py ADDED
@@ -0,0 +1,647 @@
1
+ import json
2
+ import random
3
+ import re
4
+ from dataclasses import dataclass
5
+ from enum import Enum
6
+ from typing import Any, Dict, List, Optional, Sequence, Tuple, Union, cast
7
+
8
+ import requests
9
+ from requests import Response
10
+
11
+ from LOGS.Auxiliary import LOGSException, Tools
12
+ from LOGS.Auxiliary.LOGSErrorResponse import LOGSErrorResponse
13
+ from LOGS.Entities.FileEntry import FileEntry
14
+ from LOGS.LOGSOptions import LOGSOptions
15
+ from LOGS.ServerMetaData import ServerMetaData
16
+
17
+
18
+ class ResponseTypes(Enum):
19
+ RAW = "raw"
20
+ JSON = "json"
21
+
22
+
23
+ RESPONSE_TYPES = Union[bytes, Dict[Any, Any], Response, str]
24
+
25
+
26
+ @dataclass
27
+ class MultipartEntry:
28
+ name: str
29
+ fileName: Optional[str]
30
+ content: Union[str, dict, FileEntry]
31
+
32
+
33
+ class LOGSConnection:
34
+ """Python class to access the LOGS web API"""
35
+
36
+ _noErrorStates = set([200, 201, 204])
37
+ _compatibleAPIVersions = set(["4.0"])
38
+ # _compatibleAPIVersions = set(["1.1"])
39
+ __urlRe = re.compile(r"(?:(https*)\:\/\/)*([^\/:]+)(?:\:(\d+))*(?:\/(.*))*")
40
+ __urlApiRe = re.compile(r"api\/(\d+\.\d+)")
41
+ _port: Optional[int]
42
+ _connected: bool
43
+ _metadata: ServerMetaData
44
+
45
+ def __init__(
46
+ self,
47
+ url: str,
48
+ apiKey: str,
49
+ use_internal: bool = False,
50
+ options: Optional[LOGSOptions] = None,
51
+ verify: bool = True,
52
+ ):
53
+ """Checks the connection to the server on creation
54
+
55
+ :param url: URL to specific LOGS group (e.g. https://mylogs/mygroup or https://mylogs:80/mygroup/api/0.1)
56
+ :param api_key: The API key that grants access to LOGS (you need to generate on in LOGS and copy it)
57
+ :param verbose: If set you see some information about the server connection. Defaults to False.
58
+
59
+ :raises Exception: URL does not defined or is invalid.
60
+ :raises Exception: The URL does not define a group.
61
+ :raises Exception: Server cannot be reached.
62
+ """
63
+ self._options = Tools.checkAndConvert(
64
+ options, LOGSOptions, "options", initOnNone=True
65
+ )
66
+ self.promptPrefix = "LOGSAPI>"
67
+
68
+ self.url = url
69
+
70
+ if self._options.showServerInfo:
71
+ self.printServerStatus()
72
+
73
+ self._apiKey = apiKey
74
+ self._useInternal = use_internal
75
+ self._verify = verify
76
+ self._connected = False
77
+ self._metadata = ServerMetaData()
78
+
79
+ self.checkServer()
80
+
81
+ def printServerStatus(self):
82
+ print(self.promptPrefix, "Server properties:")
83
+ print(self.promptPrefix, " protocol:", self._protocol)
84
+ print(self.promptPrefix, " server:", self._server)
85
+ print(self.promptPrefix, " port:", self._port)
86
+ print(self.promptPrefix, " group:", self._group)
87
+
88
+ def setUrl(self, url):
89
+ match = self.__urlRe.search(url)
90
+ protocol = "http"
91
+ version = "0.1"
92
+ if not match:
93
+ raise Exception("Invalid URL '%s'." % url)
94
+ else:
95
+ (protocol, server, portStr, endpoints) = match.groups()
96
+ if endpoints:
97
+ group = endpoints.split("/")[0]
98
+ else:
99
+ group = None
100
+ if server == None or server == "":
101
+ raise Exception("URL must define a server.")
102
+ if group == None or group == "":
103
+ raise Exception("URL must contain a group.")
104
+
105
+ if portStr == None or portStr == "":
106
+ port = None
107
+ else:
108
+ port = int(portStr)
109
+
110
+ match = self.__urlApiRe.search(endpoints)
111
+ if match:
112
+ version = match.group(1)
113
+
114
+ # print("match", (protocol, server, port, group, version))
115
+
116
+ self._version = version
117
+ self._protocol = protocol
118
+ self._server = server
119
+ self._port = port
120
+ self._group = group
121
+ # self._url = url
122
+
123
+ def checkServer(self):
124
+ """Check if server can be reached
125
+
126
+ :raises Exception: Server cannot be reached.
127
+ """
128
+ testEndpoint = ["version", "detail"]
129
+
130
+ result, error = self.getEndpoint(testEndpoint)
131
+ url = result["url"] if isinstance(result, dict) else self.url
132
+ if error:
133
+ raise LOGSException(
134
+ "Could not connect to '%s': %s" % (url, error.errorString())
135
+ )
136
+ if self._options.showServerInfo:
137
+ print(
138
+ self.promptPrefix,
139
+ "Connection to server '%s://%s%s' successful."
140
+ % (
141
+ self.protocol,
142
+ self.server,
143
+ ":" + str(self.port) if self.port else "",
144
+ ),
145
+ )
146
+ self._connected = True
147
+
148
+ if isinstance(result, dict):
149
+ self._metadata = ServerMetaData(ref=result)
150
+ if (
151
+ not self._metadata.apiVersion
152
+ or self._metadata.apiVersion not in self._compatibleAPIVersions
153
+ ):
154
+ raise LOGSException(
155
+ "This library is not compatible with the LOGS API version '%s'. (Expected %s %s)"
156
+ % (
157
+ (
158
+ self._metadata.apiVersion
159
+ if self._metadata.apiVersion
160
+ else "unknown"
161
+ ),
162
+ (
163
+ "one of versions"
164
+ if len(self._compatibleAPIVersions) > 1
165
+ else "version"
166
+ ),
167
+ Tools.eclipsesJoin(", ", list(self._compatibleAPIVersions)),
168
+ )
169
+ )
170
+ else:
171
+ raise LOGSException(
172
+ "Server '%s' could be reached but behaved unexpectedly." % (url, error)
173
+ )
174
+
175
+ def getUIUrl(self) -> str:
176
+ """Generate full API URL
177
+
178
+ Returns:
179
+ str: The url of the connected LOGS API (e.g. https://logs.com/api/2.1)
180
+ """
181
+ return "%s://%s%s/%s" % (
182
+ self.protocol,
183
+ self.server,
184
+ ":" + str(self.port) if self.port else "",
185
+ self.group,
186
+ )
187
+
188
+ def getAPIUrl(self) -> str:
189
+ """Generate full API URL
190
+
191
+ :return: The url of the connected LOGS API (e.g. https://logs.com/api/2.1)
192
+ """
193
+ return "%s://%s%s/%s/api/%s" % (
194
+ self.protocol,
195
+ self.server,
196
+ ":" + str(self.port) if self.port else "",
197
+ self.group,
198
+ self.version,
199
+ )
200
+
201
+ def getUIEndpointUrl(
202
+ self, endpoint: Union[Union[str, int], Sequence[Union[str, int]]]
203
+ ) -> str:
204
+ """Generate full API URL for a given endpoint
205
+
206
+ Returns:
207
+ str: The url of the connected LOGS API (for dataset endpoint e.g. https://logs.com/api/2.1/dataset)
208
+ """
209
+
210
+ if isinstance(endpoint, list):
211
+ endpoint = "/".join([str(e) for e in endpoint])
212
+
213
+ return self.getUIUrl() + "/" + str(endpoint)
214
+
215
+ def getEndpointUrl(
216
+ self, endpoint: Union[Union[str, int], Sequence[Union[str, int]]]
217
+ ) -> str:
218
+ """Generate full API URL for a given endpoint
219
+
220
+ :return: The url of the connected LOGS API (for dataset endpoint e.g. https://logs.com/api/2.1/dataset)
221
+ """
222
+
223
+ if isinstance(endpoint, list):
224
+ endpoint = "/".join([str(e) for e in endpoint])
225
+
226
+ return self.getAPIUrl() + "/" + str(endpoint)
227
+
228
+ def getUrl(
229
+ self,
230
+ url: str,
231
+ parameters: Optional[dict] = None,
232
+ responseType: ResponseTypes = ResponseTypes.JSON,
233
+ includeUrl: bool = True,
234
+ ):
235
+ """Generate full API URL with GET parameters
236
+
237
+ :param url: Specify an API url otherwise object internal is used. Defaults to None.
238
+ :param parameters: Parameters to pass to an GET request. Defaults to None.
239
+ :param responseType: The return value is converted to the specified format. Defaults to "json".
240
+ :param includeUrl:
241
+
242
+ :return: The response of the server and the error code.
243
+ """
244
+ if self._options.showRequestUrl:
245
+ paramString = ""
246
+ if parameters:
247
+ paramString = " ".join(
248
+ ("%s:%s" % (k, v))
249
+ for k, v in parameters.items()
250
+ if v != None and v != ""
251
+ )
252
+ print(
253
+ self.promptPrefix,
254
+ "GET: %s %s" % (url, "{" + paramString + "}" if paramString else ""),
255
+ )
256
+ if self._options.showRequestHeader:
257
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
258
+
259
+ # print("params", params)
260
+ response = requests.get(
261
+ url, headers=self.getHeader(), params=parameters, verify=self._verify
262
+ )
263
+ # print("URL:", response.url)
264
+
265
+ # if response == None:
266
+ # response =
267
+ # print("url", url)
268
+ return self.__convertResponse(response, responseType, includeUrl)
269
+
270
+ def getHeader(self) -> Dict[str, str]:
271
+ header = {"X-Api-Key": self.apiKey}
272
+
273
+ if self._useInternal:
274
+ header["X-LOGS-internal"] = "true"
275
+
276
+ if self._options.proxyTargetUrl:
277
+ header["X-Target-Backend"] = self._options.proxyTargetUrl
278
+
279
+ return header
280
+
281
+ def deleteUrl(
282
+ self,
283
+ url: str,
284
+ parameters: dict = {},
285
+ responseType: ResponseTypes = ResponseTypes.JSON,
286
+ includeUrl: bool = True,
287
+ ):
288
+ """Generate full API URL with PUT body
289
+
290
+ :param url: Specify an API url otherwise object internal is used. Defaults to None.
291
+ :param params: Parameters to pass to an PUT request as json body. Defaults to None.
292
+ :param mode: The return value is converted to the specified format. Defaults to "json".
293
+
294
+ :return: The response of the server and the error code.
295
+ """
296
+
297
+ if self._options.showRequestUrl:
298
+ print(self.promptPrefix, "DELETE: %s" % url)
299
+ if self._options.showRequestHeader:
300
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
301
+
302
+ response = requests.delete(
303
+ url, headers=self.getHeader(), params=parameters, verify=self._verify
304
+ )
305
+ return self.__convertResponse(response, responseType, includeUrl=includeUrl)
306
+
307
+ def putUrl(
308
+ self,
309
+ url: str,
310
+ data: Union[dict, list] = {},
311
+ responseType: ResponseTypes = ResponseTypes.JSON,
312
+ ):
313
+ """Generate full API URL with PUT body
314
+
315
+ :param url: Specify an API url otherwise object internal is used. Defaults to None.
316
+ :param params: Parameters to pass to an PUT request as json body. Defaults to None.
317
+ :param mode: The return value is converted to the specified format. Defaults to "json".
318
+
319
+ :return: The response of the server and the error code.
320
+ """
321
+
322
+ if self._options.showRequestUrl:
323
+ print(self.promptPrefix, "PUT: %s" % url)
324
+ if self._options.showRequestHeader:
325
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
326
+
327
+ if self._options.showRequestBody:
328
+ print(self.promptPrefix, "BODY: %s" % self.__convertBody(data))
329
+
330
+ response = requests.put(
331
+ url, headers=self.getHeader(), json=data, verify=self._verify
332
+ )
333
+ return self.__convertResponse(response, responseType)
334
+
335
+ def putEndpoint(
336
+ self,
337
+ endpoint: Union[Union[str, int], Sequence[Union[str, int]]],
338
+ data: Union[dict, list] = {},
339
+ responseType: ResponseTypes = ResponseTypes.JSON,
340
+ ) -> Tuple[Optional[RESPONSE_TYPES], Optional[LOGSErrorResponse]]:
341
+ """Connects to the API with PUT access to given endpoint
342
+
343
+ :param endpoint: Name of the endpoint (e.g. dataset/2/tracks)
344
+ :param params: Parameters to pass to the endpoint as json body. Defaults to None.
345
+
346
+ :return: The response of the server and the error code.
347
+ """
348
+ url = self.getEndpointUrl(endpoint)
349
+
350
+ return self.putUrl(url, data, responseType)
351
+
352
+ def postMultipartUrl(
353
+ self,
354
+ url: str,
355
+ data: List[MultipartEntry] = [],
356
+ responseType: ResponseTypes = ResponseTypes.JSON,
357
+ ):
358
+ if self._options.showRequestUrl:
359
+ print(self.promptPrefix, "POST: %s" % url)
360
+ if self._options.showRequestHeader:
361
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
362
+
363
+ if self._options.showRequestBody:
364
+ separator = "-" * 29 + "".join(
365
+ [str(random.randint(0, 9)) for _ in range(29)]
366
+ )
367
+
368
+ files = []
369
+ for entry in data:
370
+ content: Any = ""
371
+ if isinstance(entry.content, FileEntry):
372
+ # content = entry.content.toJson(compact=True)
373
+ with open(entry.content.path, "rb") as read:
374
+ content = read.read()
375
+ else:
376
+ content = json.dumps(entry.content)
377
+
378
+ if self._options.showRequestBody:
379
+ print(self.promptPrefix, "BODY: %s" % separator)
380
+ print(
381
+ self.promptPrefix,
382
+ "BODY: %s"
383
+ % "Content-Disposition: form-data; name='entry.fileName'",
384
+ )
385
+
386
+ c = (
387
+ str(content[:100]) + "..."
388
+ if isinstance(content, bytes) and len(content) > 100
389
+ else content
390
+ )
391
+ print(self.promptPrefix, "BODY: %s" % c)
392
+
393
+ files.append((entry.name, (entry.fileName, content)))
394
+
395
+ #### For checking the request
396
+ # request = requests.Request(
397
+ # "POST", "http://localhost:900/sandbox/api/0.1/datasets/create", files=files
398
+ # ).prepare()
399
+ # print(cast(Any, request.body).decode("ascii", "ignore"))
400
+
401
+ response = requests.post(
402
+ url, headers=self.getHeader(), files=files, verify=self._verify
403
+ )
404
+
405
+ return self.__convertResponse(response, responseType)
406
+
407
+ def postUrl(
408
+ self,
409
+ url: str,
410
+ data: Union[dict, list] = {},
411
+ parameters: Optional[dict] = None,
412
+ responseType: ResponseTypes = ResponseTypes.JSON,
413
+ includeUrl: bool = True,
414
+ ):
415
+ """Generate full API URL with PUT body
416
+
417
+ :param url: Specify an API url otherwise object internal is used. Defaults to None.
418
+ :param params: Parameters to pass to an PUT request as json body. Defaults to None.
419
+ :param mode: The return value is converted to the specified format. Defaults to "json".
420
+
421
+ :return: The response of the server and the error code.
422
+ """
423
+ if self._options.showRequestUrl:
424
+ paramString = ""
425
+ if parameters:
426
+ paramString = " ".join(
427
+ ("%s:%s" % (k, v))
428
+ for k, v in parameters.items()
429
+ if v != None and v != ""
430
+ )
431
+ print(
432
+ self.promptPrefix,
433
+ "POST: %s %s" % (url, "{" + paramString + "}" if paramString else ""),
434
+ )
435
+ if self._options.showRequestHeader:
436
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
437
+
438
+ if self._options.showRequestBody:
439
+ print(self.promptPrefix, "BODY: %s" % self.__convertBody(data))
440
+
441
+ response = requests.post(
442
+ url,
443
+ headers=self.getHeader(),
444
+ params=parameters,
445
+ json=data,
446
+ verify=self._verify,
447
+ )
448
+ return self.__convertResponse(response, responseType, includeUrl)
449
+
450
+ def postMultipartEndpoint(
451
+ self,
452
+ endpoint: Union[Union[str, int], Sequence[Union[str, int]]],
453
+ data: List[MultipartEntry] = [],
454
+ responseType: ResponseTypes = ResponseTypes.JSON,
455
+ ):
456
+ url = self.getEndpointUrl(endpoint)
457
+
458
+ return self.postMultipartUrl(url, data, responseType)
459
+
460
+ def postEndpoint(
461
+ self,
462
+ endpoint: Union[Union[str, int], Sequence[Union[str, int]]],
463
+ parameters: Optional[dict] = None,
464
+ data: Union[dict, list] = {},
465
+ responseType: ResponseTypes = ResponseTypes.JSON,
466
+ ):
467
+ """Connects to the API with PUT access to given endpoint
468
+
469
+ :param endpoint: Name of the endpoint (e.g. dataset/2/tracks)
470
+ :param params: Parameters to pass to the endpoint as json body. Defaults to None.
471
+
472
+ :return: The response of the server and the error code.
473
+ """
474
+ url = self.getEndpointUrl(endpoint)
475
+
476
+ return self.postUrl(
477
+ url=url, data=data, parameters=parameters, responseType=responseType
478
+ )
479
+
480
+ def deleteEndpoint(
481
+ self,
482
+ endpoint: Union[Union[str, int], Sequence[Union[str, int]]],
483
+ parameters: dict = {},
484
+ responseType: ResponseTypes = ResponseTypes.JSON,
485
+ includeUrl: bool = True,
486
+ ):
487
+ """Connects to the API with DELETE access to given endpoint
488
+
489
+ :param endpoint: Name of the endpoint (e.g. dataset/2/tracks)
490
+ :param params: Parameters to pass to the endpoint. Defaults to None.
491
+ :param mode: Convert result to this format. Defaults to None.
492
+
493
+ :return: The response of the server and the error code.
494
+ """
495
+ # print("Headers:", headers)
496
+ # print("Params:", params)
497
+ url = self.getEndpointUrl(endpoint)
498
+
499
+ return self.deleteUrl(
500
+ url, parameters=parameters, responseType=responseType, includeUrl=includeUrl
501
+ )
502
+
503
+ def getEndpoint(
504
+ self,
505
+ endpoint: Union[Union[str, int], Sequence[Union[str, int]]],
506
+ parameters: Optional[dict] = None,
507
+ responseType: ResponseTypes = ResponseTypes.JSON,
508
+ includeUrl: bool = True,
509
+ ) -> Tuple[Optional[RESPONSE_TYPES], Optional[LOGSErrorResponse]]:
510
+ """Connects to the API with GET access to given endpoint
511
+
512
+ :param endpoint: Name of the endpoint (e.g. dataset/2/tracks)
513
+ :param params: Parameters to pass to the endpoint. Defaults to None.
514
+ :param mode: Convert result to this format. Defaults to None.
515
+
516
+ :return: The response of the server and the error code.
517
+ """
518
+ # print("Headers:", headers)
519
+ # print("Params:", params)
520
+ url = self.getEndpointUrl(endpoint)
521
+ # print("URL:", url)
522
+ # print("Params:", params)
523
+
524
+ return self.getUrl(
525
+ url, parameters=parameters, responseType=responseType, includeUrl=includeUrl
526
+ )
527
+
528
+ # header = {"X-Api-Key": api_key}
529
+
530
+ # # try:
531
+ # response = requests.get(url, headers=header, params=params, verify=False, verify=self._verify)
532
+ # # except ValueError as error:
533
+ # # print(error)
534
+ # return self.convertResponse(response, mode)
535
+
536
+ # def convertCustomFieldParams(self, params: dict):
537
+ # # print(">", params)
538
+ # return {"customFields[%s]" % k: v for k, v in params.items()}
539
+
540
+ @classmethod
541
+ def __convertBody(cls, body) -> str:
542
+ if body == None:
543
+ return "None"
544
+ if isinstance(body, dict) or isinstance(body, list):
545
+ return json.dumps(body)
546
+ return body
547
+
548
+ def __convertResponse(
549
+ self,
550
+ response: Response,
551
+ responseType: ResponseTypes = ResponseTypes.JSON,
552
+ includeUrl: bool = True,
553
+ ) -> Tuple[Optional[RESPONSE_TYPES], Optional[LOGSErrorResponse]]:
554
+ if response.status_code >= 200 and response.status_code < 300:
555
+ if responseType == ResponseTypes.RAW:
556
+ return response.content, None
557
+ else:
558
+ try:
559
+ result = response.json() if len(response.content) > 0 else ""
560
+ if isinstance(result, dict) and includeUrl:
561
+ result["url"] = response.url
562
+ return cast(Union[dict, str], result), None
563
+ except:
564
+ errors = []
565
+ try:
566
+ errors = response.text.split("\n")
567
+ except:
568
+ pass
569
+ errorResponse = LOGSErrorResponse()
570
+ errors.insert(0, "%d %s" % (response.status_code, response.reason))
571
+ errorResponse.errors = errors
572
+ else:
573
+
574
+ if response.status_code in self._noErrorStates:
575
+ errorResponse = LOGSErrorResponse()
576
+ errorResponse.status = response.status_code
577
+ else:
578
+ try:
579
+ r = response.json()
580
+ errorResponse = LOGSErrorResponse(r)
581
+ except:
582
+ errors = []
583
+ try:
584
+ errors = response.text.split("\n")
585
+ except:
586
+ pass
587
+ errorResponse = LOGSErrorResponse()
588
+ errors.insert(0, "%d %s" % (response.status_code, response.reason))
589
+ errorResponse.errors = errors
590
+
591
+ return (
592
+ response,
593
+ (
594
+ errorResponse
595
+ if errorResponse and errorResponse.errorStringList
596
+ else None
597
+ ),
598
+ )
599
+
600
+ @property
601
+ def version(self) -> str:
602
+ return self._version
603
+
604
+ @property
605
+ def protocol(self) -> str:
606
+ return self._protocol
607
+
608
+ @property
609
+ def server(self) -> str:
610
+ return self._server
611
+
612
+ @property
613
+ def port(self) -> Optional[int]:
614
+ return self._port
615
+
616
+ @property
617
+ def group(self) -> str:
618
+ return self._group
619
+
620
+ @property
621
+ def apiUrl(self) -> str:
622
+ return "%s/api/%s" % (self.url, self.version)
623
+
624
+ @property
625
+ def url(self) -> str:
626
+ return "%s://%s%s/%s" % (
627
+ self.protocol,
628
+ self.server,
629
+ ":" + str(self.port) if self.port else "",
630
+ self.group,
631
+ )
632
+
633
+ @url.setter
634
+ def url(self, value):
635
+ self.setUrl(value)
636
+
637
+ @property
638
+ def apiKey(self) -> str:
639
+ return self._apiKey
640
+
641
+ @apiKey.setter
642
+ def apiKey(self, value):
643
+ self._apiKey = value
644
+
645
+ @property
646
+ def metadata(self) -> ServerMetaData:
647
+ return self._metadata
LOGS/LOGSOptions.py ADDED
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+
5
+ @dataclass
6
+ class LOGSOptions:
7
+ showRequestUrl: bool = False
8
+ showRequestHeader: bool = False
9
+ showRequestBody: bool = False
10
+ showServerInfo: bool = False
11
+ proxyTargetUrl: Optional[str] = None