digitalhub 0.13.4__py3-none-any.whl → 0.14.0__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.

Files changed (116) hide show
  1. digitalhub/__init__.py +3 -8
  2. digitalhub/context/api.py +1 -5
  3. digitalhub/context/builder.py +1 -5
  4. digitalhub/context/context.py +2 -9
  5. digitalhub/entities/_base/_base/entity.py +0 -15
  6. digitalhub/entities/_base/context/entity.py +1 -1
  7. digitalhub/entities/_base/entity/builder.py +5 -5
  8. digitalhub/entities/_base/entity/entity.py +0 -8
  9. digitalhub/entities/_base/executable/entity.py +169 -79
  10. digitalhub/entities/_base/material/entity.py +6 -22
  11. digitalhub/entities/_base/material/utils.py +1 -4
  12. digitalhub/entities/_base/runtime_entity/builder.py +53 -18
  13. digitalhub/entities/_base/unversioned/entity.py +1 -1
  14. digitalhub/entities/_base/versioned/entity.py +1 -1
  15. digitalhub/entities/_commons/enums.py +1 -31
  16. digitalhub/entities/_commons/utils.py +83 -21
  17. digitalhub/entities/_constructors/_resources.py +151 -0
  18. digitalhub/entities/{_base/entity/_constructors → _constructors}/name.py +18 -0
  19. digitalhub/entities/_processors/base/__init__.py +3 -0
  20. digitalhub/entities/_processors/{base.py → base/crud.py} +14 -226
  21. digitalhub/entities/_processors/base/import_export.py +123 -0
  22. digitalhub/entities/_processors/base/processor.py +302 -0
  23. digitalhub/entities/_processors/base/special_ops.py +108 -0
  24. digitalhub/entities/_processors/context/__init__.py +3 -0
  25. digitalhub/entities/_processors/context/crud.py +652 -0
  26. digitalhub/entities/_processors/context/import_export.py +242 -0
  27. digitalhub/entities/_processors/context/material.py +123 -0
  28. digitalhub/entities/_processors/context/processor.py +400 -0
  29. digitalhub/entities/_processors/context/special_ops.py +476 -0
  30. digitalhub/entities/_processors/processors.py +12 -0
  31. digitalhub/entities/_processors/utils.py +12 -11
  32. digitalhub/entities/artifact/crud.py +58 -22
  33. digitalhub/entities/artifact/utils.py +3 -3
  34. digitalhub/entities/dataitem/crud.py +63 -20
  35. digitalhub/entities/dataitem/table/entity.py +24 -22
  36. digitalhub/entities/dataitem/utils.py +15 -15
  37. digitalhub/entities/function/_base/entity.py +3 -3
  38. digitalhub/entities/function/crud.py +55 -24
  39. digitalhub/entities/model/_base/entity.py +62 -20
  40. digitalhub/entities/model/crud.py +58 -22
  41. digitalhub/entities/model/utils.py +3 -3
  42. digitalhub/entities/project/_base/entity.py +321 -152
  43. digitalhub/entities/project/crud.py +15 -23
  44. digitalhub/entities/run/_base/builder.py +0 -4
  45. digitalhub/entities/run/_base/entity.py +70 -63
  46. digitalhub/entities/run/crud.py +79 -26
  47. digitalhub/entities/secret/_base/entity.py +1 -5
  48. digitalhub/entities/secret/crud.py +29 -26
  49. digitalhub/entities/task/_base/builder.py +0 -4
  50. digitalhub/entities/task/_base/entity.py +5 -5
  51. digitalhub/entities/task/_base/models.py +13 -16
  52. digitalhub/entities/task/crud.py +61 -29
  53. digitalhub/entities/trigger/_base/entity.py +1 -5
  54. digitalhub/entities/trigger/crud.py +64 -24
  55. digitalhub/entities/workflow/_base/entity.py +3 -3
  56. digitalhub/entities/workflow/crud.py +55 -21
  57. digitalhub/factory/entity.py +283 -0
  58. digitalhub/factory/enums.py +18 -0
  59. digitalhub/factory/registry.py +197 -0
  60. digitalhub/factory/runtime.py +44 -0
  61. digitalhub/factory/utils.py +3 -54
  62. digitalhub/runtimes/_base.py +2 -2
  63. digitalhub/stores/client/_base/enums.py +39 -0
  64. digitalhub/stores/client/_base/key_builder.py +2 -2
  65. digitalhub/stores/client/_base/params_builder.py +48 -0
  66. digitalhub/stores/client/api.py +6 -10
  67. digitalhub/stores/client/builder.py +4 -4
  68. digitalhub/stores/client/dhcore/api_builder.py +2 -1
  69. digitalhub/stores/client/dhcore/client.py +85 -429
  70. digitalhub/stores/client/dhcore/configurator.py +109 -328
  71. digitalhub/stores/client/dhcore/enums.py +0 -16
  72. digitalhub/stores/client/dhcore/error_parser.py +0 -4
  73. digitalhub/stores/client/dhcore/header_manager.py +61 -0
  74. digitalhub/stores/client/dhcore/http_handler.py +133 -0
  75. digitalhub/stores/client/dhcore/params_builder.py +147 -134
  76. digitalhub/stores/client/dhcore/response_processor.py +102 -0
  77. digitalhub/stores/client/dhcore/utils.py +6 -72
  78. digitalhub/stores/client/local/api_builder.py +1 -1
  79. digitalhub/stores/client/local/client.py +79 -47
  80. digitalhub/stores/client/local/params_builder.py +18 -41
  81. digitalhub/stores/credentials/api.py +0 -4
  82. digitalhub/stores/credentials/configurator.py +2 -28
  83. digitalhub/stores/credentials/enums.py +3 -0
  84. digitalhub/stores/credentials/handler.py +0 -12
  85. digitalhub/stores/credentials/ini_module.py +0 -22
  86. digitalhub/stores/credentials/store.py +0 -4
  87. digitalhub/stores/data/_base/store.py +0 -16
  88. digitalhub/stores/data/builder.py +1 -5
  89. digitalhub/stores/data/local/store.py +0 -103
  90. digitalhub/stores/data/remote/store.py +0 -4
  91. digitalhub/stores/data/s3/configurator.py +60 -14
  92. digitalhub/stores/data/s3/store.py +49 -16
  93. digitalhub/stores/data/sql/configurator.py +0 -8
  94. digitalhub/stores/data/sql/store.py +21 -10
  95. digitalhub/stores/readers/data/factory.py +0 -8
  96. digitalhub/stores/readers/data/pandas/reader.py +0 -16
  97. digitalhub/utils/file_utils.py +0 -17
  98. digitalhub/utils/generic_utils.py +0 -12
  99. digitalhub/utils/git_utils.py +0 -8
  100. digitalhub/utils/io_utils.py +0 -12
  101. digitalhub/utils/store_utils.py +44 -0
  102. {digitalhub-0.13.4.dist-info → digitalhub-0.14.0.dist-info}/METADATA +3 -2
  103. {digitalhub-0.13.4.dist-info → digitalhub-0.14.0.dist-info}/RECORD +111 -95
  104. digitalhub/entities/_processors/context.py +0 -1450
  105. digitalhub/entities/task/_base/utils.py +0 -22
  106. digitalhub/factory/factory.py +0 -381
  107. digitalhub/stores/client/dhcore/models.py +0 -40
  108. digitalhub/stores/data/s3/utils.py +0 -78
  109. /digitalhub/entities/{_base/entity/_constructors → _constructors}/__init__.py +0 -0
  110. /digitalhub/entities/{_base/entity/_constructors → _constructors}/metadata.py +0 -0
  111. /digitalhub/entities/{_base/entity/_constructors → _constructors}/spec.py +0 -0
  112. /digitalhub/entities/{_base/entity/_constructors → _constructors}/status.py +0 -0
  113. /digitalhub/entities/{_base/entity/_constructors → _constructors}/uuid.py +0 -0
  114. {digitalhub-0.13.4.dist-info → digitalhub-0.14.0.dist-info}/WHEEL +0 -0
  115. {digitalhub-0.13.4.dist-info → digitalhub-0.14.0.dist-info}/licenses/AUTHORS +0 -0
  116. {digitalhub-0.13.4.dist-info → digitalhub-0.14.0.dist-info}/licenses/LICENSE +0 -0
