DIRACCommon 9.0.0a67__py3-none-any.whl → 9.0.0a68__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.
@@ -0,0 +1,52 @@
1
+ """Platform utilities for DIRAC platform compatibility and management.
2
+
3
+ This module provides functions for working with DIRAC platforms and OS compatibility.
4
+ """
5
+ import re
6
+
7
+ from DIRACCommon.Core.Utilities.ReturnValues import S_ERROR, S_OK, DReturnType
8
+
9
+
10
+ def getDIRACPlatform(osList: list[str], osCompatibilityDict: dict[str, set[str]]) -> DReturnType[list[str]]:
11
+ """Get standard DIRAC platform(s) compatible with the argument.
12
+
13
+ NB: The returned value is a list, ordered by numeric components in the platform.
14
+ In practice the "highest" version (which should be the most "desirable" one is returned first)
15
+
16
+ :param list osList: list of platforms defined by resource providers
17
+ :param dict osCompatibilityDict: dictionary with OS compatibility information
18
+ :return: a list of DIRAC platforms that can be specified in job descriptions
19
+ """
20
+
21
+ if not osCompatibilityDict:
22
+ return S_ERROR("OS compatibility info not found")
23
+
24
+ # making an OS -> platforms dict
25
+ os2PlatformDict = dict()
26
+ for platform, osItems in osCompatibilityDict.items():
27
+ for osItem in osItems:
28
+ os2PlatformDict.setdefault(osItem, set()).add(platform)
29
+
30
+ platforms = set()
31
+ for os in osList:
32
+ platforms |= os2PlatformDict.get(os, set())
33
+
34
+ if not platforms:
35
+ return S_ERROR(f"No compatible DIRAC platform found for {','.join(osList)}")
36
+
37
+ return S_OK(sorted(platforms, key=_platformSortKey, reverse=True))
38
+
39
+
40
+ def _platformSortKey(version: str) -> list[str]:
41
+ # Loosely based on distutils.version.LooseVersion
42
+ parts = []
43
+ for part in re.split(r"(\d+|[a-z]+|\.| -)", version.lower()):
44
+ if not part or part == ".":
45
+ continue
46
+ if part[:1] in "0123456789":
47
+ part = part.zfill(8)
48
+ else:
49
+ while parts and parts[-1] == "00000000":
50
+ parts.pop()
51
+ parts.append(part)
52
+ return parts
@@ -0,0 +1,3 @@
1
+ """
2
+ DIRACCommon.ConfigurationSystem.Client.Helpers - Configuration system helper functions
3
+ """
@@ -0,0 +1,3 @@
1
+ """
2
+ DIRACCommon.ConfigurationSystem.Client - Configuration system client components
3
+ """
@@ -0,0 +1,3 @@
1
+ """
2
+ DIRACCommon.ConfigurationSystem - Configuration system components
3
+ """
@@ -0,0 +1,281 @@
1
+ Metadata-Version: 2.4
2
+ Name: DIRACCommon
3
+ Version: 9.0.0a68
4
+ Summary: Stateless utilities extracted from DIRAC for use by DiracX and other projects
5
+ Project-URL: Homepage, https://github.com/DIRACGrid/DIRAC
6
+ Project-URL: Documentation, https://dirac.readthedocs.io/
7
+ Project-URL: Source Code, https://github.com/DIRACGrid/DIRAC
8
+ Author-email: DIRAC Collaboration <dirac-dev@cern.ch>
9
+ License: GPL-3.0-only
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering
15
+ Classifier: Topic :: System :: Distributed Computing
16
+ Requires-Python: >=3.11
17
+ Requires-Dist: diraccfg
18
+ Requires-Dist: pydantic>=2.0.0
19
+ Requires-Dist: typing-extensions>=4.0.0
20
+ Provides-Extra: testing
21
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'testing'
22
+ Requires-Dist: pytest>=7.0.0; extra == 'testing'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # DIRACCommon
26
+
27
+ Stateless utilities extracted from DIRAC for use by DiracX and other projects without triggering DIRAC's global state initialization.
28
+
29
+ ## Purpose
30
+
31
+ This package solves the circular dependency issue where DiracX needs DIRAC utilities but importing DIRAC triggers global state initialization. DIRACCommon contains only stateless utilities that can be safely imported without side effects.
32
+
33
+ ## Contents
34
+
35
+ - `DIRACCommon.Core.Utilities.ReturnValues`: DIRAC's S_OK/S_ERROR return value system
36
+ - `DIRACCommon.Core.Utilities.DErrno`: DIRAC error codes and utilities
37
+ - `DIRACCommon.Core.Utilities.ClassAd.ClassAdLight`: JDL parsing utilities
38
+ - `DIRACCommon.Core.Utilities.TimeUtilities`: Time and date utilities
39
+ - `DIRACCommon.Core.Utilities.StateMachine`: State machine utilities
40
+ - `DIRACCommon.Core.Utilities.JDL`: JDL parsing utilities
41
+ - `DIRACCommon.Core.Utilities.List`: List manipulation utilities
42
+ - `DIRACCommon.ConfigurationSystem.Client.Helpers.Resources`: Platform compatibility utilities
43
+ - `DIRACCommon.WorkloadManagementSystem.Client.JobStatus`: Job status constants and state machines
44
+ - `DIRACCommon.WorkloadManagementSystem.Client.JobState.JobManifest`: Job manifest utilities
45
+ - `DIRACCommon.WorkloadManagementSystem.DB.JobDBUtils`: Job database utilities
46
+ - `DIRACCommon.WorkloadManagementSystem.Utilities.JobModel`: Pydantic-based job models
47
+ - `DIRACCommon.WorkloadManagementSystem.Utilities.JobStatusUtility`: Job status utilities
48
+ - `DIRACCommon.WorkloadManagementSystem.Utilities.ParametricJob`: Parametric job utilities
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install DIRACCommon
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ ### Basic Usage
59
+
60
+ ```python
61
+ from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
62
+
63
+ def my_function():
64
+ if success:
65
+ return S_OK("Operation successful")
66
+ else:
67
+ return S_ERROR("Operation failed")
68
+ ```
69
+
70
+ ## Development
71
+
72
+ This package is part of the DIRAC project and shares its version number. When DIRAC is released, DIRACCommon is also released with the same version.
73
+
74
+ ```bash
75
+ pixi install
76
+ pixi run pytest
77
+ ```
78
+
79
+ ## Migrating Code to DIRACCommon
80
+
81
+ This section documents the proper pattern for moving code from DIRAC to DIRACCommon to enable shared usage by DiracX and other projects.
82
+
83
+ ### Migration Pattern
84
+
85
+ The migration follows a specific pattern to maintain backward compatibility while making code stateless:
86
+
87
+ 1. **Move core functionality to DIRACCommon** - Create the stateless version
88
+ 2. **Update DIRAC module** - Make it a backward compatibility wrapper
89
+ 3. **Move and update tests** - Ensure both versions are tested
90
+ 4. **Verify migration** - Test both import paths work correctly
91
+
92
+ ### Step-by-Step Migration Process
93
+
94
+ #### 1. Create DIRACCommon Module
95
+
96
+ Create the new module in DIRACCommon with the **exact same directory structure** as DIRAC:
97
+
98
+ ```bash
99
+ # Example: Moving from src/DIRAC/ConfigurationSystem/Client/Helpers/Resources.py
100
+ # Create: dirac-common/src/DIRACCommon/ConfigurationSystem/Client/Helpers/Resources.py
101
+ ```
102
+
103
+ #### 2. Make Code Stateless
104
+
105
+ **❌ Remove these dependencies:**
106
+ ```python
107
+ # DON'T import these in DIRACCommon
108
+ from DIRAC import gConfig, gLogger, gMonitor, Operations
109
+ from DIRAC.Core.Security import getProxyInfo
110
+ # Any other DIRAC global state
111
+ ```
112
+
113
+ **✅ Use these instead:**
114
+ ```python
115
+ # Use DIRACCommon's own utilities
116
+ from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
117
+ from DIRACCommon.Core.Utilities.DErrno import strerror
118
+
119
+ # Accept configuration data as parameters
120
+ def my_function(data, config_dict):
121
+ # Use config_dict instead of gConfig.getOptionsDict()
122
+ pass
123
+ ```
124
+
125
+ #### 3. Handle Configuration Data
126
+
127
+ **❌ Don't do this:**
128
+ ```python
129
+ # DIRACCommon function taking config object
130
+ def getDIRACPlatform(OSList, config):
131
+ result = config.getOptionsDict("/Resources/Computing/OSCompatibility")
132
+ # ...
133
+ ```
134
+
135
+ **✅ Do this instead:**
136
+ ```python
137
+ # DIRACCommon function taking configuration data directly
138
+ def getDIRACPlatform(osList: str | list[str], osCompatibilityDict: dict[str, set[str]]) -> DReturnType[list[str]]:
139
+ if not osCompatibilityDict:
140
+ return S_ERROR("OS compatibility info not found")
141
+ # Use osCompatibilityDict directly
142
+ # ...
143
+ ```
144
+
145
+ #### 4. Update DIRAC Module for Backward Compatibility
146
+
147
+ Transform the original DIRAC module into a backward compatibility wrapper:
148
+
149
+ ```python
150
+ """Backward compatibility wrapper - moved to DIRACCommon
151
+
152
+ This module has been moved to DIRACCommon.ConfigurationSystem.Client.Helpers.Resources
153
+ to avoid circular dependencies and allow DiracX to use these utilities without
154
+ triggering DIRAC's global state initialization.
155
+
156
+ All exports are maintained for backward compatibility.
157
+ """
158
+
159
+ # Re-export everything from DIRACCommon for backward compatibility
160
+ from DIRACCommon.ConfigurationSystem.Client.Helpers.Resources import (
161
+ getDIRACPlatform as _getDIRACPlatform,
162
+ _platformSortKey,
163
+ )
164
+
165
+ from DIRAC import S_ERROR, S_OK, gConfig
166
+
167
+ def getDIRACPlatform(OSList):
168
+ """Get standard DIRAC platform(s) compatible with the argument.
169
+
170
+ Backward compatibility wrapper that uses gConfig.
171
+ """
172
+ result = gConfig.getOptionsDict("/Resources/Computing/OSCompatibility")
173
+ if not (result["OK"] and result["Value"]):
174
+ return S_ERROR("OS compatibility info not found")
175
+
176
+ # Convert string values to sets for DIRACCommon function
177
+ platformsDict = {k: set(v.replace(" ", "").split(",")) for k, v in result["Value"].items()}
178
+ for k, v in platformsDict.items():
179
+ if k not in v:
180
+ v.add(k)
181
+
182
+ return _getDIRACPlatform(OSList, platformsDict)
183
+
184
+ # Re-export the helper function
185
+ _platformSortKey = _platformSortKey
186
+ ```
187
+
188
+ #### 5. Move and Update Tests
189
+
190
+ **Create DIRACCommon tests:**
191
+ ```python
192
+ # dirac-common/tests/ConfigurationSystem/Client/Helpers/test_Resources.py
193
+ from DIRACCommon.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
194
+
195
+ def test_getDIRACPlatform():
196
+ # Test with configuration data directly
197
+ osCompatibilityDict = {
198
+ "plat1": {"OS1", "OS2"},
199
+ "plat2": {"OS3", "OS4"}
200
+ }
201
+ result = getDIRACPlatform("OS1", osCompatibilityDict)
202
+ assert result["OK"]
203
+ assert "plat1" in result["Value"]
204
+ ```
205
+
206
+ **Update DIRAC tests:**
207
+ ```python
208
+ # src/DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py
209
+ from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
210
+
211
+ def test_getDIRACPlatform():
212
+ # Test backward compatibility wrapper
213
+ # (existing tests should continue to work)
214
+ pass
215
+ ```
216
+
217
+ #### 6. Create Directory Structure
218
+
219
+ Ensure the DIRACCommon directory structure mirrors DIRAC exactly:
220
+
221
+ ```bash
222
+ dirac-common/src/DIRACCommon/
223
+ ├── ConfigurationSystem/
224
+ │ ├── __init__.py
225
+ │ └── Client/
226
+ │ ├── __init__.py
227
+ │ └── Helpers/
228
+ │ ├── __init__.py
229
+ │ └── Resources.py
230
+ └── tests/
231
+ └── ConfigurationSystem/
232
+ ├── __init__.py
233
+ └── Client/
234
+ ├── __init__.py
235
+ └── Helpers/
236
+ ├── __init__.py
237
+ └── test_Resources.py
238
+ ```
239
+
240
+ ### Requirements for DIRACCommon Code
241
+
242
+ Code in DIRACCommon **MUST** be:
243
+
244
+ - **Completely stateless** - No global variables or state
245
+ - **No DIRAC dependencies** - Cannot import from DIRAC
246
+ - **No global state access** - Cannot use `gConfig`, `gLogger`, `gMonitor`, etc.
247
+ - **No database connections** - Cannot establish DB connections
248
+ - **No side effects on import** - Importing should not trigger any initialization
249
+ - **Pure functions** - Functions should be deterministic and side-effect free
250
+
251
+ ### Configuration Data Handling
252
+
253
+ When DIRACCommon functions need configuration data:
254
+
255
+ 1. **Accept data as parameters** - Don't accept config objects
256
+ 2. **Use specific data types** - Pass dictionaries, not config objects
257
+ 3. **Let DIRAC wrapper handle gConfig** - DIRAC gets data and passes it to DIRACCommon
258
+
259
+ ### Example Migration
260
+
261
+ See the migration of `getDIRACPlatform` in:
262
+ - `dirac-common/src/DIRACCommon/ConfigurationSystem/Client/Helpers/Resources.py`
263
+ - `src/DIRAC/ConfigurationSystem/Client/Helpers/Resources.py`
264
+
265
+ This demonstrates the complete pattern from stateless DIRACCommon implementation to backward-compatible DIRAC wrapper.
266
+
267
+ ### Testing the Migration
268
+
269
+ After migration, verify:
270
+
271
+ 1. **DIRACCommon tests pass** - `pixi run python -m pytest dirac-common/tests/`
272
+ 2. **DIRAC tests pass** - `pixi run python -m pytest src/DIRAC/`
273
+ 3. **Both import paths work**:
274
+ ```python
275
+ # DIRACCommon (stateless)
276
+ from DIRACCommon.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
277
+
278
+ # DIRAC (backward compatibility)
279
+ from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
280
+ ```
281
+ 4. **No linting errors** - All code should pass linting checks
@@ -1,4 +1,8 @@
1
1
  DIRACCommon/__init__.py,sha256=o31FFvmIiU2Wsc9nfsPZVaXYK9d3KTN0vOa8mZS6x5E,587
