logs-py 3.0.1__py3-none-any.whl → 3.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of logs-py might be problematic. Click here for more details.

@@ -6,6 +6,7 @@ from LOGS.Auxiliary.Tools import Tools
6
6
  from LOGS.Entity.Entity import Entity
7
7
  from LOGS.Entity.EntityConnector import EntityConnector
8
8
  from LOGS.Entity.EntityRequestParameter import EntityRequestParameter
9
+ from LOGS.Entity.IdIterator import IdIterator
9
10
  from LOGS.LOGSConnection import RESPONSE_TYPES, LOGSConnection, ResponseTypes
10
11
 
11
12
  # SELF = TypeVar("SELF", bound="EntityConnector")
@@ -189,8 +190,8 @@ class EntityIterator(Generic[ENTITY, REQUEST], EntityConnector[ENTITY]):
189
190
 
190
191
  items = iter(self)
191
192
  ids = []
192
- for dataset in items:
193
- ids.append(dataset.id)
193
+ for item in items:
194
+ ids.append(item.id)
194
195
  if len(ids) >= size:
195
196
  param = dataclasses.replace(self._parameters)
196
197
  param.ids = ids
@@ -205,6 +206,17 @@ class EntityIterator(Generic[ENTITY, REQUEST], EntityConnector[ENTITY]):
205
206
  iterator._parameters = param
206
207
  yield iterator
207
208
 
209
+ def ids(self):
210
+ if not self._generatorType:
211
+ return
212
+ d = self._generatorType()
213
+ iterator = IdIterator[type(d.id), REQUEST](connection=self._connection)
214
+ iterator._endpoint = self._endpoint
215
+ iterator._parameters = self._parameters
216
+ iterator._parameterType = self._parameterType
217
+ iterator._generatorType = type(d.id)
218
+ return iterator
219
+
208
220
  def first(self):
209
221
  i = iter(self)
210
222
  try:
@@ -0,0 +1,190 @@
1
+ from typing import Generic, List, Optional, Type, TypeVar, Union, cast
2
+
3
+ from LOGS.Auxiliary.Exceptions import LOGSException
4
+ from LOGS.Auxiliary.Tools import Tools
5
+ from LOGS.Entity.Entity import Entity
6
+ from LOGS.Entity.EntityConnector import EntityConnector
7
+ from LOGS.Entity.EntityRequestParameter import EntityRequestParameter
8
+ from LOGS.LOGSConnection import RESPONSE_TYPES, LOGSConnection, ResponseTypes
9
+
10
+ # SELF = TypeVar("SELF", bound="EntityConnector")
11
+
12
+ _idType = TypeVar("_idType", bound=Union[int, str])
13
+ REQUEST = TypeVar("REQUEST", bound=EntityRequestParameter)
14
+
15
+
16
+ class IdIterator(Generic[_idType, REQUEST], EntityConnector[Entity]):
17
+ """Represents a connected LOGS entity id iterator"""
18
+
19
+ _entityIterator: int
20
+ _currentResults: Optional[RESPONSE_TYPES]
21
+ _generatorType: Optional[Type[_idType]] = None
22
+ _parameterType: Optional[Type[REQUEST]] = None
23
+
24
+ _parametersInput: Optional[REQUEST]
25
+ _parameters: REQUEST
26
+ _responseType: ResponseTypes = ResponseTypes.JSON
27
+ _includeUrl: bool = True
28
+ _connection: Optional[LOGSConnection]
29
+ _count: Optional[int]
30
+
31
+ def __init__(
32
+ self, connection: Optional[LOGSConnection], parameters: Optional[REQUEST] = None
33
+ ):
34
+ super().__init__(connection=connection)
35
+ self._connection = connection
36
+
37
+ self._parametersInput = parameters
38
+
39
+ self._entityIterator = 0
40
+ self._currentResults = None
41
+ self._count = None
42
+
43
+ def __iter__(self):
44
+ self._initEntityIterator()
45
+ return self
46
+
47
+ def __next__(self) -> _idType:
48
+ if not self._generatorType:
49
+ raise NotImplementedError(
50
+ "Iterator cannot generate items without a specified 'generatorType' field in class %a"
51
+ % type(self).__name__
52
+ )
53
+
54
+ return self._getNextEntity()
55
+
56
+ def _getNextPage(self, result):
57
+ if not self._connection:
58
+ raise LOGSException("Connection of %a is not defined" % type(self).__name__)
59
+
60
+ if "hasNext" not in result or not result["hasNext"]:
61
+ return None, None
62
+
63
+ url = result["url"]
64
+
65
+ page = 1
66
+ if "page" in result:
67
+ page = int(result["page"])
68
+ elif self._parameters.page:
69
+ page = self._parameters.page
70
+ self._parameters.page = page + 1
71
+ return self._connection.postUrl(
72
+ url=url,
73
+ data=self._parameters.toDict(),
74
+ responseType=self._responseType,
75
+ includeUrl=self._includeUrl,
76
+ )
77
+
78
+ def _checkParameterType(self):
79
+ if not self._parameterType:
80
+ raise NotImplementedError(
81
+ "Entity connection cannot be initialized without the request 'parameterType' field in class %a"
82
+ % type(self).__name__
83
+ )
84
+
85
+ if not isinstance(self._parameterType, type):
86
+ raise NotImplementedError(
87
+ "The field 'parameterType' must be a 'type' got %a in class %a"
88
+ % (type(self._parameterType), type(self).__name__)
89
+ )
90
+
91
+ if self._parametersInput and not isinstance(
92
+ self._parametersInput, self._parameterType
93
+ ):
94
+ raise LOGSException(
95
+ "Parameter for iterator %a must be of type %a. (Got %a)"
96
+ % (
97
+ type(self).__name__,
98
+ self._parameterType.__name__,
99
+ type(self._parametersInput).__name__,
100
+ )
101
+ )
102
+
103
+ self._parametersInput = Tools.checkAndConvert(
104
+ self._parametersInput, self._parameterType, "parameters", initOnNone=True
105
+ )
106
+
107
+ def _initEntityIterator(self):
108
+ self._checkParameterType()
109
+
110
+ url = self.getBaseUrl()
111
+ self._entityIterator = 0
112
+
113
+ if not self._connection:
114
+ raise LOGSException(
115
+ "Entity connector %a is not connected" % type(self).__name__
116
+ )
117
+
118
+ tmp = False
119
+ if hasattr(self._parameters, "includeCount"):
120
+ tmp = self._parameters.includeCount
121
+ self._parameters.includeCount = True
122
+
123
+ self._currentResults, responseError = self._connection.postUrl(
124
+ url=url + "/ids_only",
125
+ data=self._parameters.toDict(),
126
+ responseType=self._responseType,
127
+ includeUrl=self._includeUrl,
128
+ )
129
+
130
+ if hasattr(self._parameters, "includeCount"):
131
+ self._parameters.includeCount = tmp
132
+
133
+ if isinstance(self._currentResults, dict) and "count" in self._currentResults:
134
+ self._count = int(self._currentResults["count"])
135
+
136
+ if responseError:
137
+ raise LOGSException(responseError=responseError)
138
+
139
+ def _getNextEntity(self):
140
+ if not isinstance(self._currentResults, dict):
141
+ raise StopIteration
142
+
143
+ results = self._currentResults["results"]
144
+ if self._entityIterator < len(results):
145
+ result = results[self._entityIterator]
146
+ self._entityIterator += 1
147
+ return result
148
+
149
+ self._currentResults, error = self._getNextPage(self._currentResults)
150
+ if error:
151
+ raise Exception("Connection error: %a", error)
152
+ self._entityIterator = 0
153
+
154
+ if (
155
+ not self._currentResults
156
+ or not isinstance(self._currentResults, dict)
157
+ or len(self._currentResults["results"]) < 1
158
+ ):
159
+ raise StopIteration
160
+
161
+ return self._getNextEntity()
162
+
163
+ def first(self):
164
+ i = iter(self)
165
+ try:
166
+ return cast(_idType, next(i))
167
+ except StopIteration:
168
+ return None
169
+
170
+ def toList(self, count: Optional[int] = None):
171
+ if count:
172
+ count = int(count)
173
+ if count < 0:
174
+ raise Exception("Invalid negative count %d" % count)
175
+ result = cast(List[_idType], [])
176
+ num = 0
177
+ for entity in self:
178
+ result.append(entity)
179
+ num += 1
180
+ if num >= count:
181
+ break
182
+ return result
183
+
184
+ return list(self)
185
+
186
+ @property
187
+ def count(self) -> int:
188
+ if self._count is None:
189
+ self._initEntityIterator()
190
+ return self._count if self._count else 0
LOGS/LOGS.py CHANGED
@@ -213,6 +213,8 @@ class LOGS:
213
213
  _url = config["url"]
214
214
  if "apiKey" in config:
215
215
  _apiKey = config["apiKey"]
216
+ if "proxyTargetUrl" in config:
217
+ self._options.proxyTargetUrl = config["proxyTargetUrl"]
216
218
 
217
219
  if url:
218
220
  _url = url
LOGS/LOGSConnection.py CHANGED
@@ -253,6 +253,8 @@ class LOGSConnection:
253
253
  self.promptPrefix,
254
254
  "GET: %s %s" % (url, "{" + paramString + "}" if paramString else ""),
255
255
  )
256
+ if self._options.showRequestHeader:
257
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
256
258
 