@@ -7,22 +7,6 @@ from __future__ import annotations
7
7
  from enum import Enum
8
8
 
9
9
 
10
- class DhcoreEnvVar(Enum):
11
- """
12
- Environment variables.
13
- """
14
-
15
- ENDPOINT = "DHCORE_ENDPOINT"
16
- ISSUER = "DHCORE_ISSUER"
17
- USER = "DHCORE_USER"
18
- PASSWORD = "DHCORE_PASSWORD"
19
- CLIENT_ID = "DHCORE_CLIENT_ID"
20
- ACCESS_TOKEN = "DHCORE_ACCESS_TOKEN"
21
- REFRESH_TOKEN = "DHCORE_REFRESH_TOKEN"
22
- PERSONAL_ACCESS_TOKEN = "DHCORE_PERSONAL_ACCESS_TOKEN"
23
- WORKFLOW_IMAGE = "DHCORE_WORKFLOW_IMAGE"
24
-
25
-
26
10
  class AuthType(Enum):
27
11
  """
28
12
  Authentication types.
@@ -44,10 +44,6 @@ class ErrorParser:
44
44
  response : Response
45
45
  The HTTP response object from requests.
46
46
 
47
- Returns
48
- -------
49
- None
50
-
51
47
  Raises
52
48
  ------
53
49
  TimeoutError
@@ -0,0 +1,61 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+
8
+ class HeaderManager:
9
+ """
10
+ Manages HTTP headers for DHCore client requests.
11
+
12
+ Provides utilities for setting and managing common HTTP headers
13
+ like Content-Type for JSON requests.
14
+ """
15
+
16
+ @staticmethod
17
+ def ensure_headers(**kwargs) -> dict:
18
+ """
19
+ Initialize headers dictionary in kwargs.
20
+
21
+ Ensures parameter dictionary has 'headers' key for HTTP headers,
22
+ guaranteeing consistent structure for all parameter building methods.
23
+
24
+ Parameters
25
+ ----------
26
+ **kwargs : dict
27
+ Keyword arguments to format. May be empty or contain various
28
+ parameters for API operations.
29
+
30
+ Returns
31
+ -------
32
+ dict
33
+ Dictionary with guaranteed 'headers' key containing
34
+ empty dict if not already present.
35
+ """
36
+ if "headers" not in kwargs:
37
+ kwargs["headers"] = {}
38
+ return kwargs
39
+
40
+ @staticmethod
41
+ def set_json_content_type(**kwargs) -> dict:
42
+ """
43
+ Set Content-Type header to application/json.
44
+
45
+ Ensures that the 'Content-Type' header is set to 'application/json'
46
+ for requests that require JSON payloads.
47
+
48
+ Parameters
49
+ ----------
50
+ **kwargs : dict
51
+ Keyword arguments to format. May be empty or contain various
52
+ parameters for API operations.
53
+
54
+ Returns
55
+ -------
56
+ dict
57
+ Dictionary with 'Content-Type' header set to 'application/json'.
58
+ """
59
+ kwargs = HeaderManager.ensure_headers(**kwargs)
60
+ kwargs["headers"]["Content-Type"] = "application/json"
61
+ return kwargs
@@ -0,0 +1,133 @@
1
+ # SPDX-FileCopyrightText: © 2025 DSLab - Fondazione Bruno Kessler
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ from requests import request
8
+
9
+ from digitalhub.stores.client.dhcore.configurator import ClientDHCoreConfigurator
10
+ from digitalhub.stores.client.dhcore.response_processor import ResponseProcessor
11
+ from digitalhub.utils.exceptions import BackendError
12
+
13
+ # Default timeout for requests (in seconds)
14
+ DEFAULT_TIMEOUT = 60
15
+
16
+
17
+ class HttpRequestHandler:
18
+ """
19
+ Handles HTTP request execution for DHCore client.
20
+
21
+ Encapsulates all HTTP communication logic including request execution,
22
+ automatic token refresh on authentication failures, and response processing.
23
+ Works in coordination with configurator for authentication and response
24
+ processor for parsing.
25
+ """
26
+
27
+ def __init__(self) -> None:
28
+ self._configurator = ClientDHCoreConfigurator()
29
+ self._response_processor = ResponseProcessor()
30
+
31
+ def prepare_request(self, method: str, api: str, **kwargs) -> dict:
32
+ """
33
+ Execute API call with full URL construction and authentication.
34
+
35
+ Parameters
36
+ ----------
37
+ method : str
38
+ HTTP method type (GET, POST, PUT, DELETE, etc.).
39
+ api : str
40
+ API endpoint path to call.
41
+ **kwargs : dict
42
+ Additional HTTP request arguments.
43
+
44
+ Returns
45
+ -------
46
+ dict
47
+ Response from the API call.
48
+ """
49
+ full_kwargs = self._set_auth(**kwargs)
50
+ url = self._build_url(api)
51
+ return self._execute_request(method, url, **full_kwargs)
52
+
53
+ def _execute_request(
54
+ self,
55
+ method: str,
56
+ url: str,
57
+ refresh: bool = True,
58
+ **kwargs,
59
+ ) -> dict:
60
+ """
61
+ Execute HTTP request with automatic handling.
62
+
63
+ Sends HTTP request with authentication, handles token refresh on 401 errors,
64
+ validates API version compatibility, and parses response. Uses 60-second
65
+ timeout by default.
66
+
67
+ Parameters
68
+ ----------
69
+ method : str
70
+ HTTP method (GET, POST, PUT, DELETE, etc.).
71
+ url : str
72
+ Complete URL to request.
73
+ refresh : bool, default True
74
+ Whether to attempt token refresh on authentication errors.
75
+ Set to False during refresh to prevent infinite recursion.
76
+ **kwargs : dict
77
+ Additional HTTP request arguments (headers, params, data, etc.).
78
+
79
+ Returns
80
+ -------
81
+ dict
82
+ Parsed response body as dictionary.
83
+ """
84
+ # Execute HTTP request
85
+ response = request(method, url, timeout=DEFAULT_TIMEOUT, **kwargs)
86
+
87
+ # Process response (version check, error parsing, dictify)
88
+ try:
89
+ return self._response_processor.process(response)
90
+ except BackendError as e:
91
+ # Handle authentication errors with token refresh
92
+ if response.status_code == 401 and refresh and self._configurator.refreshable_auth_types():
93
+ self._configurator.refresh_credentials(change_origin=True)
94
+ kwargs = self._configurator.get_auth_parameters(kwargs)
95
+ return self._execute_request(method, url, refresh=False, **kwargs)
96
+ raise e
97
+
98
+ def _set_auth(self, **kwargs) -> dict:
99
+ """
100
+ Prepare kwargs with authentication parameters.
101
+
102
+ Parameters
103
+ ----------
104
+ **kwargs : dict
105
+ Request parameters to augment with authentication.
106
+
107
+ Returns
108
+ -------
109
+ dict
110
+ kwargs enhanced with authentication parameters.
111
+ """
112
+ self._configurator.check_config()
113
+ return self._configurator.get_auth_parameters(kwargs)
114
+
115
+ def _build_url(self, api: str) -> str:
116
+ """
117
+ Build complete URL for API call.
118
+
119
+ Combines configured endpoint with API path, automatically removing
120
+ leading slashes for proper URL construction.
121
+
122
+ Parameters
123
+ ----------
124
+ api : str
125
+ API endpoint path. Leading slashes are automatically handled.
126
+
127
+ Returns
128
+ -------
129
+ str
130
+ Complete URL for the API call.
131
+ """
132
+ endpoint = self._configurator.get_endpoint()
133
+ return f"{endpoint}/{api.removeprefix('/')}"
@@ -4,26 +4,24 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- from digitalhub.entities._commons.enums import ApiCategories, BackendOperations
7
+ from digitalhub.stores.client._base.enums import ApiCategories, BackendOperations
8
8
  from digitalhub.stores.client._base.params_builder import ClientParametersBuilder
9
9
 
10
+ DEFAULT_START_PAGE = 0
11
+ DEFAULT_SIZE = 25
12
+ DEFAULT_SORT = "metadata.updated,DESC"
13
+
10
14
 
11
15
  class ClientDHCoreParametersBuilder(ClientParametersBuilder):
12
16
  """