2
+ DIRACCommon/ConfigurationSystem/__init__.py,sha256=zD7hqGhEaKikUOFQ9fYd-T1nGE3A7hBQnSbZMNdde_Q,74
3
+ DIRACCommon/ConfigurationSystem/Client/__init__.py,sha256=wc_AKSzmjk_56P_CMkihYaEX4RUiED3XZCLcwZ9NPoY,88
4
+ DIRACCommon/ConfigurationSystem/Client/Helpers/Resources.py,sha256=N8gRrfv3Ai-tzloNTvCb3jOMHj7PkMzKiWd-MmWu2vA,1904
5
+ DIRACCommon/ConfigurationSystem/Client/Helpers/__init__.py,sha256=gCIB_25s-6H77hwho9ex_nUnMX2vvzg1Rr33u1-mLkI,95
2
6
  DIRACCommon/Core/__init__.py,sha256=Kv_Rkbm9hOPmHSnTG0_i7QR5Tck8bldITONhsoT2syg,33
3
7
  DIRACCommon/Core/Utilities/DErrno.py,sha256=LUaIcKkjuioTMO3O7H9T9Pk5pHUS63Nzx3FcaP40n5c,7998
4
8
  DIRACCommon/Core/Utilities/JDL.py,sha256=z4RID730tbCmbgldKfhSFc9ADfXDhUfjaBG8RpuK2Bs,6724
