dnastack-client-library 3.1.179__py3-none-any.whl → 3.1.205__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 (73) hide show
  1. dnastack/alpha/app/explorer.py +1 -1
  2. dnastack/alpha/app/workbench.py +4 -4
  3. dnastack/alpha/cli/wes.py +3 -3
  4. dnastack/alpha/client/collections/client.py +2 -3
  5. dnastack/alpha/client/wes/client.py +5 -8
  6. dnastack/cli/commands/collections/commands.py +3 -4
  7. dnastack/cli/commands/collections/tables.py +1 -1
  8. dnastack/cli/commands/collections/utils.py +1 -1
  9. dnastack/cli/commands/config/commands.py +1 -1
  10. dnastack/cli/commands/config/endpoints.py +39 -20
  11. dnastack/cli/commands/config/registries.py +2 -2
  12. dnastack/cli/commands/dataconnect/tables.py +1 -1
  13. dnastack/cli/commands/drs/commands.py +1 -1
  14. dnastack/cli/commands/explorer/questions/commands.py +12 -6
  15. dnastack/cli/commands/explorer/questions/utils.py +16 -7
  16. dnastack/cli/commands/publisher/collections/commands.py +20 -20
  17. dnastack/cli/commands/publisher/collections/items.py +9 -0
  18. dnastack/cli/commands/publisher/collections/tables.py +1 -1
  19. dnastack/cli/commands/publisher/collections/utils.py +1 -1
  20. dnastack/cli/commands/publisher/datasources/commands.py +1 -1
  21. dnastack/cli/commands/workbench/runs/commands.py +11 -3
  22. dnastack/cli/commands/workbench/workflows/versions/dependencies/commands.py +3 -3
  23. dnastack/cli/commands/workbench/workflows/versions/transformations.py +5 -9
  24. dnastack/cli/helpers/exporter.py +1 -1
  25. dnastack/client/base_exceptions.py +2 -2
  26. dnastack/client/collections/client.py +4 -4
  27. dnastack/client/collections/model.py +30 -29
  28. dnastack/client/data_connect.py +5 -9
  29. dnastack/client/datasources/model.py +3 -3
  30. dnastack/client/drs.py +4 -4
  31. dnastack/client/explorer/client.py +1 -1
  32. dnastack/client/explorer/models.py +3 -7
  33. dnastack/client/factory.py +1 -1
  34. dnastack/client/models.py +6 -6
  35. dnastack/client/service_registry/factory.py +3 -3
  36. dnastack/client/service_registry/helper.py +7 -14
  37. dnastack/client/service_registry/manager.py +4 -4
  38. dnastack/client/workbench/base_client.py +2 -2
  39. dnastack/client/workbench/ewes/client.py +3 -3
  40. dnastack/client/workbench/ewes/models.py +246 -181
  41. dnastack/client/workbench/models.py +7 -7
  42. dnastack/client/workbench/samples/models.py +40 -40
  43. dnastack/client/workbench/storage/client.py +2 -2
  44. dnastack/client/workbench/storage/models.py +24 -24
  45. dnastack/client/workbench/workflow/client.py +7 -7
  46. dnastack/client/workbench/workflow/models.py +64 -64
  47. dnastack/client/workbench/workflow/utils.py +5 -5
  48. dnastack/common/auth_manager.py +6 -13
  49. dnastack/common/class_decorator.py +3 -3
  50. dnastack/common/events.py +7 -7
  51. dnastack/common/json_argument_parser.py +4 -4
  52. dnastack/common/model_mixin.py +1 -1
  53. dnastack/common/parser.py +3 -3
  54. dnastack/common/simple_stream.py +1 -1
  55. dnastack/configuration/manager.py +8 -4
  56. dnastack/configuration/models.py +2 -2
  57. dnastack/constants.py +1 -1
  58. dnastack/context/manager.py +2 -2
  59. dnastack/context/models.py +2 -2
  60. dnastack/feature_flags.py +2 -2
  61. dnastack/http/authenticators/abstract.py +2 -2
  62. dnastack/http/authenticators/factory.py +2 -2
  63. dnastack/http/authenticators/oauth2.py +8 -8
  64. dnastack/http/authenticators/oauth2_adapter/client_credential.py +5 -14
  65. dnastack/http/authenticators/oauth2_adapter/models.py +15 -15
  66. dnastack/http/session.py +3 -3
  67. dnastack/http/session_info.py +3 -3
  68. {dnastack_client_library-3.1.179.dist-info → dnastack_client_library-3.1.205.dist-info}/METADATA +2 -2
  69. {dnastack_client_library-3.1.179.dist-info → dnastack_client_library-3.1.205.dist-info}/RECORD +73 -73
  70. {dnastack_client_library-3.1.179.dist-info → dnastack_client_library-3.1.205.dist-info}/WHEEL +0 -0
  71. {dnastack_client_library-3.1.179.dist-info → dnastack_client_library-3.1.205.dist-info}/entry_points.txt +0 -0
  72. {dnastack_client_library-3.1.179.dist-info → dnastack_client_library-3.1.205.dist-info}/licenses/LICENSE +0 -0
  73. {dnastack_client_library-3.1.179.dist-info → dnastack_client_library-3.1.205.dist-info}/top_level.txt +0 -0