13
17
  Parameter builder for DHCore client API calls.
14
18
 
15
- This class constructs HTTP request parameters for different DHCore API
16
- operations, handling the specific parameter formats and query structures
17
- required by the DigitalHub Core backend. It supports both base-level
18
- operations (like project management) and context-level operations
19
- (entity operations within projects).
20
-
21
- The builder handles various parameter transformations including:
22
- - Query parameter formatting for different operations
23
- - Search filter construction for Solr-based searches
24
- - Cascade deletion options
25
- - Versioning parameters
26
- - Entity sharing parameters
19
+ Constructs HTTP request parameters for DHCore API operations, handling
20
+ parameter formats and query structures for both base-level operations
21
+ (project management) and context-level operations (entity operations
22
+ within projects). Supports query parameter formatting, search filter
23
+ construction for Solr-based searches, cascade deletion options,
24
+ versioning parameters, and entity sharing parameters.
27
25
 
28
26
  Methods
29
27
  -------
@@ -39,36 +37,22 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
39
37
  """
40
38
  Build HTTP request parameters for DHCore API calls.
41
39
 
42
- Routes parameter building to the appropriate method based on the
43
- API category (base or context operations) and applies operation-specific
44
- parameter transformations.
45
-
46
40
  Parameters
47
41
  ----------
48
42
  category : str
49
- The API category, either 'base' for project-level operations
50
- or 'context' for entity operations within projects.
43
+ API category: 'base' for project-level operations or 'context'
44
+ for entity operations within projects.
51
45
  operation : str
52
- The specific API operation being performed (create, read, update,
53
- delete, list, search, etc.).
46
+ Specific API operation (create, read, update, delete, list, search, etc.).
54
47
  **kwargs : dict
55
- Raw parameters to be transformed into proper HTTP request format.
56
- May include entity identifiers, filter criteria, pagination
57
- options, etc.
48
+ Raw parameters to transform including entity identifiers, filter
49
+ criteria, pagination options, etc.
58
50
 
59
51
  Returns
60
52
  -------
61
53
  dict
62
- Formatted parameters dictionary ready for HTTP request, typically
63
- containing a 'params' key with query parameters and other
64
- request-specific parameters.
65
-
66
- Notes
67
- -----
68
- This method acts as a dispatcher, routing to either base or context
69
- parameter building based on the category. All parameter dictionaries
70
- are initialized with a 'params' key for query parameters if not
71
- already present.
54
+ Formatted parameters dictionary with 'params' key for query parameters
55
+ and other request-specific parameters.
72
56
  """
