esd-services-api-client 2.5.14a148.dev5__py3-none-any.whl → 2.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,4 +17,4 @@
17
17
  Root index.
18
18
  """
19
19
 
20
- __version__ = "0.0.0"
20
+ __version__ = "2.6.1"
@@ -20,7 +20,11 @@ import os
20
20
  from functools import reduce
21
21
  from typing import Optional, Iterator, final
22
22
 
23
- from adapta.security.clients import AzureClient
23
+ try:
24
+ from adapta.security.clients import AzureClient
25
+ except ImportError:
26
+ pass
27
+
24
28
  from adapta.utils import session_with_retries
25
29
  from requests import Session, Response
26
30
 
@@ -22,7 +22,7 @@ import socketserver
22
22
  import threading
23
23
  from dataclasses import dataclass
24
24
  from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
25
- from typing import Dict, Optional, Any
25
+ from typing import Optional, Any
26
26
 
27
27
  import pandas
28
28
  from adapta.metrics import MetricsProvider
@@ -30,6 +30,7 @@ from adapta.storage.query_enabled_store import QueryEnabledStore
30
30
  from dataclasses_json import DataClassJsonMixin
31
31
  from injector import inject
32
32
 
33
+ from esd_services_api_client.crystal import CrystalEntrypointArguments
33
34
  from esd_services_api_client.nexus.abstractions.algrorithm_cache import InputCache
34
35
  from esd_services_api_client.nexus.abstractions.logger_factory import LoggerFactory
35
36
  from esd_services_api_client.nexus.abstractions.nexus_object import AlgorithmResult
@@ -292,6 +293,15 @@ async def main():
292
293
  Mock HTTP Server
293
294
  :return:
294
295
  """
296
+ def tags_from_payload(payload: MyAlgorithmPayload, _: CrystalEntrypointArguments) -> dict[str, str]:
297
+ return {
298
+ "test_tag": str(payload.x)
299
+ }
300
+ def enrich_from_payload(payload: MyAlgorithmPayload2, run_args: CrystalEntrypointArguments) -> dict[str, dict[str, str]]:
301
+ return {
302
+ "(value of y:{y})": {"y": payload.y},
303
+ "(request_id:{request_id})": {"request_id": run_args.request_id}
304
+ }
295
305
  with ThreadingHTTPServer(("localhost", 9876), MockRequestHandler) as server:
296
306
  server_thread = threading.Thread(target=server.serve_forever)
297
307
  server_thread.daemon = True
@@ -306,6 +316,7 @@ async def main():
306
316
  .on_complete(ObjectiveAnalytics)
307
317
  .inject_configuration(MyAlgorithmConfiguration)
308
318
  .inject_payload(MyAlgorithmPayload, MyAlgorithmPayload2)
319
+ .with_log_enricher(tags_from_payload, enrich_from_payload)
309
320
  )
310
321
 
311
322
  await nexus.activate()
@@ -19,8 +19,9 @@
19
19
 
20
20
  import json
21
21
  import os
22
+ from abc import ABC
22
23
  from logging import StreamHandler
23
- from typing import final, Type, TypeVar, Optional, Dict
24
+ from typing import final, TypeVar
24
25
 
25
26
  from adapta.logs import LoggerInterface, create_async_logger
26
27
  from adapta.logs.handlers.datadog_api_handler import DataDogApiHandler
@@ -29,13 +30,61 @@ from adapta.logs.models import LogLevel
29
30
  TLogger = TypeVar("TLogger") # pylint: disable=C0103:
30
31
 
31
32
 
33
+ @final
34
+ class BootstrapLogger(LoggerInterface, ABC):
35
+ """
36
+ Dummy class to separate bootstrap logging from core app loggers
37
+ """
38
+
39
+
40
+ @final
41
+ class BootstrapLoggerFactory:
42
+ """
43
+ Bootstrap logger provisioner.
44
+ Bootstrap loggers do not use enriched properties since they are initialized before payload is deserialized.
45
+ """
46
+
47
+ def __init__(self):
48
+ self._log_handlers = [
49
+ StreamHandler(),
50
+ ]
51
+ if "NEXUS__DATADOG_LOGGER_CONFIGURATION" in os.environ:
52
+ self._log_handlers.append(
53
+ DataDogApiHandler(
54
+ **json.loads(os.getenv("NEXUS__DATADOG_LOGGER_CONFIGURATION"))
55
+ )
56
+ )
57
+
58
+ def create_logger(self, request_id: str, algorithm_name: str) -> LoggerInterface:
59
+ """
60
+ Creates an async-safe logger for the provided class name.
61
+ """
62
+ return create_async_logger(
63
+ logger_type=BootstrapLogger.__class__,
64
+ log_handlers=self._log_handlers,
65
+ min_log_level=LogLevel(os.getenv("NEXUS__LOG_LEVEL", "INFO")),
66
+ global_tags={
67
+ "request_id": request_id,
68
+ "algorithm": algorithm_name,
69
+ },
70
+ )
71
+
72
+
32
73
  @final
