digitalhub 0.8.0b15__py3-none-any.whl → 0.8.1__py3-none-any.whl

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

Potentially problematic release.


This version of digitalhub might be problematic. Click here for more details.

@@ -5,13 +5,14 @@ import json
5
5
  import os
6
6
  import typing
7
7
  from urllib.parse import urlparse
8
+ from warnings import warn
8
9
 
9
- from dotenv import load_dotenv, set_key
10
+ from dotenv import get_key, set_key
10
11
  from requests import request
11
12
  from requests.exceptions import HTTPError, JSONDecodeError, RequestException
12
13
 
13
14
  from digitalhub.client._base.client import Client
14
- from digitalhub.client.dhcore.env import ENV_FILE, FALLBACK_USER, MAX_API_LEVEL, MIN_API_LEVEL
15
+ from digitalhub.client.dhcore.env import ENV_FILE, FALLBACK_USER, MAX_API_LEVEL, MIN_API_LEVEL, LIB_VERSION
15
16
  from digitalhub.client.dhcore.models import BasicAuth, OAuth2TokenAuth
16
17
  from digitalhub.utils.exceptions import (
17
18
  BackendError,
@@ -332,6 +333,8 @@ class ClientDHCore(Client):
332
333
  core_api_level = int(response.headers["X-Api-Level"])
333
334
  if not (MIN_API_LEVEL <= core_api_level <= MAX_API_LEVEL):
334
335
  raise BackendError("Backend API level not supported.")
336
+ if LIB_VERSION < core_api_level:
337
+ warn("Backend API level is higher than library version. You should consider updating the library.")
335
338
 
336
339
  def _raise_for_error(self, response: Response) -> None:
337
340
  """
@@ -462,8 +465,6 @@ class ClientDHCore(Client):
462
465
  -------
463
466
  None
464
467
  """
465
- # Load env from file
466
- self._load_env()
467
468
 
468
469
  self._get_endpoints_from_env()
469
470
 
@@ -487,7 +488,8 @@ class ClientDHCore(Client):
487
488
  self._get_auth_from_env()
488
489
 
489
490
  # Propagate access and refresh token to env file
490
- self._write_env()
491
+ if not ENV_FILE.exists():
492
+ self._write_env()
491
493
 
492
494
  def _get_endpoints_from_env(self) -> None:
493
495
  """
@@ -563,11 +565,21 @@ class ClientDHCore(Client):
563
565
  url = self._get_refresh_endpoint()
564
566
 
565
567
  # Call refresh token endpoint
566
- response = self._call_refresh_token_endpoint(url)
568
+ # Try token from env
569
+ refresh_token = os.getenv("DHCORE_REFRESH_TOKEN")
570
+ response = self._call_refresh_token_endpoint(url, refresh_token)
571
+
572
+ # Otherwise try token from file
573
+ if response.status_code in (400, 401, 403):
574
+ refresh_token = get_key(ENV_FILE, "DHCORE_REFRESH_TOKEN")
575
+ response = self._call_refresh_token_endpoint(url, refresh_token)
576
+
577
+ response.raise_for_status()
578
+ dict_response = response.json()
567
579
 
568
580
  # Read new access token and refresh token
569
- self._access_token = response["access_token"]
570
- self._refresh_token = response["refresh_token"]
581
+ self._access_token = dict_response["access_token"]
582
+ self._refresh_token = dict_response["refresh_token"]
571
583
 
572
584
  # Propagate new access token to env
573
585
  self._write_env()
@@ -593,7 +605,7 @@ class ClientDHCore(Client):
593
605
  self._raise_for_error(r)
594
606
  return r.json().get("token_endpoint")
595
607
 
596
- def _call_refresh_token_endpoint(self, url: str) -> dict:
608
+ def _call_refresh_token_endpoint(self, url: str, refresh_token: str) -> Response:
597
609
  """
598
610
  Call the refresh token endpoint.
599
611
 
@@ -601,17 +613,14 @@ class ClientDHCore(Client):
601
613
  ----------
602
614
  url : str
603
615
  Refresh token endpoint.
616
+ refresh_token : str
617
+ Refresh token.
604
618
 
605
619
  Returns
606
620
  -------
607
- dict
621
+ Response
608
622
  Response object.
609
623
  """
610
- # Get refersh token from .core file to avoid concurrency
611
- # in a shared workspace
612
- self._load_env()
613
- refresh_token = os.getenv("DHCORE_REFRESH_TOKEN")
614
-
615
624
  # Send request to get new access token
616
625
  payload = {
617
626
  "grant_type": "refresh_token",
@@ -619,20 +628,7 @@ class ClientDHCore(Client):
619
628
  "refresh_token": refresh_token,
620
629
  }
621
630
  headers = {"Content-Type": "application/x-www-form-urlencoded"}
622
- r = request("POST", url, data=payload, headers=headers, timeout=60)
623
- self._raise_for_error(r)
624
- return r.json()
625
-
626
- @staticmethod
627
- def _load_env() -> None:
628
- """
629
- Load the env variables from the .dhcore file.
630
-
631
- Returns
632
- -------
633
- None
634
- """
635
- load_dotenv(dotenv_path=ENV_FILE, override=True)
631
+ return request("POST", url, data=payload, headers=headers, timeout=60)
636
632
 
637
633
  def _write_env(self) -> None:
638
634
  """
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import os
4
+ from pathlib import Path
4
5
 
5
6
  # Use env user as fallback in the API calls
6
7
  try:
@@ -13,9 +14,10 @@ except Exception:
13
14
  # but refresh token is only available once. Is it's used, we cannot
14
15
  # overwrite it with coder, so we need to store the new one in a file,
15
16
  # preserved for jupyter restart
16
- ENV_FILE = ".dhcore"
17
+ ENV_FILE = Path.home() / ".dhcore"
17
18
 
18
19
 
19
20
  # API levels that are supported
20
21
  MAX_API_LEVEL = 20
21
22
  MIN_API_LEVEL = 8
23
+ LIB_VERSION = 8
@@ -23,4 +23,4 @@ def build_uuid(uuid: str | None = None) -> str:
23
23
  if slugify_string(uuid) != uuid:
24
24
  raise ValueError(f"Invalid ID: {uuid}. Must pass slugified ID.")
25
25
  return uuid
26
- return str(uuid4())
26
+ return uuid4().hex
@@ -159,6 +159,8 @@ def import_project(
159
159
  # Import related entities
160
160
  obj._import_entities(dict_obj)
161
161
 
162
+ obj.refresh()
163
+
162
164
  return obj
163
165
 
164
166
 
@@ -284,22 +284,21 @@ class S3Store(Store):
284
284
  """
285
285
  client, bucket = self._check_factory()
286
286
 
287
+ # Get list of files
287
288
  src_pth = Path(src)
288
289
  files = [i for i in src_pth.rglob("*") if i.is_file()]
290
+
291
+ # Build keys
289
292
  keys = []
290
293
  for i in files:
291
- if src_pth.is_absolute():
292
- i = i.relative_to(src_pth)
294
+ i = i.relative_to(src_pth)
293
295
  keys.append(f"{dst}{i}")
294
296
 
295
297
  # Upload files
296
298
  paths = []
297
- for i in zip(files, keys):
298
- f, k = i
299
+ for f, k in zip(files, keys):
299
300
  self._upload_file(f, k, client, bucket)
300
- if src_pth.is_absolute():
301
- f = f.relative_to(src_pth)
302
- paths.append((k, str(f)))
301
+ paths.append((k, str(f.relative_to(src_pth))))
303
302
  return paths
304
303
 
305
304
  def _upload_file_list(self, src: list[str], dst: str) -> list[tuple[str, str]]:
@@ -328,8 +327,7 @@ class S3Store(Store):
328
327
 
329
328
  # Upload files
330
329
  paths = []
331
- for i in zip(files, keys):
332
- f, k = i
330
+ for f, k in zip(files, keys):
333
331
  self._upload_file(f, k, client, bucket)
334
332
  paths.append((k, Path(f).name))
335
333
  return paths
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: digitalhub
3
- Version: 0.8.0b15
3
+ Version: 0.8.1
4
4
  Summary: Python SDK for Digitalhub
5
5
  Author-email: Fondazione Bruno Kessler <dslab@fbk.eu>, Matteo Martini <mmartini@fbk.eu>
6
- License: Apache License
6
+ License: Apache License
7
7
  Version 2.0, January 2004
8
8
  http://www.apache.org/licenses/
9
9
 
@@ -240,6 +240,13 @@ Requires-Dist: python-dotenv
240
240
  Requires-Dist: GitPython>=3
241
241
  Requires-Dist: psycopg2-binary
242
242
  Requires-Dist: python-slugify
243
+ Provides-Extra: full
244
+ Requires-Dist: pandas<2.2,>=1.2; extra == "full"
245
+ Requires-Dist: mlflow; extra == "full"
246
+ Provides-Extra: pandas
247
+ Requires-Dist: pandas<2.2,>=1.2; extra == "pandas"
248
+ Provides-Extra: mlflow
249
+ Requires-Dist: mlflow; extra == "mlflow"
243
250
  Provides-Extra: dev
244
251
  Requires-Dist: black; extra == "dev"
245
252
  Requires-Dist: pytest; extra == "dev"
@@ -250,13 +257,6 @@ Provides-Extra: docs
250
257
  Requires-Dist: Sphinx>=7; extra == "docs"
251
258
  Requires-Dist: pydata-sphinx-theme>=0.15; extra == "docs"
252
259
  Requires-Dist: numpydoc>=1.6; extra == "docs"
253
- Provides-Extra: full
254
- Requires-Dist: pandas<2.2,>=1.2; extra == "full"
255
- Requires-Dist: mlflow; extra == "full"
256
- Provides-Extra: mlflow
257
- Requires-Dist: mlflow; extra == "mlflow"
258
- Provides-Extra: pandas
259
- Requires-Dist: pandas<2.2,>=1.2; extra == "pandas"
260
260
 
261
261
  # Digitalhub Library
262
262
 
@@ -5,8 +5,8 @@ digitalhub/client/builder.py,sha256=83PoMCus4s4nbkoWmvcjW2hIpXbNx74sUW93wgQgbuo,
5
5
  digitalhub/client/_base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  digitalhub/client/_base/client.py,sha256=HDv9Vr9DZpoaZVsAT5SSBD9j1oHoVuxA4ILGDl0mBz4,1299
7
7
  digitalhub/client/dhcore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- digitalhub/client/dhcore/client.py,sha256=eh-IQu72Kz4K82uUlMRtatQAQNymvOCMJZZPjB9TdqQ,19169
9
- digitalhub/client/dhcore/env.py,sha256=F5A5dPTliwd4UUbpw7hQQ3hoVjZYjcVF8MbniTuTFHE,563
8
+ digitalhub/client/dhcore/client.py,sha256=qzZaM0y5wxXkp7aTMbAGWyrXIulGwtrzpVx2ZtnZTZo,19397
9
+ digitalhub/client/dhcore/env.py,sha256=5IsPR4SG0lg2TkqgW4vhHvThieuWVOZyZsBodWH6kKs,618
10
10
  digitalhub/client/dhcore/models.py,sha256=KiTg5xR8EzI7Xa1pmYmzixabLdnqlnn5kn-IILZDGIw,900
11
11
  digitalhub/client/dhcore/utils.py,sha256=TaLjA3LT6heKpPclmufZx-kZKZNOe4OzS_Jtpj2S5wY,2990
12
12
  digitalhub/client/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -48,7 +48,7 @@ digitalhub/entities/_base/entity/_constructors/metadata.py,sha256=IGB1l6EJ1xlnGM
48
48
  digitalhub/entities/_base/entity/_constructors/name.py,sha256=sNU54TzzdYug5sqio8uaus6pP5RkEJYIEl6j0fwR4ho,485
49
49
  digitalhub/entities/_base/entity/_constructors/spec.py,sha256=ymUHuJ6m3B8eVL4622XRdNMQdeYxRwBV5drao0L5MiQ,879
50
50
  digitalhub/entities/_base/entity/_constructors/status.py,sha256=xrr2u2wlDMmlqrUIV9xVqFRHfn5LV_TqzdrCEWNCzE0,1132
51
- digitalhub/entities/_base/entity/_constructors/uuid.py,sha256=8wys6Uhk8L1uUo18moh7Rq5YnFHtmUVXfNOkcsTVUN8,556
51
+ digitalhub/entities/_base/entity/_constructors/uuid.py,sha256=QzG0nsVpGU2UDD5CjpkOM2RfVaCHPdLp2HoQt8TM_tk,555
52
52
  digitalhub/entities/_base/executable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  digitalhub/entities/_base/executable/entity.py,sha256=NJCb82RAp9f_KERdCPQYev39WxchlicY6gnEi1P2QTg,10075
54
54
  digitalhub/entities/_base/material/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -136,7 +136,7 @@ digitalhub/entities/model/sklearn/entity.py,sha256=pPy4mOqOmbkqNkKFUnhrsIQNt2mGN
136
136
  digitalhub/entities/model/sklearn/spec.py,sha256=Md0aKlfNHZ2fhZbJgp9wZxF0Hu6XIkcniQHCgwoRdkk,301
137
137
  digitalhub/entities/model/sklearn/status.py,sha256=eqkPPtERX-6_BjPb_GD8j1FIeavpl43k-dfXZGqzGI0,187
138
138
  digitalhub/entities/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
- digitalhub/entities/project/crud.py,sha256=P2IhKR2-YNmiNy0rpu0PG-LKD9nJGKsAahxvhsovmJA,8971
139
+ digitalhub/entities/project/crud.py,sha256=z2UhAESn8nmZf6nF6KnTQClUyNjO1LCG04OJucNGJfs,8990
140
140
  digitalhub/entities/project/_base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
141
  digitalhub/entities/project/_base/builder.py,sha256=Fx_p8M75SkE_ssVBvKGu45wwqwqAZ5N6l6UZZj9LSNc,3612
142
142
  digitalhub/entities/project/_base/entity.py,sha256=CA3MqkwJlvnoI0shUIqsf-SsOoTZUA4Z41wnn0jbT5c,53552
@@ -202,7 +202,7 @@ digitalhub/stores/local/store.py,sha256=KjJ8OG6vfNrckMWbkbEA8KDM6b0Ds0Ed3fwxvTnG
202
202
  digitalhub/stores/remote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
203
  digitalhub/stores/remote/store.py,sha256=MBsotmc5Zk-eT5vgAufnYyR2xJmQvgBR28u3bhaSJtM,3615
204
204
  digitalhub/stores/s3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
- digitalhub/stores/s3/store.py,sha256=dS0TumNf3tDkpVcn_0_kp-ERogP3w87tEa-osIU11AQ,15515
205
+ digitalhub/stores/s3/store.py,sha256=MFP0zCVWXpgg13cz2BB40R5TFeOl0GcxO0rycAYTqIY,15427
206
206
  digitalhub/stores/sql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
207
207
  digitalhub/stores/sql/store.py,sha256=NdELCkP2Rl5ewiRuI4J9eRvTiBzVmpF0cMowZ1NME_8,8654
208
208
  digitalhub/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -224,8 +224,8 @@ test/local/CRUD/test_artifacts.py,sha256=Y3J_C7SDRSsQd2SGIZjPIOvyTL92B1sTFrUONG3
224
224
  test/local/CRUD/test_dataitems.py,sha256=LQqTzI59uwTGy4zoq8jL0yWVe2W9vXlatkgDU9aB6xg,2968
225
225
  test/local/CRUD/test_models.py,sha256=msosbZuRwIMbZtmi3ZaOva4TjQ4lrzkNu9AguIFhrSo,2929
226
226
  test/local/imports/test_imports.py,sha256=W-YugO0rpJwvtWp57MXaXfEmE-f5iWuCiLY-n0ZU4z8,1271
227
- digitalhub-0.8.0b15.dist-info/LICENSE.txt,sha256=_yVOtnbW7Ss28mp058UEEc1X4Rgj8-kQBP_kj8_Sc88,11585
228
- digitalhub-0.8.0b15.dist-info/METADATA,sha256=nv71Q9Q1Ni-cZ3_fVQ4_T1q29zC0nvaOaViNCL19Xes,15289
229
- digitalhub-0.8.0b15.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
230
- digitalhub-0.8.0b15.dist-info/top_level.txt,sha256=ae9pDfCF27ZoaVAxuBKONMP0lm5P-N_I-e-no1WlvD8,16
231
- digitalhub-0.8.0b15.dist-info/RECORD,,
227
+ digitalhub-0.8.1.dist-info/LICENSE.txt,sha256=_yVOtnbW7Ss28mp058UEEc1X4Rgj8-kQBP_kj8_Sc88,11585
228
+ digitalhub-0.8.1.dist-info/METADATA,sha256=1-dYS0X78aKXA0SvnWJF-AhbFOItvrU8P7AahsxqJY0,15316
229
+ digitalhub-0.8.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
230
+ digitalhub-0.8.1.dist-info/top_level.txt,sha256=ae9pDfCF27ZoaVAxuBKONMP0lm5P-N_I-e-no1WlvD8,16
231
+ digitalhub-0.8.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5