73
57
  if category == ApiCategories.BASE.value:
74
58
  return self.build_parameters_base(operation, **kwargs)
@@ -76,128 +60,105 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
76
60
 
77
61
  def build_parameters_base(self, operation: str, **kwargs) -> dict:
78
62
  """
79
- Build parameters for base-level API operations.
80
-
81
- Constructs HTTP request parameters for operations that work at the
82
- base level of the API, typically project-level operations and
83
- entity sharing functionality.
63
+ Constructs HTTP request parameters for project operations.
84
64
 
85
65
  Parameters
86
66
  ----------
87
67
  operation : str
88
- The API operation being performed. Supported operations:
89
- - DELETE: Project deletion with optional cascade
90
- - SHARE: Entity sharing/unsharing with users
68
+ API operation.
91
69
  **kwargs : dict
92
- Operation-specific parameters including:
93
- - cascade (bool): For DELETE, whether to cascade delete
94
- - user (str): For SHARE, target user for sharing
95
- - unshare (bool): For SHARE, whether to unshare instead
96
- - id (str): For SHARE unshare, entity ID to unshare
97
-
70
+ Operation-specific parameters.
98
71
  Returns
99
72
  -------
100
73
  dict
101
- Formatted parameters with 'params' containing query parameters
102
- and other request-specific parameters.
103
-
104
- Notes
105
- -----
106
- Parameter transformations:
107
- - CASCADE: Boolean values are converted to lowercase strings
108
- - SHARE: User parameter is moved to query params
109
- - UNSHARE: Requires both unshare=True and entity id
74
+ Formatted parameters with 'params' containing query parameters.
110
75
  """
