digitalhub 0.13.0b1__py3-none-any.whl → 0.13.0b3__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 (53) hide show
  1. digitalhub/__init__.py +1 -1
  2. digitalhub/context/api.py +5 -5
  3. digitalhub/context/builder.py +3 -5
  4. digitalhub/context/context.py +9 -1
  5. digitalhub/entities/_base/material/entity.py +3 -3
  6. digitalhub/entities/dataitem/crud.py +10 -2
  7. digitalhub/entities/dataitem/table/entity.py +3 -3
  8. digitalhub/entities/dataitem/utils.py +1 -2
  9. digitalhub/entities/task/_base/models.py +12 -3
  10. digitalhub/factory/factory.py +25 -3
  11. digitalhub/factory/utils.py +11 -3
  12. digitalhub/runtimes/_base.py +1 -1
  13. digitalhub/runtimes/builder.py +18 -1
  14. digitalhub/stores/client/__init__.py +12 -0
  15. digitalhub/stores/client/_base/api_builder.py +14 -0
  16. digitalhub/stores/client/_base/client.py +93 -0
  17. digitalhub/stores/client/_base/key_builder.py +28 -0
  18. digitalhub/stores/client/_base/params_builder.py +14 -0
  19. digitalhub/stores/client/api.py +10 -5
  20. digitalhub/stores/client/builder.py +3 -1
  21. digitalhub/stores/client/dhcore/api_builder.py +17 -0
  22. digitalhub/stores/client/dhcore/client.py +276 -58
  23. digitalhub/stores/client/dhcore/configurator.py +336 -141
  24. digitalhub/stores/client/dhcore/error_parser.py +35 -1
  25. digitalhub/stores/client/dhcore/params_builder.py +113 -17
  26. digitalhub/stores/client/dhcore/utils.py +32 -14
  27. digitalhub/stores/client/local/api_builder.py +17 -0
  28. digitalhub/stores/client/local/client.py +6 -8
  29. digitalhub/stores/credentials/api.py +8 -8
  30. digitalhub/stores/credentials/configurator.py +176 -3
  31. digitalhub/stores/credentials/enums.py +16 -3
  32. digitalhub/stores/credentials/handler.py +73 -45
  33. digitalhub/stores/credentials/ini_module.py +59 -27
  34. digitalhub/stores/credentials/store.py +33 -1
  35. digitalhub/stores/data/_base/store.py +8 -3
  36. digitalhub/stores/data/api.py +20 -16
  37. digitalhub/stores/data/builder.py +3 -9
  38. digitalhub/stores/data/s3/configurator.py +64 -23
  39. digitalhub/stores/data/s3/store.py +30 -27
  40. digitalhub/stores/data/s3/utils.py +9 -9
  41. digitalhub/stores/data/sql/configurator.py +23 -22
  42. digitalhub/stores/data/sql/store.py +14 -16
  43. digitalhub/utils/exceptions.py +6 -0
  44. digitalhub/utils/file_utils.py +53 -30
  45. digitalhub/utils/generic_utils.py +41 -33
  46. digitalhub/utils/git_utils.py +24 -14
  47. digitalhub/utils/io_utils.py +19 -18
  48. digitalhub/utils/uri_utils.py +31 -31
  49. {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/METADATA +1 -1
  50. {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/RECORD +53 -53
  51. {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/WHEEL +0 -0
  52. {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/licenses/AUTHORS +0 -0
  53. {digitalhub-0.13.0b1.dist-info → digitalhub-0.13.0b3.dist-info}/licenses/LICENSE +0 -0
@@ -7,104 +7,132 @@ from __future__ import annotations
7
7
  import os
8
8
 
9
9
  from digitalhub.stores.credentials.enums import SetCreds
10
- from digitalhub.stores.credentials.ini_module import load_from_file, read_env_from_file, set_current_env, write_config
10
+ from digitalhub.stores.credentials.ini_module import (
11
+ load_file,
12
+ load_key,
13
+ load_profile,
14
+ set_current_profile,
15
+ write_config,
16
+ )
11
17
  from digitalhub.stores.credentials.store import CredentialsStore
12
18
 
13
19
 
14
20
  class CredentialHandler:
15
21
  """
16
- Configurator object used to configure clients and store credentials.
22
+ Handler for configuring clients and managing credentials.
23
+
24
+ Attributes
25
+ ----------
26
+ _creds_store : CredentialsStore
27
+ Store for credentials.
28
+ _profile : str
29
+ Current credentials profile name.
17
30
  """
18
31
 
19
32
  def __init__(self) -> None:
20
- # Store
21
33
  self._creds_store = CredentialsStore()
34
+ self._profile = self._read_current_profile()
22
35
 
23
- # Current credentials set (__default by default)
24
- self._environment = os.getenv(SetCreds.DH_ENV.value, SetCreds.DEFAULT.value)
36
+ @staticmethod
37
+ def _read_current_profile() -> str:
38
+ """
39
+ Read the current credentials profile name.
40
+
41
+ Returns
42
+ -------
43
+ str
44
+ Name of the credentials profile.
45
+ """
46
+ profile = os.getenv(SetCreds.DH_PROFILE.value)
47
+ if profile is not None:
48
+ return profile
49
+ file = load_file()
50
+ profile = load_profile(file)
51
+ if profile is not None:
52
+ return profile
53
+ return SetCreds.DEFAULT.value
25
54
 
26
55
  ##############################
27
56
  # Public methods
28
57
  ##############################
29
58
 
30
- def set_current_env(self, creds_set: str) -> None:
59
+ def set_current_profile(self, creds_set: str) -> None:
31
60
  """
32
- Set the current credentials set.
61
+ Set the current credentials profile name.
33
62
 
34
63
  Parameters
35
64
  ----------
36
65
  creds_set : str
37
- Credentials set name.
66
+ Name of the credentials profile to set.
38
67
 
39
68
  Returns
40
69
  -------
41
70
  None
42
71
  """
43
- self._environment = creds_set
44
- set_current_env(creds_set)
72
+ self._profile = creds_set
73
+ set_current_profile(creds_set)
45
74
 
46
- def get_current_env(self) -> str:
75
+ def get_current_profile(self) -> str:
47
76
  """
48
- Get the current credentials set.
77
+ Get the current credentials profile name.
49
78
 
50
79
  Returns
51
80
  -------
52
81
  str
53
- Credentials set name.
82
+ Name of the current credentials profile.
54
83
  """
55
- return self._environment
84
+ return self._profile
56
85
 
57
- def load_from_env(self, var: str) -> str | None:
86
+ def load_from_env(self, vars: list[str]) -> dict:
58
87
  """
59
- Load variable from env.
88
+ Load variables from environment.
60
89
 
61
90
  Parameters
62
91
  ----------
63
- var : str
64
- Environment variable name.
92
+ vars : list of str
93
+ List of environment variable names to load.
65
94
 
66
95
  Returns
67
96
  -------
68
- str | None
69
- Environment variable value.
97
+ dict
98
+ Dictionary of environment variable values.
70
99
  """
71
- env_var = os.getenv(var)
72
- if env_var != "":
73
- return env_var
100
+ return {var: os.getenv(var) for var in vars}
74
101
 
75
- def load_from_file(self, var: str) -> str | None:
102
+ def load_from_file(self, vars: list[str]) -> dict:
76
103
  """
77
- Load variable from config file.
104
+ Load variables from credentials config file.
78
105
 
79
106
  Parameters
80
107
  ----------
81
- var : str
82
- Environment variable name.
108
+ vars : list of str
109
+ List of variable names to load from file.
83
110
 
84
111
  Returns
85
112
  -------
86
- str | None
87
- Environment variable value.
113
+ dict
114
+ Dictionary of variable values from file.
88
115
  """
89
- env_from_file = read_env_from_file()
90
- if env_from_file is not None:
91
- self._environment = env_from_file
92
- return load_from_file(var)
116
+ file = load_file()
117
+ profile = load_profile(file)
118
+ if profile is not None:
119
+ self._profile = profile
120
+ return {var: load_key(file, self._profile, var) for var in vars}
93
121
 
94
122
  def write_env(self, creds: dict) -> None:
95
123
  """
96
- Write the env variables to the .dhcore file.
124
+ Write credentials to the .dhcore file for the current profile.
97
125
 
98
126
  Parameters
99
127
  ----------
100
128
  creds : dict
101
- Credentials.
129
+ Credentials to write.
102
130
 
103
131
  Returns
104
132
  -------
105
133
  None
106
134
  """
107
- write_config(creds, self._environment)
135
+ write_config(creds, self._profile)
108
136
 
109
137
  ##############################
110
138
  # Credentials store methods
@@ -112,37 +140,37 @@ class CredentialHandler:
112
140
 
113
141
  def set_credentials(self, origin: str, creds: dict) -> None:
114
142
  """
115
- Set credentials.
143
+ Set credentials for the current profile and origin.
116
144
 
117
145
  Parameters
118
146
  ----------
119
147
  origin : str
120
- The origin of the credentials.
148
+ The origin of the credentials ('env' or 'file').
121
149
  creds : dict
122
- The credentials.
150
+ Credentials to set.
123
151
 
124
152
  Returns
125
153
  -------
126
154
  None
127
155
  """
128
- self._creds_store.set_credentials(self._environment, origin, creds)
156
+ self._creds_store.set_credentials(self._profile, origin, creds)
129
157
 
130
158
  def get_credentials(self, origin: str) -> dict:
131
159
  """
132
- Get credentials from origin.
160
+ Get credentials for the current profile from the specified origin.
133
161
 
134
162
  Parameters
135
163
  ----------
136
164
  origin : str
137
- The origin of the credentials.
165
+ The origin to get credentials from ('env' or 'file').
138
166
 
139
167
  Returns
140
168
  -------
141
169
  dict
142
- The credentials.
170
+ Dictionary of credentials.
143
171
  """
144
- return self._creds_store.get_credentials(self._environment, origin)
172
+ return self._creds_store.get_credentials(self._profile, origin)
145
173
 
146
174
 
147
- # Define global configurator
175
+ # Define global credential handler
148
176
  creds_handler = CredentialHandler()
@@ -9,22 +9,23 @@ from pathlib import Path
9
9
 
10
10
  from digitalhub.utils.exceptions import ClientError
11
11
 
12
- # File where to write DHCORE_ACCESS_TOKEN and DHCORE_REFRESH_TOKEN
13
- # It's used because we inject the variables in jupyter env,
14
- # but refresh token is only available once. Is it's used, we cannot
15
- # overwrite it with coder, so we need to store the new one in a file,
16
- # preserved for jupyter restart
12
+ # File where to write credementials
17
13
  ENV_FILE = Path.home() / ".dhcore.ini"
18
14
 
19
15
 
20
16
  def load_file() -> ConfigParser:
21
17
  """
22
- Load current credentials set from the .dhcore.ini file.
18
+ Load the credentials configuration from the .dhcore.ini file.
23
19
 
24
20
  Returns
25
21
  -------
26
22
  ConfigParser
27
- Credentials set name.
23
+ Parsed configuration file object.
24
+
25
+ Raises
26
+ ------
27
+ ClientError
28
+ If the file cannot be read.
28
29
  """
29
30
  try:
30
31
  file = ConfigParser()
@@ -34,45 +35,71 @@ def load_file() -> ConfigParser:
34
35
  raise ClientError(f"Failed to read env file: {e}")
35
36
 
36
37
 
37
- def load_from_file(var: str) -> str | None:
38
+ def load_profile(file: ConfigParser) -> str | None:
38
39
  """
39
- Load variable from config file.
40
+ Load the current credentials profile name from the .dhcore.ini file.
40
41
 
41
42
  Parameters
42
43
  ----------
44
+ file : ConfigParser
45
+ Parsed configuration file object.
46
+
47
+ Returns
48
+ -------
49
+ str or None
50
+ Name of the credentials profile, or None if not found.
51
+ """
52
+ try:
53
+ return file["DEFAULT"]["current_environment"]
54
+ except KeyError:
55
+ return
56
+
57
+
58
+ def load_key(file: ConfigParser, profile: str, key: str) -> str | None:
59
+ """
60
+ Load a specific key value from the credentials profile in the
61
+ .dhcore.ini file.
62
+
63
+ Parameters
64
+ ----------
65
+ file : ConfigParser
66
+ Parsed configuration file object.
43
67
  profile : str
44
- Credentials set name.
45
- var : str
46
- Environment variable name.
68
+ Name of the credentials profile.
69
+ key : str
70
+ Name of the key to retrieve.
47
71
 
48
72
  Returns
49
73
  -------
50
- str | None
51
- Environment variable value.
74
+ str or None
75
+ Value of the key, or None if not found.
52
76
  """
53
77
  try:
54
- cfg = load_file()
55
- profile = cfg["DEFAULT"]["current_environment"]
56
- return cfg[profile].get(var)
78
+ return file[profile][key]
57
79
  except KeyError:
58
80
  return
59
81
 
60
82
 
61
83
  def write_config(creds: dict, environment: str) -> None:
62
84
  """
63
- Write the env variables to the .dhcore.ini file.
64
- It will overwrite any existing env variables.
85
+ Write credentials to the .dhcore.ini file for the specified environment.
86
+ Overwrites any existing values for that environment.
65
87
 
66
88
  Parameters
67
89
  ----------
68
90
  creds : dict
69
- Credentials.
91
+ Dictionary of credentials to write.
70
92
  environment : str
71
- Credentials set name.
93
+ Name of the credentials profile/environment.
72
94
 
73
95
  Returns
74
96
  -------
75
97
  None
98
+
99
+ Raises
100
+ ------
101
+ ClientError
102
+ If the file cannot be written.
76
103
  """
77
104
  try:
78
105
  cfg = load_file()
@@ -93,18 +120,23 @@ def write_config(creds: dict, environment: str) -> None:
93
120
  raise ClientError(f"Failed to write env file: {e}")
94
121
 
95
122
 
96
- def set_current_env(environment: str) -> None:
123
+ def set_current_profile(environment: str) -> None:
97
124
  """
98
- Set the current credentials set.
125
+ Set the current credentials profile in the .dhcore.ini file.
99
126
 
100
127
  Parameters
101
128
  ----------
102
129
  environment : str
103
- Credentials set name.
130
+ Name of the credentials profile to set as current.
104
131
 
105
132
  Returns
106
133
  -------
107
134
  None
135
+
136
+ Raises
137
+ ------
138
+ ClientError
139
+ If the file cannot be written.
108
140
  """
109
141
  try:
110
142
  cfg = load_file()
@@ -118,12 +150,12 @@ def set_current_env(environment: str) -> None:
118
150
 
119
151
  def read_env_from_file() -> str | None:
120
152
  """
121
- Read the current credentials set from the .dhcore.ini file.
153
+ Read the current credentials profile name from the .dhcore.ini file.
122
154
 
123
155
  Returns
124
156
  -------
125
- str
126
- Credentials set name.
157
+ str or None
158
+ Name of the current credentials profile, or None if not found.
127
159
  """
128
160
  try:
129
161
  cfg = load_file()
@@ -11,7 +11,14 @@ from digitalhub.stores.credentials.enums import CredsOrigin
11
11
 
12
12
  class CredentialsStore:
13
13
  """
14
- Credentials store to store and retrieve credentials.
14
+ Store and retrieve credentials for different profiles and origins.
15
+
16
+ Attributes
17
+ ----------
18
+ _file_creds : dict of str to dict
19
+ Credentials stored by profile from file origin.
20
+ _env_creds : dict of str to Any
21
+ Credentials stored from environment origin.
15
22
  """
16
23
 
17
24
  def __init__(self) -> None:
@@ -26,6 +33,19 @@ class CredentialsStore:
26
33
  ) -> None:
27
34
  """
28
35
  Set all credentials for a given profile and origin.
36
+
37
+ Parameters
38
+ ----------
39
+ profile : str
40
+ Name of the credentials profile.
41
+ origin : str
42
+ Origin of the credentials ('env' or 'file').
43
+ credentials : dict of str to Any
44
+ Dictionary of credentials to set.
45
+
46
+ Returns
47
+ -------
48
+ None
29
49
  """
30
50
  if origin == CredsOrigin.ENV.value:
31
51
  for key, value in credentials.items():
@@ -43,6 +63,18 @@ class CredentialsStore:
43
63
  ) -> dict[str, Any]:
44
64
  """
45
65
  Get all credentials for a given profile and origin.
66
+
67
+ Parameters
68
+ ----------
69
+ profile : str
70
+ Name of the credentials profile.
71
+ origin : str
72
+ Origin of the credentials ('env' or 'file').
73
+
74
+ Returns
75
+ -------
76
+ dict of str to Any
77
+ Dictionary of credentials for the profile and origin.
46
78
  """
47
79
  if origin == CredsOrigin.ENV.value:
48
80
  return self._env_creds
@@ -186,9 +186,14 @@ class Store:
186
186
  """
187
187
  if not isinstance(path, Path):
188
188
  path = Path(path)
189
- if path.suffix != "":
190
- path = path.parent
191
- path.mkdir(parents=True, exist_ok=True)
189
+ # If the path does not exist, we need to infer if it's a file or directory
190
+ if path.suffix and not path.name.startswith("."):
191
+ # Looks like a file, use parent
192
+ dir_path = path.parent
193
+ else:
194
+ # Looks like a directory (even if it contains dots)
195
+ dir_path = path
196
+ dir_path.mkdir(parents=True, exist_ok=True)
192
197
 
193
198
  @staticmethod
194
199
  def _build_temp() -> Path:
@@ -17,53 +17,57 @@ if typing.TYPE_CHECKING:
17
17
 
18
18
  def get_default_store(project: str) -> str:
19
19
  """
20
- Get default store URI.
20
+ Returns the default store URI for a given project.
21
21
 
22
22
  Parameters
23
23
  ----------
24
24
  project : str
25
- Project name.
25
+ The name of the project.
26
26
 
27
27
  Returns
28
28
  -------
29
29
  str
30
- Default store URI.
30
+ The default store URI.
31
+
32
+ Raises
33
+ ------
34
+ ValueError
35
+ If no default store is found.
31
36
  """
37
+ var = StoreEnv.DEFAULT_FILES_STORE.value
38
+
32
39
  context = get_context(project)
33
- store = context.config.get(StoreEnv.DEFAULT_FILES_STORE.value.lower())
40
+ store = context.config.get(var.lower())
34
41
  if store is not None:
35
42
  return store
36
43
 
37
- store = creds_handler.load_from_env(StoreEnv.DEFAULT_FILES_STORE.value)
44
+ store = creds_handler.load_from_env([var]).get(var)
38
45
  if store is None:
39
- store = creds_handler.load_from_file(StoreEnv.DEFAULT_FILES_STORE.value)
46
+ store = creds_handler.load_from_file([var]).get(var)
40
47
 
41
48
  if store is None or store == "":
42
49
  raise ValueError(
43
50
  "No default store found. "
44
51
  "Please set a default store "
45
- f"in your environment (e.g. export {StoreEnv.DEFAULT_FILES_STORE.value}=) "
52
+ f"in your environment (e.g. export {var}=) "
53
+ " in the .dhcore.ini file "
46
54
  "or set it in project config."
47
55
  )
48
56
  return store
49
57
 
50
58
 
51
- def get_store(project: str, uri: str) -> Store:
59
+ def get_store(uri: str) -> Store:
52
60
  """
53
- Get store instance by URI.
61
+ Returns a store instance for the given URI.
54
62
 
55
63
  Parameters
56
- ---------
57
- project : str
58
- Project name.
64
+ ----------
59
65
  uri : str
60
- URI to parse.
61
- config : dict
62
- Store configuration.
66
+ The URI to parse.
63
67
 
64
68
  Returns
65
69
  -------
66
70
  Store
67
- Store instance.
71
+ The store instance corresponding to the URI.
68
72
  """
69
73
  return store_builder.get(uri)
@@ -6,7 +6,6 @@ from __future__ import annotations
6
6
 
7
7
  import typing
8
8
 
9
- from digitalhub.stores.credentials.api import get_current_env
10
9
  from digitalhub.stores.data.local.store import LocalStore
11
10
  from digitalhub.stores.data.remote.store import RemoteStore
12
11
  from digitalhub.stores.data.s3.configurator import S3StoreConfigurator
@@ -61,15 +60,10 @@ class StoreBuilder:
61
60
  Store
62
61
  The store instance.
63
62
  """
64
- env_profile = get_current_env()
65
63
  store_type = map_uri_scheme(uri)
66
64
 
67
- # Ensure env exists in _instances
68
- if env_profile not in self._instances:
69
- self._instances[env_profile] = {}
70
-
71
65
  # Build the store instance if not already present
72
- if store_type not in self._instances[env_profile]:
66
+ if store_type not in self._instances:
73
67
  store_info = self._builders[store_type]
74
68
  store_cls = store_info._store
75
69
  cfgrt_cls = store_info._configurator
@@ -78,9 +72,9 @@ class StoreBuilder:
78
72
  store = store_cls()
79
73
  else:
80
74
  store = store_cls(cfgrt_cls())
81
- self._instances[env_profile][store_type] = store
75
+ self._instances[store_type] = store
82
76
 
83
- return self._instances[env_profile][store_type]
77
+ return self._instances[store_type]
84
78
 
85
79
 
86
80
  store_builder = StoreBuilder()
@@ -4,8 +4,11 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
+ from datetime import datetime, timezone
8
+
7
9
  from botocore.config import Config
8
10
 
11
+ from digitalhub.stores.client.dhcore.utils import refresh_token
9
12
  from digitalhub.stores.credentials.configurator import Configurator
10
13
  from digitalhub.stores.credentials.enums import CredsEnvVar
11
14
 
@@ -17,17 +20,19 @@ class S3StoreConfigurator(Configurator):
17
20
  """
18
21
 
19
22
  keys = [
20
- CredsEnvVar.S3_ENDPOINT_URL,
21
- CredsEnvVar.S3_ACCESS_KEY_ID,
22
- CredsEnvVar.S3_SECRET_ACCESS_KEY,
23
- CredsEnvVar.S3_REGION,
24
- CredsEnvVar.S3_SIGNATURE_VERSION,
25
- CredsEnvVar.S3_SESSION_TOKEN,
23
+ CredsEnvVar.S3_ENDPOINT_URL.value,
24
+ CredsEnvVar.S3_ACCESS_KEY_ID.value,
25
+ CredsEnvVar.S3_SECRET_ACCESS_KEY.value,
26
+ CredsEnvVar.S3_REGION.value,
27
+ CredsEnvVar.S3_SIGNATURE_VERSION.value,
28
+ CredsEnvVar.S3_SESSION_TOKEN.value,
29
+ CredsEnvVar.S3_PATH_STYLE.value,
30
+ CredsEnvVar.S3_CREDENTIALS_EXPIRATION.value,
26
31
  ]
27
32
  required_keys = [
28
- CredsEnvVar.S3_ENDPOINT_URL,
29
- CredsEnvVar.S3_ACCESS_KEY_ID,
30
- CredsEnvVar.S3_SECRET_ACCESS_KEY,
33
+ CredsEnvVar.S3_ENDPOINT_URL.value,
34
+ CredsEnvVar.S3_ACCESS_KEY_ID.value,
35
+ CredsEnvVar.S3_SECRET_ACCESS_KEY.value,
31
36
  ]
32
37
 
33
38
  def __init__(self):
@@ -38,30 +43,43 @@ class S3StoreConfigurator(Configurator):
38
43
  # Configuration methods
39
44
  ##############################
40
45
 
41
- def load_configs(self) -> None:
42
- # Load from env
43
- env_creds = {var.value: self._creds_handler.load_from_env(var.value) for var in self.keys}
46
+ def load_env_vars(self) -> None:
47
+ """
48
+ Loads the credentials from the environment variables.
49
+
50
+ Returns
51
+ -------
52
+ None
53
+ """
54
+ env_creds = self._creds_handler.load_from_env(self.keys)
44
55
  self._creds_handler.set_credentials(self._env, env_creds)
45
56
 
46
- # Load from file
47
- file_creds = {var.value: self._creds_handler.load_from_file(var.value) for var in self.keys}
48
- self._creds_handler.set_credentials(self._file, file_creds)
57
+ def load_file_vars(self) -> None:
58
+ """
59
+ Loads the credentials from a file.
49
60
 
50
- def get_client_config(self, origin: str) -> dict:
61
+ Returns
62
+ -------
63
+ None
51
64
  """
52
- Get S3 credentials (access key, secret key, session token and other config).
65
+ file_creds = self._creds_handler.load_from_file(self.keys)
66
+ self._creds_handler.set_credentials(self._file, file_creds)
53
67
 
54
- Parameters
55
- ----------
56
- origin : str
57
- The origin of the credentials.
68
+ def get_client_config(self) -> dict:
69
+ """
70
+ Gets S3 credentials (access key, secret key, session token, and other config).
58
71
 
59
72
  Returns
60
73
  -------
61
74
  dict
62
- The credentials.
75
+ Dictionary containing S3 credentials and configuration.
63
76
  """
64
- creds = self.get_credentials(origin)
77
+ creds = self.get_credentials(self._origin)
78
+ expired = creds[CredsEnvVar.S3_CREDENTIALS_EXPIRATION.value]
79
+ if self._origin == self._file and self._is_expired(expired):
80
+ refresh_token()
81
+ self.load_file_vars()
82
+ creds = self.get_credentials(self._origin)
65
83
  return {
66
84
  "endpoint_url": creds[CredsEnvVar.S3_ENDPOINT_URL.value],
67
85
  "aws_access_key_id": creds[CredsEnvVar.S3_ACCESS_KEY_ID.value],
@@ -72,3 +90,26 @@ class S3StoreConfigurator(Configurator):
72
90
  signature_version=creds[CredsEnvVar.S3_SIGNATURE_VERSION.value],
73
91
  ),
74
92
  }
93
+
94
+ @staticmethod
95
+ def _is_expired(timestamp: str | None) -> bool:
96
+ """
97
+ Determines whether a given timestamp is after the current UTC time.
98
+
99
+ Parameters
100
+ ----------
101
+ timestamp : str or None
102
+ Timestamp string in the format 'YYYY-MM-DDTHH:MM:SSZ'.
103
+
104
+ Returns
105
+ -------
106
+ bool
107
+ True if the given timestamp is later than the current UTC time,
108
+ otherwise False.
109
+ """
110
+ if timestamp is None:
111
+ return False
112
+ dt = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%SZ")
113
+ dt = dt.replace(tzinfo=timezone.utc)
114
+ now = datetime.now(timezone.utc) + datetime.timedelta(seconds=120)
115
+ return dt < now