257
259
  # print("params", params)
258
260
  response = requests.get(
@@ -266,10 +268,15 @@ class LOGSConnection:
266
268
  return self.__convertResponse(response, responseType, includeUrl)
267
269
 
268
270
  def getHeader(self) -> Dict[str, str]:
271
+ header = {"X-Api-Key": self.apiKey}
272
+
269
273
  if self._useInternal:
270
- return {"X-Api-Key": self.apiKey, "X-LOGS-internal": "true"}
271
- else:
272
- return {"X-Api-Key": self.apiKey}
274
+ header["X-LOGS-internal"] = "true"
275
+
276
+ if self._options.proxyTargetUrl:
277
+ header["X-Target-Backend"] = self._options.proxyTargetUrl
278
+
279
+ return header
273
280
 
274
281
  def deleteUrl(
275
282
  self,
@@ -289,6 +296,8 @@ class LOGSConnection:
289
296
 
290
297
  if self._options.showRequestUrl:
291
298
  print(self.promptPrefix, "DELETE: %s" % url)
299
+ if self._options.showRequestHeader:
300
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
292
301
 
293
302
  response = requests.delete(
294
303
  url, headers=self.getHeader(), params=parameters, verify=self._verify
@@ -312,6 +321,8 @@ class LOGSConnection:
312
321
 
313
322
  if self._options.showRequestUrl:
314
323
  print(self.promptPrefix, "PUT: %s" % url)
324
+ if self._options.showRequestHeader:
325
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
315
326
 
316
327
  if self._options.showRequestBody:
317
328
  print(self.promptPrefix, "BODY: %s" % self.__convertBody(data))
@@ -346,6 +357,8 @@ class LOGSConnection:
346
357
  ):
347
358
  if self._options.showRequestUrl:
348
359
  print(self.promptPrefix, "POST: %s" % url)
360
+ if self._options.showRequestHeader:
361
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
349
362
 
350
363
  if self._options.showRequestBody:
351
364
  seperator = "-" * 29 + "".join(
@@ -419,6 +432,8 @@ class LOGSConnection:
419
432
  self.promptPrefix,
420
433
  "POST: %s %s" % (url, "{" + paramString + "}" if paramString else ""),
421
434
  )
435
+ if self._options.showRequestHeader:
436
+ print(self.promptPrefix, "HEADER: %s" % self.getHeader())
422
437
 
423
438
  if self._options.showRequestBody:
424
439
  print(self.promptPrefix, "BODY: %s" % self.__convertBody(data))
LOGS/LOGSOptions.py CHANGED
@@ -1,8 +1,11 @@
1
1
  from dataclasses import dataclass
2
+ from typing import Optional
2
3
 
3
4
 
4
5
  @dataclass
5
6
  class LOGSOptions:
6
7
  showRequestUrl: bool = False
8
+ showRequestHeader: bool = False
7
9
  showRequestBody: bool = False
8
10
  showServerInfo: bool = False
11
+ proxyTargetUrl: Optional[str] = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: logs-py
3
- Version: 3.0.1
3
+ Version: 3.0.3
4
4
  Summary: A python interface for the LOGS public API
5
5
  Home-page: https://docs.logs-python.com
6
6
  Author: Sina Kazemi
@@ -1,6 +1,6 @@
1
- LOGS/LOGS.py,sha256=qLeYWnxMyoWOgwM-mKEeoTEcWmOd_4UWS0ekUBrdQf4,45284
2
- LOGS/LOGSConnection.py,sha256=vy_Eda7-oAskPN1Zb-Y_6ZG4NZ62FFfT4OP7yfjBBzE,20917
3
- LOGS/LOGSOptions.py,sha256=jgJjLycBh9AOq0YtTpXWuaGz5afQcldZHEye3XaH3ZI,166
1
+ LOGS/LOGS.py,sha256=O0XpA1m7uashHuBIKmowYI6ZeeX_d7p2jS_dUpbhVXU,45399
2
+ LOGS/LOGSConnection.py,sha256=T8C9vTk4nyy0qJjs3Ee2_pkFyDPMoKapOGTUszP_htY,21581
3
+ LOGS/LOGSOptions.py,sha256=eDymNMLvms_DcM_71poUxcn7FkUH5K-zSZw28gMsVzs,271
4
4
  LOGS/ServerMetaData.py,sha256=WdXCCiCSFqER6s9c3N3v0O273OvxygxBzmE6_C8FmXs,3361
5
5
  LOGS/__init__.py,sha256=J5-bGgXlm7MxYhTAhLtqWLn612_rarRRxblT5n5O2bY,280
6
6
  LOGS/Auxiliary/Constants.py,sha256=jKsThb6TS6b1adgnv1uAoqohBJi8ySGo7fULHlE2Es0,2504
@@ -220,7 +220,7 @@ LOGS/Entities/LabNotebookEntryContent/__init__.py,sha256=03TqIEBq0R2B0pUcGplIP68
220
220
  LOGS/Entity/ConnectedEntity.py,sha256=FP1jJoDOXoMBTozz6sur36IxjhlfqGI-1qUK-G001vc,2805
221
221
  LOGS/Entity/Entity.py,sha256=WLCtVjRxyRg6nX8UzEMjKJ4MkLICrMmXSo5xrtRHaUE,6300
222
222
  LOGS/Entity/EntityConnector.py,sha256=kjCoieYABujwX1hIaldJVHmg_Js2OdWdbkvNwgBLeNo,2109
223
- LOGS/Entity/EntityIterator.py,sha256=3gUZx28451sxsHrUT0qYlPRmi03U8rVAcJs0KHXmrEs,7721
223
+ LOGS/Entity/EntityIterator.py,sha256=EF29TdSvC0rTMMnQgCe5X99mYAYNjZydtLaQc3n7-6k,8165
224
224
  LOGS/Entity/EntityMinimal.py,sha256=GysThwk8YbT8xqbHvJqmYKgPf8ckALO5pG-J_SNT0vw,3237
225
225
  LOGS/Entity/EntityMinimalWithIntId.py,sha256=6eVhFFbXKdH3LPj-fAzQLpnzbkWqh1AmV_uRksTi7Ho,1045
226
226
  LOGS/Entity/EntityMinimalWithStrId.py,sha256=JmuY0Aah4YLngrgluzwMkhIyeExj2j6kiBZ6Y115hbA,1046
@@ -230,6 +230,7 @@ LOGS/Entity/EntityRelations.py,sha256=zaAASS5SVDwPVMUyNgUH8DcZhWdErRulrZjD6MAWlh
230
230
  LOGS/Entity/EntityRequestParameter.py,sha256=RH6-Sh8ug3aeq_AOFHs0Lp2J94cKI9Ts3slAATZ1tNA,828
231
231
  LOGS/Entity/EntityWithIntId.py,sha256=B79VqAQ9I0uEQwbf3DMHXoi064gCw4fv3vCKoXwrHQM,631
232
232
  LOGS/Entity/EntityWithStrId.py,sha256=5hz8-F_t_X4kf85DMwW3DJ2NqH_RiRV1Io1WiMN11yk,631
233
+ LOGS/Entity/IdIterator.py,sha256=syaf7ygWPhbpSM3Sa5oukGi4wW9KiYInK8Ry61U85N8,6216
233
234
  LOGS/Entity/SerializeableContent.py,sha256=iN_rW3zorXnvL1RBjyQvwxEJwvx5d3RqZKRtPSlScXk,22203
234
235
  LOGS/Entity/__init__.py,sha256=8q6dB_AqlLGx-6PexFn8QH7LWOnSGRhgPfFVkYAghR0,749
235
236
  LOGS/Interfaces/ICreationRecord.py,sha256=SpACPwz2zA60pkApErZelUOsPq40fHAfiFW3vm9qW9k,1461
@@ -257,7 +258,7 @@ LOGS/Parameters/ParameterElement.py,sha256=fr6AlO_flKRygZZFx1OILP4P-2lV2Tx4PAe6W
257
258
  LOGS/Parameters/ParameterList.py,sha256=ijukB1__iKI5cefmOIIWz0wKaPz9Cx8KpD7Y7Gz2Pn0,1478
258
259
  LOGS/Parameters/ParameterTable.py,sha256=7Lew4DPgWmKcpV1T-1Pvt00kEI05FB383QqO-LHAjds,1758
259
260
  LOGS/Parameters/__init__.py,sha256=jNF_VnD9u6V7usDFymzvDx5kzvcYssnpASICiKW0wdU,341
260
- logs_py-3.0.1.dist-info/METADATA,sha256=_sJJ09I_3FP5hLKlmCbDBLTjIAcA2jeuZoSco0MR4nY,2072
261
- logs_py-3.0.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
262
- logs_py-3.0.1.dist-info/top_level.txt,sha256=Ckn2LiAmGaR7k3tdEnKAc04z_uboMD4gLreYghRNdCs,5
263
- logs_py-3.0.1.dist-info/RECORD,,
261
+ logs_py-3.0.3.dist-info/METADATA,sha256=ZJ_KEvGBwckmHV0jTLjn37FKc6t8KH1ICuMR7MomxQs,2072
262
+ logs_py-3.0.3.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
263
+ logs_py-3.0.3.dist-info/top_level.txt,sha256=Ckn2LiAmGaR7k3tdEnKAc04z_uboMD4gLreYghRNdCs,5
264
+ logs_py-3.0.3.dist-info/RECORD,,