111
- kwargs = self._set_params(**kwargs)
76
+ kwargs = self._ensure_params(**kwargs)
77
+
78
+ # Handle delete
112
79
  if operation == BackendOperations.DELETE.value:
113
80
  if (cascade := kwargs.pop("cascade", None)) is not None:
114
- kwargs["params"]["cascade"] = str(cascade).lower()
81
+ kwargs = self._add_param("cascade", str(cascade).lower(), **kwargs)
82
+
83
+ # Handle share
115
84
  elif operation == BackendOperations.SHARE.value:
116
- kwargs["params"]["user"] = kwargs.pop("user")
85
+ kwargs = self._add_param("user", kwargs.pop("user"), **kwargs)
117
86
  if kwargs.pop("unshare", False):
118
- kwargs["params"]["id"] = kwargs.pop("id")
87
+ kwargs = self._add_param("id", kwargs.pop("id"), **kwargs)
119
88
 
120
89
  return kwargs
121
90
 
122
91
  def build_parameters_context(self, operation: str, **kwargs) -> dict:
123
92
  """
124
- Build parameters for context-level API operations.
125
-
126
- Constructs HTTP request parameters for operations that work within
127
- a specific context (project), including entity management and
128
- search functionality.
93
+ Constructs HTTP request parameters for entity management and search within
94
+ projects.
129
95
 
130
96
  Parameters
131
97
  ----------
132
98
  operation : str
133
- The API operation being performed. Supported operations:
134
- - SEARCH: Search entities with filtering and pagination
135
- - READ_MANY: Retrieve multiple entities with pagination
136
- - DELETE: Delete specific entity by ID
137
- - READ: Read specific entity by ID (with optional embedded)
99
+ API operation.
138
100
  **kwargs : dict
139
- Operation-specific parameters including:
140
- - params (dict): Search filters and conditions
141
- - page (int): Page number for pagination (default: 0)
142
- - size (int): Number of items per page (default: 20)
143
- - order_by (str): Field to order results by
144
- - order (str): Order direction ('asc' or 'desc')
145
- - embedded (bool): For READ, whether to include embedded entities
146
- - id (str): For READ/DELETE, entity identifier
101
+ Operation-specific parameters.
147
102
 
148
103
  Returns
149
104
  -------
150
105
  dict
151
- Formatted parameters with 'params' containing query parameters
152
- and other request-specific parameters like 'id' for entity operations.
153
-
154
- Notes
155
- -----
156
- Search and pagination:
157
- - Filters are applied via 'filter' parameter in query string
158
- - Pagination uses 'page' and 'size' parameters
159
- - Results can be ordered using 'sort' parameter format
160
-
161
- Entity operations:
162
- - READ: Supports embedded entity inclusion via 'embedded' param
163
- - DELETE: Requires entity 'id' parameter
106
+ Formatted parameters with 'params'.
164
107
  """