33
74
  class LoggerFactory:
34
75
  """
35
76
  Async logger provisioner.
36
77
  """
37
78
 
38
- def __init__(self):
79
+ def __init__(
80
+ self,
81
+ fixed_template: dict[str, dict[str, str]] | None = None,
82
+ fixed_template_delimiter: str = None,
83
+ global_tags: dict[str, str] | None = None,
84
+ ):
85
+ self._global_tags = global_tags
86
+ self._fixed_template = fixed_template
87
+ self._fixed_template_delimiter = fixed_template_delimiter or ", "
39
88
  self._log_handlers = [
40
89
  StreamHandler(),
41
90
  ]
@@ -45,12 +94,20 @@ class LoggerFactory:
45
94
  **json.loads(os.getenv("NEXUS__DATADOG_LOGGER_CONFIGURATION"))
46
95
  )
47
96
  )
97
+ if "NEXUS__LOGGER_FIXED_TEMPLATE" in os.environ:
98
+ self._fixed_template = self._fixed_template | json.loads(
99
+ os.getenv("NEXUS__LOGGER_FIXED_TEMPLATE")
100
+ )
101
+
102
+ if "NEXUS__LOGGER_FIXED_TEMPLATE_DELIMITER" in os.environ:
103
+ self._fixed_template_delimiter = (
104
+ self._fixed_template_delimiter
105
+ or os.getenv("NEXUS__LOGGER_FIXED_TEMPLATE")
106
+ )
48
107
 
49
108
  def create_logger(
50
109
  self,
51
- logger_type: Type[TLogger],
52
- fixed_template: Optional[Dict[str, Dict[str, str]]] = None,
53
- fixed_template_delimiter=", ",
110
+ logger_type: type[TLogger],
54
111
  ) -> LoggerInterface:
55
112
  """
56
113
  Creates an async-safe logger for the provided class name.
@@ -59,6 +116,7 @@ class LoggerFactory:
59
116
  logger_type=logger_type,
60
117
  log_handlers=self._log_handlers,
61
118
  min_log_level=LogLevel(os.getenv("NEXUS__LOG_LEVEL", "INFO")),
62
- fixed_template=fixed_template,
63
- fixed_template_delimiter=fixed_template_delimiter,
119
+ fixed_template=self._fixed_template,
120
+ fixed_template_delimiter=self._fixed_template_delimiter,
121
+ global_tags=self._global_tags,
64
122
  )
@@ -23,7 +23,7 @@ import platform
23
23
  import signal
24
24
  import sys
25
25
  import traceback
26
- from typing import final, Type, Optional
26
+ from typing import final, Type, Optional, Callable
27
27
 
28
28
  import backoff
29
29
  import urllib3.exceptions
@@ -41,7 +41,10 @@ from esd_services_api_client.crystal import (
41
41
  AlgorithmRunResult,
42
42
  CrystalEntrypointArguments,
43
43
  )
44
- from esd_services_api_client.nexus.abstractions.logger_factory import LoggerFactory
44
+ from esd_services_api_client.nexus.abstractions.logger_factory import (
45
+ LoggerFactory,
46
+ BootstrapLoggerFactory,
47
+ )
45
48
  from esd_services_api_client.nexus.abstractions.nexus_object import AlgorithmResult
46
49
  from esd_services_api_client.nexus.algorithms import (
47
50
  BaselineAlgorithm,
@@ -119,6 +122,21 @@ class Nexus:
119
122
  self._algorithm_run_task: Optional[asyncio.Task] = None
120
123
  self._on_complete_tasks: list[type[UserTelemetryRecorder]] = []
121
124
  self._payload_types: list[type[AlgorithmPayload]] = []
125
+ self._log_enricher: Callable[
126
+ [
127
+ AlgorithmPayload,
128
+ CrystalEntrypointArguments,
129
+ ],
130
+ dict[str, dict[str, str]],
131
+ ] | None = None
132
+ self._log_tagger: Callable[
133
+ [
134
+ AlgorithmPayload,
135
+ CrystalEntrypointArguments,
136
+ ],
137
+ dict[str, str],
138
+ ] | None = None
139
+ self._log_enrichment_delimiter: str = ", "
122
140
 
123
141
  attach_signal_handlers()
124
142
 
@@ -177,6 +195,36 @@ class Nexus:
177
195
 
178
196
  return self
179
197
 
198
+ def with_log_enricher(
199
+ self,
200
+ tagger: Callable[
201
+ [
202
+ AlgorithmPayload,
203
+ CrystalEntrypointArguments,
204
+ ],
205
+ dict[str, str],
206
+ ]
207
+ | None,
208
+ enricher: Callable[
209
+ [
210
+ AlgorithmPayload,
211
+ CrystalEntrypointArguments,
212
+ ],
213
+ dict[str, dict[str, str]],
214
+ ]
215
+ | None = None,
216
+ delimiter: str = ", ",
217
+ ) -> "Nexus":
218
+ """
219
+ Adds a log `tagger` and a log `enricher` to be used with injected logger.
220
+ A log `tagger` will add key-value tags to each emitted log message, and those tags can be inferred from the payload and entrypoint arguments.
221
+ A log `enricher` will add additional static templated content to log messages, and render those templates using payload properties entrypoint argyments.
222
+ """
223
+ self._log_tagger = tagger
224
+ self._log_enricher = enricher
225
+ self._log_enrichment_delimiter = delimiter
226
+ return self
227
+
180
228
  def with_module(self, module: Type[Module]) -> "Nexus":
181
229
  """