dnastack/common/parser.py CHANGED
@@ -27,7 +27,7 @@ class DotPropertiesParser:
27
27
  self.allow_value_overriding = allow_value_overriding
28
28
 
29
29
  def parse(self, content: str) -> Dict[str, Any]:
30
- data: Dict[str, Any] = dict()
30
+ data: Dict[str, Any] = {}
31
31
 
32
32
  for line in re.split(r'\r\n|\r|\n', content):
33
33
  truncated_line = line.strip()
@@ -99,11 +99,11 @@ class DotPropertiesParser:
99
99
  '.'.join([path[i] for i in range(depth + 1)]))
100
100
 
101
101
  if is_array:
102
- node[p_name_without_array] = list()
102
+ node[p_name_without_array] = []
103
103
  node = node[p_name_without_array]
104
104
  else:
105
105
  if p_name not in node:
106
- node[p_name] = dict()
106
+ node[p_name] = {}
107
107
  node = node[p_name]
108
108
 
109
109
  self.__logger.debug(f'PARSED: {path} = {value}')
@@ -38,7 +38,7 @@ class SimpleStream:
38
38
  return [item for item in self._run()]
39
39
 
40
40
  def to_map(self, key_mapper: Callable[[X], Y], value_mapper: Callable[[X], Z]) -> Dict[Y, Z]:
41
- result: Dict[Y, Z] = dict()
41
+ result: Dict[Y, Z] = {}
42
42
 
43
43
  for item in self._run():
44
44
  result[key_mapper(item)] = value_mapper(item)
@@ -51,10 +51,14 @@ class ConfigurationManager:
51
51
  """ Load the configuration object """
52
52
  self.__logger.debug(f'Reading the configuration from {self.__file_path}...')
53
53
  raw_config = self.load_raw()
54
- if not raw_config:
54
+ if not raw_config or raw_config.strip() in ('', '{}'):
55
55
  return Configuration()
56
56
  try:
57
- config = Configuration(**yaml.load(raw_config, Loader=yaml.SafeLoader))
57
+ parsed_config = yaml.load(raw_config, Loader=yaml.SafeLoader)
58
+ # Handle empty or None yaml results
59
+ if not parsed_config or parsed_config == {}:
60
+ return Configuration()
61
+ config = Configuration(**parsed_config)
58
62
  return self.migrate(config)
59
63
  except ValidationError as e:
60
64
  raise InvalidExistingConfigurationError(f'The existing configuration file at {self.__file_path} is invalid.') from e
@@ -69,7 +73,7 @@ class ConfigurationManager:
69
73
 
70
74
  # Perform sanity checks
71
75
  for context_name, context in configuration.contexts.items():