165
- kwargs = self._set_params(**kwargs)
108
+ kwargs = self._ensure_params(**kwargs)
166
109
 
167
110
  # Handle read
168
111
  if operation == BackendOperations.READ.value:
169
- name = kwargs.pop("entity_name", None)
170
- if name is not None:
171
- kwargs["params"]["name"] = name
112
+ if (name := kwargs.pop("name", None)) is not None:
113
+ kwargs = self._add_param("name", name, **kwargs)
114
+
115
+ # Handle read all versions
172
116
  elif operation == BackendOperations.READ_ALL_VERSIONS.value:
173
- kwargs["params"]["versions"] = "all"
174
- kwargs["params"]["name"] = kwargs.pop("entity_name")
117
+ kwargs = self._add_param("versions", "all", **kwargs)
118
+ kwargs = self._add_param("name", kwargs.pop("name"), **kwargs)
119
+
120
+ # Handle list
121
+ elif operation == BackendOperations.LIST.value:
122
+ possible_list_params = [
123
+ "q",
124
+ "name",
125
+ "kind",
126
+ "user",
127
+ "state",
128
+ "created",
129
+ "updated",
130
+ "versions",
131
+ "function",
132
+ "workflow",
133
+ "action",
134
+ "task",
135
+ ]
136
+ list_params = {k: kwargs.get(k, None) for k in possible_list_params}
137
+ list_params = self._filter_none_params(**list_params)
138
+ for k, v in list_params.items():
139
+ kwargs = self._add_param(k, v, **kwargs)
140
+ for k in possible_list_params:
141
+ kwargs.pop(k, None)
142
+
175
143
  # Handle delete