@@ -20,6 +24,6 @@ DIRACCommon/WorkloadManagementSystem/Utilities/JobModel.py,sha256=kpvsxQnR-j9Y9I
20
24
  DIRACCommon/WorkloadManagementSystem/Utilities/JobStatusUtility.py,sha256=Kf4o1bp25JLsRb-Vsc4NuM6w1Io2hg_ALtIyqBk-Qhw,3628
21
25
  DIRACCommon/WorkloadManagementSystem/Utilities/ParametricJob.py,sha256=iYd29TgGXZk31pQLPw_frIhcmZB9X-RmuDmIRxzgiww,7405
22
26
  DIRACCommon/WorkloadManagementSystem/Utilities/__init__.py,sha256=XMOUD0OcPVo-mjuA0vU-mbtf9K0kBMy5I5sELrX3HEs,53
23
- diraccommon-9.0.0a67.dist-info/METADATA,sha256=NA1PLIfXlFQ4tWmuf1m_7mSvSlHBuHVudhsOIC_VRDs,2575
24
- diraccommon-9.0.0a67.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- diraccommon-9.0.0a67.dist-info/RECORD,,
27
+ diraccommon-9.0.0a68.dist-info/METADATA,sha256=ls6roTiA24Si3-mNyiqPDfXr13szs1e9tnVjzGH-n5I,9738
28
+ diraccommon-9.0.0a68.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ diraccommon-9.0.0a68.dist-info/RECORD,,
@@ -1,74 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: DIRACCommon
3
- Version: 9.0.0a67
4
- Summary: Stateless utilities extracted from DIRAC for use by DiracX and other projects
5
- Project-URL: Homepage, https://github.com/DIRACGrid/DIRAC
6
- Project-URL: Documentation, https://dirac.readthedocs.io/
7
- Project-URL: Source Code, https://github.com/DIRACGrid/DIRAC
8
- Author-email: DIRAC Collaboration <dirac-dev@cern.ch>
9
- License: GPL-3.0-only
10
- Classifier: Development Status :: 5 - Production/Stable
11
- Classifier: Intended Audience :: Science/Research
12
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Topic :: Scientific/Engineering
15
- Classifier: Topic :: System :: Distributed Computing
16
- Requires-Python: >=3.11
17
- Requires-Dist: diraccfg
18
- Requires-Dist: pydantic>=2.0.0
19
- Requires-Dist: typing-extensions>=4.0.0
20
- Provides-Extra: testing
21
- Requires-Dist: pytest-cov>=4.0.0; extra == 'testing'
22
- Requires-Dist: pytest>=7.0.0; extra == 'testing'
23
- Description-Content-Type: text/markdown
24
-
25
- # DIRACCommon
26
-
27
- Stateless utilities extracted from DIRAC for use by DiracX and other projects without triggering DIRAC's global state initialization.
28
-
29
- ## Purpose
30
-
31
- This package solves the circular dependency issue where DiracX needs DIRAC utilities but importing DIRAC triggers global state initialization. DIRACCommon contains only stateless utilities that can be safely imported without side effects.
32
-
33
- ## Contents
34
-
35
- - `DIRACCommon.Core.Utilities.ReturnValues`: DIRAC's S_OK/S_ERROR return value system
36
- - `DIRACCommon.Core.Utilities.DErrno`: DIRAC error codes and utilities
37
- - `DIRACCommon.Core.Utilities.ClassAd.ClassAdLight`: JDL parsing utilities
38
- - `DIRACCommon.WorkloadManagementSystem.DB.JobDBUtils`: Job database utilities
39
- - `DIRACCommon.WorkloadManagementSystem.Utilities.ParametricJob`: Parametric job utilities
40
-
41
- ## Installation
42
-
43
- ```bash
44
- pip install DIRACCommon
45
- ```
46
-
47
- ## Usage
48
-
49
- ```python
50
- from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
51
-
52
- def my_function():
53
- if success:
54
- return S_OK("Operation successful")
55
- else:
56
- return S_ERROR("Operation failed")
57
- ```
58
-
59
- ## Development
60
-
61
- This package is part of the DIRAC project and shares its version number. When DIRAC is released, DIRACCommon is also released with the same version.
62
-
63
- ```bash
64
- pixi install
65
- pixi run pytest
66
- ```
67
-
68
- ## Guidelines for Adding Code
69
-
70
- Code added to DIRACCommon must:
71
- - Be completely stateless
72
- - Not import or use any of DIRAC's global objects (`gConfig`, `gLogger`, `gMonitor`, `Operations`)
73
- - Not establish database connections
74
- - Not have side effects on import