72
- duplicate_endpoint_id_count_map = dict()
76
+ duplicate_endpoint_id_count_map = {}
73
77
  for endpoint in context.endpoints:
74
78
  if endpoint.id not in duplicate_endpoint_id_count_map:
75
79
  duplicate_endpoint_id_count_map[endpoint.id] = 0
@@ -80,7 +84,7 @@ class ConfigurationManager:
80
84
  f'in the "{context_name}" context'
81
85
 
82
86
  # Save the changes.
83
- new_content = yaml.dump(configuration.dict(exclude_none=True), Dumper=yaml.SafeDumper)
87
+ new_content = yaml.dump(configuration.model_dump(exclude_none=True), Dumper=yaml.SafeDumper)
84
88
  if not os.path.exists(os.path.dirname(self.__swap_file_path)):
85
89
  os.makedirs(os.path.dirname(self.__swap_file_path), exist_ok=True)
86
90
  with open(self.__swap_file_path, 'w') as f:
@@ -29,5 +29,5 @@ class Configuration(BaseModel):
29
29
  ###############################################################
30
30
  # Version 3 (for object migration and backward compatibility) #
31
31
  ###############################################################
32
- defaults: Optional[Dict[str, str]]
33
- endpoints: Optional[List[Endpoint]]
32
+ defaults: Optional[Dict[str, str]] = None
33
+ endpoints: Optional[List[Endpoint]] = None
dnastack/constants.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import os
2
2
 
3
- __version__ = "v3.1.179"
3
+ __version__ = "3.1.205"
4
4
 
5
5
  LOCAL_STORAGE_DIRECTORY = os.path.join(os.path.expanduser("~"), '.dnastack')
@@ -81,7 +81,7 @@ class InMemoryContextMap(ContextMap):
81
81
  self._current_context_name: Optional[str] = None
82
82
 
83
83
  # Internal context maps
84
- self._reference_contexts: Dict[str, Context] = reference_contexts or dict()
84
+ self._reference_contexts: Dict[str, Context] = reference_contexts or {}
85
85
 
86
86
  def all(self) -> Dict[str, Context]:
87
87
  return self._reference_contexts
@@ -327,7 +327,7 @@ class BaseContextManager:
327
327
  # Initiate the authentication procedure.
328
328
  if no_auth:
329
329
  self._logger.debug('AUTH disabled')
330
- self.events.dispatch('auth-disabled', dict())
330
+ self.events.dispatch('auth-disabled', {})
331
331
  else:
332
332
  self._logger.debug('AUTH enabled')
333
333
  auth_manager = AuthManager(context=self._contexts.current_context)
@@ -13,9 +13,9 @@ class Context(BaseModel):
13
13
  guid: str = Field(default_factory=lambda: str(uuid4()))
14
14
 
15
15
  # This is the short-type-to-service-id map.
16
- defaults: Dict[str, str] = Field(default_factory=lambda: dict())
16
+ defaults: Dict[str, str] = Field(default_factory=lambda: {})
17
17
 
18
- endpoints: List[Endpoint] = Field(default_factory=lambda: list())
18
+ endpoints: List[Endpoint] = Field(default_factory=lambda: [])
19
19
 
20
20
  # Store subject token for token exchange authentication if provided
21
21
  platform_subject_token: Optional[str] = Field(default=None)
dnastack/feature_flags.py CHANGED
@@ -3,8 +3,8 @@ from typing import Callable, List, Dict
3
3
 
4
4
  from dnastack.common.environments import flag
5
5
 
6
- __FLAG_CACHE_MAP: Dict[str, bool] = dict()
7
- __DEBUG_MODE_HOOKS: List[Callable[[bool], None]] = list()
6
+ __FLAG_CACHE_MAP: Dict[str, bool] = {}
7
+ __DEBUG_MODE_HOOKS: List[Callable[[bool], None]] = []
8
8
 
9
9
 
10
10
  def currently_in_debug_mode():