176
144
  elif operation == BackendOperations.DELETE.value:
177
- # Handle cascade
178
145
  if (cascade := kwargs.pop("cascade", None)) is not None:
179
- kwargs["params"]["cascade"] = str(cascade).lower()
180
-
181
- # Handle delete all versions
182
- entity_id = kwargs.pop("entity_id")
183
- entity_name = kwargs.pop("entity_name")
184
- if not kwargs.pop("delete_all_versions", False):
185
- if entity_id is None:
186
- raise ValueError(
187
- "If `delete_all_versions` is False, `entity_id` must be provided,"
188
- " either as an argument or in key `identifier`.",
189
- )
190
- else:
191
- kwargs["params"]["name"] = entity_name
146
+ kwargs = self._add_param("cascade", str(cascade).lower(), **kwargs)
147
+
148
+ elif operation == BackendOperations.DELETE_ALL_VERSIONS.value:
149
+ if (cascade := kwargs.pop("cascade", None)) is not None:
150
+ kwargs = self._add_param("cascade", str(cascade).lower(), **kwargs)
151
+ kwargs = self._add_param("name", kwargs.pop("name"), **kwargs)
152
+
192
153
  # Handle search
193
154
  elif operation == BackendOperations.SEARCH.value:
194
155
  # Handle fq
195
156
  if (fq := kwargs.pop("fq", None)) is not None:
196
- kwargs["params"]["fq"] = fq
157
+ kwargs = self._add_param("fq", fq, **kwargs)
197
158
 
198
159
  # Add search query
199
160
  if (query := kwargs.pop("query", None)) is not None:
200
- kwargs["params"]["q"] = query
161
+ kwargs = self._add_param("q", query, **kwargs)
201
162
 
202
163
  # Add search filters
203
164
  fq = []
@@ -240,39 +201,91 @@ class ClientDHCoreParametersBuilder(ClientParametersBuilder):
240
201
  fq.append(f"metadata.labels:({labels})")
241
202
 
242
203
  # Add filters
243
- kwargs["params"]["fq"] = fq
204
+ kwargs = self._add_param("fq", fq, **kwargs)
205
+
206
+ return kwargs
207
+
208
+ def set_pagination(self, partial: bool = False, **kwargs) -> dict:
209
+ """
210
+ Ensure pagination parameters are set in kwargs.
211
+
212
+ Parameters
213
+ ----------
214
+ **kwargs : dict
215
+ Keyword arguments to format. May be empty or contain various
216
+ parameters for API operations.
217
+
218
+ Returns
219
+ -------
220
+ dict
221
+ Pagination parameters set in 'params' of kwargs.
222
+ """
223
+ kwargs = self._ensure_params(**kwargs)
224
+
225
+ if "page" not in kwargs["params"]:
226
+ kwargs["params"]["page"] = DEFAULT_START_PAGE
227
+
228
+ if partial:
229
+ return kwargs
230
+
231
+ if "size" not in kwargs["params"]:
232
+ kwargs["params"]["size"] = DEFAULT_SIZE
233
+
234
+ if "sort" not in kwargs["params"]:
235
+ kwargs["params"]["sort"] = DEFAULT_SORT
244
236
 
245
237
  return kwargs
246
238
 
247
239
  @staticmethod
248
- def _set_params(**kwargs) -> dict:
240
+ def read_page_number(**kwargs) -> int:
241
+ """
242
+ Read current page number from kwargs.
243
+
244
+ Parameters
245
+ ----------
246
+ **kwargs : dict
247
+ Keyword arguments to format. May be empty or contain various
248
+ parameters for API operations.
249
+
250
+ Returns
251
+ -------
252
+ int
253
+ Current page number.
249
254
  """
250
- Initialize parameter dictionary with query parameters structure.
255
+ return kwargs["params"]["page"]
251
256
 
252
- Ensures that the parameter dictionary has a 'params' key for
253
- HTTP query parameters. This is a utility method used by all
254
- parameter building methods to guarantee consistent structure.
257
+ @staticmethod
258
+ def increment_page_number(**kwargs) -> dict:
259
+ """
260
+ Increment page number in kwargs.
255
261
 
256
262
  Parameters
257
263
  ----------
258
264
  **kwargs : dict
259
- Keyword arguments to be formatted. May be empty or contain
260
- various parameters for API operations.
265
+ Keyword arguments to format. May be empty or contain various
266
+ parameters for API operations.
261
267
 
262
268
  Returns
263
269
  -------
264
270
  dict
265
- Parameters dictionary with guaranteed 'params' key containing
266
- an empty dict if not already present.
267
-
268
- Notes
269
- -----
270
- This method is called at the beginning of all parameter building
271
- methods to ensure consistent dictionary structure for query
272
- parameter handling.
271
+ Parameters dictionary with incremented 'page' number in 'params'.
273
272
  """
274
- if not kwargs:
275
- kwargs = {}
276
- if "params" not in kwargs:
277
- kwargs["params"] = {}
273
+ kwargs["params"]["page"] += 1
278
274
  return kwargs
275
+
276
+ @staticmethod
277
+ def _filter_none_params(**kwargs) -> dict:
278
+ """
279
+ Filter out None values from kwargs.
280
+
281
+ Parameters
282
+ ----------
283
+ **kwargs : dict
284
+ Keyword arguments to filter.
285
+
286
+ Returns
287
+ -------
288
+ dict
289
+ Filtered kwargs.
290
+ """
291
+ return {k: v for k, v in kwargs.items() if v is not None}