182
230
  Adds a (custom) DI module into the DI container.
@@ -260,11 +308,14 @@ class Nexus:
260
308
 
261
309
  self._injector = Injector(self._configurator.injection_binds)
262
310
 
263
- root_logger: LoggerInterface = self._injector.get(LoggerFactory).create_logger(
264
- logger_type=self.__class__,
311
+ bootstrap_logger: LoggerInterface = self._injector.get(
312
+ BootstrapLoggerFactory
313
+ ).create_logger(
314
+ request_id=self._run_args.request_id,
315
+ algorithm_name=os.getenv("CRYSTAL__ALGORITHM_NAME"),
265
316
  )
266
317
 
267
- root_logger.start()
318
+ bootstrap_logger.start()
268
319
 
269
320
  for payload_type in self._payload_types:
270
321
  try:
@@ -272,10 +323,31 @@ class Nexus:
272
323
  self._injector.binder.bind(
273
324
  payload.__class__, to=payload, scope=singleton
274
325
  )
326
+ logger_factory = LoggerFactory(
327
+ fixed_template=None
328
+ if not self._log_enricher
329
+ else self._log_enricher(payload, self._run_args),
330
+ fixed_template_delimiter=self._log_enrichment_delimiter,
331
+ global_tags=self._log_tagger(payload, self._run_args),
332
+ )
333
+ # bind app-level LoggerFactory now
334
+ self._injector.binder.bind(
335
+ logger_factory.__class__,
336
+ to=logger_factory,
337
+ scope=singleton,
338
+ )
275
339
  except BaseException as ex: # pylint: disable=broad-except
276
- root_logger.error("Error reading algorithm payload", ex)
340
+ bootstrap_logger.error("Error reading algorithm payload", ex)
277
341
  sys.exit(1)
278
342
 
343
+ bootstrap_logger.stop()
344
+
345
+ root_logger: LoggerInterface = self._injector.get(LoggerFactory).create_logger(
346
+ logger_type=self.__class__,
347
+ )
348
+
349
+ root_logger.start()
350
+
279
351
  algorithm: BaselineAlgorithm = self._injector.get(self._algorithm_class)
280
352
  telemetry_recorder: TelemetryRecorder = self._injector.get(TelemetryRecorder)
281
353
 
@@ -289,14 +361,18 @@ class Nexus:
289
361
  self._algorithm_run_task = asyncio.create_task(
290
362
  instance.run(**self._run_args.__dict__)
291
363
  )
292
- await self._algorithm_run_task
364
+
365
+ # avoid exception propagation to main thread, since we need to handle it later
366
+ await asyncio.wait(
367
+ [self._algorithm_run_task], return_when=asyncio.FIRST_EXCEPTION
368
+ )
293
369
  ex = self._algorithm_run_task.exception()
294
370
 
295
371
  if ex is not None:
296
372
  root_logger.error(
297
373
  "Algorithm {algorithm} run failed on Nexus version {version}",
298
374
  ex,
299
- algorithm=self._algorithm_class,
375
+ algorithm=algorithm.__class__.__name__,
300
376
  version=__version__,
301
377
  )
302
378
 
@@ -307,8 +383,8 @@ class Nexus:
307
383
 
308
384
  # record telemetry
309
385
  root_logger.info(
310
- "Recording telemetry for the run {request_id}",
311
- request_id=self._run_args.request_id,
386
+ "Recording telemetry for the run {run_id}",
387
+ run_id=self._run_args.request_id,
312
388
  )
313
389
  async with telemetry_recorder as recorder:
314
390
  await recorder.record(
@@ -30,7 +30,9 @@ from injector import Module, singleton, provider
30
30
 
31
31
  from esd_services_api_client.crystal import CrystalConnector
32
32
  from esd_services_api_client.nexus.abstractions.algrorithm_cache import InputCache
33
- from esd_services_api_client.nexus.abstractions.logger_factory import LoggerFactory
33
+ from esd_services_api_client.nexus.abstractions.logger_factory import (
34
+ BootstrapLoggerFactory,
35
+ )
34
36
  from esd_services_api_client.nexus.abstractions.socket_provider import (
35
37
  ExternalSocketProvider,
36
38
  )
@@ -72,18 +74,18 @@ class MetricsModule(Module):
72
74
 
73
75
 
74
76
  @final
75
- class LoggerFactoryModule(Module):
77
+ class BootstrapLoggerFactoryModule(Module):
76
78
  """
77
79
  Logger factory module.
78
80
  """
79
81
 
80
82
  @singleton
81
83
  @provider
82
- def provide(self) -> LoggerFactory:
84
+ def provide(self) -> BootstrapLoggerFactory:
83
85
  """
84
86
  DI factory method.
85
87
  """
86
- return LoggerFactory()
88
+ return BootstrapLoggerFactory()
87
89
 
88
90
 
89
91
  @final
@@ -234,6 +236,7 @@ class ServiceConfigurator:
234
236
 
235
237
  def __init__(self):
236
238
  self._injection_binds = [
239
+ BootstrapLoggerFactoryModule(),
237
240
  MetricsModule(),
238
241
  CrystalReceiverClientModule(),
239
242
  QueryEnabledStoreModule(),
@@ -1,21 +1,19 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: esd-services-api-client
3
- Version: 2.5.14a148.dev5
3
+ Version: 2.6.1
4
4
  Summary: Python clients for ESD services
5
5
  License: Apache 2.0
6
6
  Author: ECCO Sneaks & Data
7
7
  Author-email: esdsupport@ecco.com
8
8
  Maintainer: GZU
9
9
  Maintainer-email: gzu@ecco.com
10
- Requires-Python: >=3.9,<3.12
10
+ Requires-Python: >=3.11,<3.12
11
11
  Classifier: License :: Other/Proprietary License
12
12
  Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.9
14
- Classifier: Programming Language :: Python :: 3.10
15
13
  Classifier: Programming Language :: Python :: 3.11
16
14
  Provides-Extra: azure
17
15
  Provides-Extra: nexus
18
- Requires-Dist: adapta[azure,datadog,storage] (>=3.2,<4.0)
16
+ Requires-Dist: adapta[datadog,storage] (>=3.3,<4.0)
19
17
  Requires-Dist: azure-identity (>=1.7,<1.8) ; extra == "azure"
20
18
  Requires-Dist: dataclasses-json (>=0.6.0,<0.7.0)
21
19
  Requires-Dist: httpx (>=0.27.0,<0.28.0) ; extra == "nexus"
@@ -1,5 +1,4 @@
1
- esd_services_api_client/__init__.py,sha256=4LskDwFuAFMOjHtN3_-71G_VZ4MNfjMJ7wX2cHYxV-0,648
2
- esd_services_api_client/_version.py,sha256=FrmlYBMHa48XHRqBIZUWCZDO-FJfblJzIeg6CSTLDmE,33
1
+ esd_services_api_client/__init__.py,sha256=FJBUxZX7h17fr_sUs01bd-fSxy6eQ6zLaqD-pb5bvRo,648
3
2
  esd_services_api_client/beast/__init__.py,sha256=zNhXcHSP5w4P9quM1XP4oXVJEccvC_VScG41TZ0GzZ8,723
4
3
  esd_services_api_client/beast/v3/__init__.py,sha256=FtumtInoDyCCRE424Llqv8QZLRuwXzj-smyfu1od1nc,754
5
4
  esd_services_api_client/beast/v3/_connector.py,sha256=VqxiCzJWKERh42aZAIphzmOEG5cdOcKM0DQzG7eQ_-8,11479
@@ -8,19 +7,19 @@ esd_services_api_client/boxer/README.md,sha256=-MAhYUPvmEMcgx_lo_2PlH_gZI1lndGv8
8
7
  esd_services_api_client/boxer/__init__.py,sha256=yDEcfL-9q0H91UWr-al-1iMJtVLv-oIXky6hUmFZs0g,785
9
8
  esd_services_api_client/boxer/_auth.py,sha256=q9vU4agH-s6HPpVTEdkXFA_RvO92hogOfjurfjHBmBg,7445
10
9
  esd_services_api_client/boxer/_base.py,sha256=LMKDArELZlWVKJH10coUFSSN8MFH6KfHCBncEDjsiIU,981
11
- esd_services_api_client/boxer/_connector.py,sha256=gUplRNAxcOoZfMPee0ZUJmhbzYmreys9cMeIMHmIyKM,8677
10
+ esd_services_api_client/boxer/_connector.py,sha256=UsZnAUSXT9BeUAU8eoezEaADrqz8ab-jSp4MVa-e3eM,8716
12
11
  esd_services_api_client/boxer/_models.py,sha256=ursQIR_c9jcVfRKc0LH1OuVL2KFD6kqojyGBadRfRPI,1702
13
12
  esd_services_api_client/common/__init__.py,sha256=L-cEW1mVbnTJLCLG5V6Ucw7zBgx1zf0t1bYcQC1heyw,603
14
13
  esd_services_api_client/crystal/__init__.py,sha256=oeyJjdQ9EpTnIq6XnjPq5v0DWPdHqi4uEfRIcD1mNZA,792
15
14
  esd_services_api_client/crystal/_api_versions.py,sha256=GHbmV_5lP9fP72TZE0j_ZeQSeJjMRcRaBRxNJbz-MWQ,837
16
15
  esd_services_api_client/crystal/_connector.py,sha256=0CqBpPahozAnentM6ZZrH84s_D7SoWCShr5_cRQGMX8,13110
17
16
  esd_services_api_client/crystal/_models.py,sha256=j8SEbwp_iAKjn06i-0f8npmhQhs2YJlmQ3eHwc2TwQE,4366
18
- esd_services_api_client/nexus/README.md,sha256=2-o9TeOYsVlUm72LsI6HUVaVx6ndYblRVDE7ncosYNQ,10032
17
+ esd_services_api_client/nexus/README.md,sha256=hNFV_fzAGrG6_1yXE3o_GuLTKIWEia2FfedMh-Sg0ew,10619
19
18
  esd_services_api_client/nexus/__init__.py,sha256=sOgKKq3_LZGbLmQMtMS7lDw2hv027qownTmNIRV0BB8,627
20
19
  esd_services_api_client/nexus/abstractions/__init__.py,sha256=sOgKKq3_LZGbLmQMtMS7lDw2hv027qownTmNIRV0BB8,627
21
20
  esd_services_api_client/nexus/abstractions/algrorithm_cache.py,sha256=6GevJJ7mf1c_PImhKQ_4_6n652VyHlgK_12LNidirxs,3644
22
21
  esd_services_api_client/nexus/abstractions/input_object.py,sha256=RUKnhekuZwd_RVvnLGAxHa4wYDFJf6wEwWQI9f-o0lM,1761
23
- esd_services_api_client/nexus/abstractions/logger_factory.py,sha256=9biONvCqNrP__yrmeRkoDL05TMA5v-LyrcKwgiKG59U,2019
22
+ esd_services_api_client/nexus/abstractions/logger_factory.py,sha256=oJStrOPir8J18E3ALhUTCQrj3rbjo2yuYrnjpDwLQg8,3947
24
23
  esd_services_api_client/nexus/abstractions/nexus_object.py,sha256=rLE42imCVGE6Px4Yu6X6C4b69gA1grK-7Md_SuCLN2Q,3115
25
24
  esd_services_api_client/nexus/abstractions/socket_provider.py,sha256=Rwa_aPErI4Es5AdyCd3EoGze7mg2D70u8kuc2UGEBaI,1729
26
25
  esd_services_api_client/nexus/algorithms/__init__.py,sha256=v4rPDf36r6AaHi_3K8isBKYU_fG8ct3w14KpUg2XRgg,976
@@ -33,8 +32,8 @@ esd_services_api_client/nexus/algorithms/recursive.py,sha256=uaCCl4q-st_KqbcmkdO
33
32
  esd_services_api_client/nexus/configurations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
33
  esd_services_api_client/nexus/configurations/algorithm_configuration.py,sha256=eE7diX2PATCGkmqhvFOcZwXrr6vns4fqnJGmgNvhhZM,1091
35
34
  esd_services_api_client/nexus/core/__init__.py,sha256=sOgKKq3_LZGbLmQMtMS7lDw2hv027qownTmNIRV0BB8,627
36
- esd_services_api_client/nexus/core/app_core.py,sha256=SNKcD0nOXdq1P_9T2-aQr1mZZ2qApRlf6i40DW_8iq0,12811
37
- esd_services_api_client/nexus/core/app_dependencies.py,sha256=tA18Smbiv1HjgXnpCHnigrR2mTmIeZawPKxMH0pezIU,8615
35
+ esd_services_api_client/nexus/core/app_core.py,sha256=Lmkpq7Hy74EfMOi5vtjD82PpY7Lb84RVbXN5b82BxKs,15462
36
+ esd_services_api_client/nexus/core/app_dependencies.py,sha256=1m7Oc9JCXyrU0qVZekYhpbXLQo20aQPQ-Bf8zEdjtqI,8704
38
37
  esd_services_api_client/nexus/core/serializers.py,sha256=Vk9FaEeDHXx3S7rPlYoWzsOcN6gzLzemsrjq6ytfaI0,2217
39
38
  esd_services_api_client/nexus/exceptions/__init__.py,sha256=feN33VdqB5-2bD9aJesJl_OlsKrNNo3hZCnQgKuaU9k,696
40
39
  esd_services_api_client/nexus/exceptions/_nexus_error.py,sha256=QvtY38mNoIA6t26dUN6UIsaPfljhtVNsbQVS7ksMb-Q,895
@@ -51,7 +50,7 @@ esd_services_api_client/nexus/modules/mlflow_module.py,sha256=d4y8XetGF37md4dEpE
51
50
  esd_services_api_client/nexus/telemetry/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
51
  esd_services_api_client/nexus/telemetry/recorder.py,sha256=-shxk2vYDTafJ0U3CzkHxIHBQtxVJ1ZNI4ST0p1YV2g,4801
53
52
  esd_services_api_client/nexus/telemetry/user_telemetry_recorder.py,sha256=NgnjSY64nEx1kslkdomENC6vMqkEOpfXggJXwm-NyFs,5163
54
- esd_services_api_client-2.5.14a148.dev5.dist-info/LICENSE,sha256=0gS6zXsPp8qZhzi1xaGCIYPzb_0e8on7HCeFJe8fOpw,10693
55
- esd_services_api_client-2.5.14a148.dev5.dist-info/METADATA,sha256=PCgeW72rd26I9ZuEXh2kaTO8hW7RGtU414USNQg1d5w,1174
56
- esd_services_api_client-2.5.14a148.dev5.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
57
- esd_services_api_client-2.5.14a148.dev5.dist-info/RECORD,,
53
+ esd_services_api_client-2.6.1.dist-info/LICENSE,sha256=0gS6zXsPp8qZhzi1xaGCIYPzb_0e8on7HCeFJe8fOpw,10693
54
+ esd_services_api_client-2.6.1.dist-info/METADATA,sha256=Y893K15f-VzKzAKxxs66BGwf8sCkGvMHe0hm_T3VL6Y,1058
55
+ esd_services_api_client-2.6.1.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
56
+ esd_services_api_client-2.6.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.1
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1 +0,0 @@
1
- __version__ = 'v2.5.14a148.dev5'