@@ -39,7 +39,7 @@ class RefreshRequired(RuntimeError):
39
39
 
40
40
  def __init__(self, session: Optional[SessionInfo]):
41
41
  super().__init__('Session refresh required')
42
- self.__session = session.copy(deep=True)
42
+ self.__session = session.model_copy(deep=True)
43
43
 
44
44
  @property
45
45
  def session(self):
@@ -141,7 +141,7 @@ class Authenticator(AuthBase, ABC):
141
141
 
142
142
  def initialize(self, trace_context: Span) -> SessionInfo:
143
143
  """ Initialize the authenticator """
144
- self.events.dispatch('initialization-before', dict(origin=f'{self.class_name}'))
144
+ self.events.dispatch('initialization-before', {'origin': f'{self.class_name}'})
145
145
  logger = trace_context.create_span_logger(self._logger)
146
146
  try:
147
147
  logger.debug('initialize: Restoring the session...')
@@ -37,13 +37,13 @@ class HttpAuthenticatorFactory:
37
37
 
38
38
  # NOTE: Should raise a custom exception if it fails the model validation.
39
39
 
40
- return config.dict()
40
+ return config.model_dump()
41
41
  else:
42
42
  raise UnsupportedAuthenticationInformationError(auth_info)
43
43
 
44
44
  @staticmethod
45
45
  def get_unique_auth_info_list(endpoints: List[ServiceEndpoint]) -> List[Dict[str, Any]]:
46
- unique_auth_info_map: Dict[str, Dict[str, Any]] = dict()
46
+ unique_auth_info_map: Dict[str, Dict[str, Any]] = {}
47
47
 
48
48
  for endpoint in endpoints:
49
49
  for auth_info in endpoint.get_authentications():
@@ -55,7 +55,7 @@ class OAuth2Authenticator(Authenticator):
55
55
  self._session_info: Optional[SessionInfo] = None
56
56
 
57
57
  def _get_logger_name(self):
58
- metadata = dict()
58
+ metadata = {}
59
59
 
60
60
  if self._auth_info:
61
61
  auth_info = OAuth2Authentication(**self._auth_info)
@@ -81,14 +81,14 @@ class OAuth2Authenticator(Authenticator):
81
81
 
82
82
  def get_state(self) -> AuthState:
83
83
  status = AuthStateStatus.READY
84
- session_info: Dict[str, Any] = dict()
84
+ session_info: Dict[str, Any] = {}
85
85
 
86
86
  try:
87
87
  session = self.restore_session()
88
- session_info.update(session.dict())
88
+ session_info.update(session.model_dump())
89
89
  except RefreshRequired as e:
90
90
  status = AuthStateStatus.REFRESH_REQUIRED
91
- session_info.update(e.session.dict())
91
+ session_info.update(e.session.model_dump())
92
92
  except AuthenticationRequired:
93
93
  status = AuthStateStatus.UNINITIALIZED
94
94
  except (ReauthenticationRequiredDueToConfigChange, ReauthenticationRequired):
@@ -137,7 +137,7 @@ class OAuth2Authenticator(Authenticator):
137
137
  self.events.relay_from(adapter.events, auth_event_type)
138
138
 
139
139
  raw_response = adapter.exchange_tokens(trace_context)
140
- self._session_info = self._convert_token_response_to_session(auth_info.dict(), raw_response)
140
+ self._session_info = self._convert_token_response_to_session(auth_info.model_dump(), raw_response)
141
141
  self._session_manager.save(session_id, self._session_info)
142
142
 
143
143
  event_details['session_info'] = self._session_info
@@ -227,7 +227,7 @@ class OAuth2Authenticator(Authenticator):
227
227
  refresh_token_json['refresh_token'] = refresh_token
228
228
 
229
229
  # Update the session
230
- updated_session_info = self._convert_token_response_to_session(auth_info.dict(), refresh_token_json)
230
+ updated_session_info = self._convert_token_response_to_session(auth_info.model_dump(), refresh_token_json)
231
231
  session_info.access_token = updated_session_info.access_token
232
232
  session_info.token_type = updated_session_info.token_type
233
233
  session_info.valid_until = updated_session_info.valid_until
@@ -280,7 +280,7 @@ class OAuth2Authenticator(Authenticator):
280
280
 
281
281
  if currently_in_debug_mode():
282
282
  exception_details['_internal'] = {
283
- 'session_info': session_info.dict(),
283
+ 'session_info': session_info.model_dump(),
284
284
  'session_manager': str(self._session_manager),
285
285
  }
286
286
 
@@ -420,7 +420,7 @@ class OAuth2Authenticator(Authenticator):
420
420
  self.events.relay_from(adapter.events, auth_event_type)
421
421
 
422
422
  token_response = adapter.exchange_tokens(trace_context)
423
- self._session_info = self._convert_token_response_to_session(auth_info.dict(), token_response)
423
+ self._session_info = self._convert_token_response_to_session(auth_info.model_dump(), token_response)
424
424
  self._session_manager.save(session_id, self._session_info)
425
425
 
426
426
  event_details['session_info'] = self._session_info
@@ -31,22 +31,13 @@ class ClientCredentialAdapter(OAuth2Adapter):
31
31
  auth_info = self._auth_info
32
32
  resource_urls = self._prepare_resource_urls_for_request(auth_info.resource_url)
33
33
 
34
- trace_info = dict(
35
- oauth='client-credentials',
36
- token_url=auth_info.token_endpoint,
37
- client_id=auth_info.client_id,
38
- grant_type=self.__grant_type,
39
- resource_urls=resource_urls,
40
- scope=auth_info.scope,
41
- )
34
+ trace_info = {'oauth': 'client-credentials', 'token_url': auth_info.token_endpoint,
35
+ 'client_id': auth_info.client_id, 'grant_type': self.__grant_type, 'resource_urls': resource_urls,
36
+ 'scope': auth_info.scope}
42
37
  logger.debug(f'exchange_token: Authenticating with {trace_info}')
43
38
 
44
- auth_params = dict(
45
- client_id=auth_info.client_id,
46
- client_secret=auth_info.client_secret,
47
- grant_type=self.__grant_type,
48
- resource=resource_urls,
49
- )
39
+ auth_params = {'client_id': auth_info.client_id, 'client_secret': auth_info.client_secret,
40
+ 'grant_type': self.__grant_type, 'resource': resource_urls}
50
41
 
51
42
  if auth_info.scope:
52
43
  auth_params['scope'] = auth_info.scope
@@ -10,21 +10,21 @@ GRANT_TYPE_TOKEN_EXCHANGE = 'urn:ietf:params:oauth:grant-type:token-exchange'
10
10
 
11
11
  class OAuth2Authentication(BaseModel, HashableModel):
12
12
  """OAuth2 Authentication Information"""
13
- authorization_endpoint: Optional[str]
14
- client_id: Optional[str]
15
- client_secret: Optional[str]
16
- device_code_endpoint: Optional[str]
13
+ authorization_endpoint: Optional[str] = None
14
+ client_id: Optional[str] = None
15
+ client_secret: Optional[str] = None
16
+ device_code_endpoint: Optional[str] = None
17
17
  grant_type: str
18
- personal_access_endpoint: Optional[str]
19
- personal_access_email: Optional[str]
20
- personal_access_token: Optional[str]
21
- redirect_url: Optional[str]
18
+ personal_access_endpoint: Optional[str] = None
19
+ personal_access_email: Optional[str] = None
20
+ personal_access_token: Optional[str] = None
21
+ redirect_url: Optional[str] = None
22
22
  resource_url: str
23
- scope: Optional[str]
24
- token_endpoint: Optional[str]
23
+ scope: Optional[str] = None
24
+ token_endpoint: Optional[str] = None
25
25
  type: str = 'oauth2'
26
- subject_token: Optional[str]
27
- subject_token_type: Optional[str]
28
- requested_token_type: Optional[str]
29
- audience: Optional[str]
30
- cloud_provider: Optional[str] # Currently supported: 'gcp'
26
+ subject_token: Optional[str] = None
27
+ subject_token_type: Optional[str] = None
28
+ requested_token_type: Optional[str] = None
29
+ audience: Optional[str] = None
30
+ cloud_provider: Optional[str] = None # Currently supported: 'gcp'
dnastack/http/session.py CHANGED
@@ -164,7 +164,7 @@ class HttpSession(AbstractContextManager):
164
164
  **kwargs) -> Response | None | Any:
165
165
  trace_context = trace_context or Span(origin=self)
166
166
 
167
- retry_history = retry_history or list()
167
+ retry_history = retry_history or []
168
168
  session = self._session
169
169
 
170
170
  logger = trace_context.create_span_logger(self.__logger)
@@ -211,7 +211,7 @@ class HttpSession(AbstractContextManager):
211
211
 
212
212
  sub_logger.debug(f'Request/{http_method.upper()} {url}')
213
213
 
214
- existing_headers = kwargs.get('headers') or dict()
214
+ existing_headers = kwargs.get('headers') or {}
215
215
  existing_headers.update(sub_span.create_http_headers())
216
216
  kwargs['headers'] = existing_headers
217
217
 
@@ -369,7 +369,7 @@ class HttpSession(AbstractContextManager):
369
369
  final_comments = [
370
370
  f'Platform/{platform.platform()}', # OS information + CPU architecture
371
371
  'Python/{}.{}.{}'.format(*sys.version_info), # Python version
372
- *(comments or list()),
372
+ *(comments or []),
373
373
  *[
374
374
  f'Module/{interested_module_name}'
375
375
  for interested_module_name in interested_module_names
@@ -111,7 +111,7 @@ class InMemorySessionStorage(BaseSessionStorage):
111
111
 
112
112
  def __init__(self):
113
113
  self.__logger = get_logger(type(self).__name__)
114
- self.__cache_map: Dict[str, SessionInfo] = dict()
114
+ self.__cache_map: Dict[str, SessionInfo] = {}
115
115
 
116
116
  def __contains__(self, id: str) -> bool:
117
117
  return id in self.__cache_map
@@ -164,7 +164,7 @@ class FileSessionStorage(BaseSessionStorage):
164
164
  final_file_path = self.__get_file_path(id)
165
165
  temp_file_path = f'{final_file_path}.{time()}.swap'
166
166
 
167
- content: str = session.json(indent=2)
167
+ content: str = session.model_dump_json(indent=2)
168
168
 
169
169
  os.makedirs(os.path.dirname(final_file_path), exist_ok=True)
170
170
  with open(temp_file_path, 'w') as f:
@@ -210,7 +210,7 @@ class SessionManager:
210
210
  static_session_file: Optional[str] = None):
211
211
  self.__logger = get_logger(type(self).__name__)
212
212
  self.__storage = storage
213
- self.__change_locks: Dict[str, Lock] = dict()
213
+ self.__change_locks: Dict[str, Lock] = {}
214
214
  self.__static_session: Optional[SessionInfo] = None
215
215
 
216
216
  self.__logger.debug('Session Storage: %s', self.__storage)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dnastack-client-library
3
- Version: 3.1.179
3
+ Version: 3.1.205
4
4
  Summary: DNAstack's GA4GH library and CLI
5
5
  Author-email: DNAstack <devs@dnastack.com>
6
6
  License: Apache License, Version 2.0
@@ -18,7 +18,7 @@ Requires-Python: >=3.11
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: click<8.2,>=8.0.3
21
- Requires-Dist: pydantic<2,>=1.9.0
21
+ Requires-Dist: pydantic>=2.0
22
22
  Requires-Dist: pyjwt<3,>=2.1.0
23
23
  Requires-Dist: pyyaml>=5.4.1
24
24
  Requires-Dist: requests<3,>=2.23.0