DIRACCommon
Stateless utilities extracted from DIRAC for use by DiracX and other projects without triggering DIRAC's global state initialization.
Purpose
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.
Contents
DIRACCommon.Core.Utilities.ReturnValues: DIRAC's S_OK/S_ERROR return value systemDIRACCommon.Core.Utilities.DErrno: DIRAC error codes and utilitiesDIRACCommon.Core.Utilities.ClassAd.ClassAdLight: JDL parsing utilitiesDIRACCommon.Core.Utilities.TimeUtilities: Time and date utilitiesDIRACCommon.Core.Utilities.StateMachine: State machine utilitiesDIRACCommon.Core.Utilities.JDL: JDL parsing utilitiesDIRACCommon.Core.Utilities.List: List manipulation utilitiesDIRACCommon.ConfigurationSystem.Client.Helpers.Resources: Platform compatibility utilitiesDIRACCommon.WorkloadManagementSystem.Client.JobStatus: Job status constants and state machinesDIRACCommon.WorkloadManagementSystem.Client.JobState.JobManifest: Job manifest utilitiesDIRACCommon.WorkloadManagementSystem.DB.JobDBUtils: Job database utilitiesDIRACCommon.WorkloadManagementSystem.Utilities.JobModel: Pydantic-based job modelsDIRACCommon.WorkloadManagementSystem.Utilities.JobStatusUtility: Job status utilitiesDIRACCommon.WorkloadManagementSystem.Utilities.ParametricJob: Parametric job utilities
Installation
pip install DIRACCommon
Usage
Basic Usage
from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
def my_function():
if success:
return S_OK("Operation successful")
else:
return S_ERROR("Operation failed")
Development
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.
pixi install
pixi run pytest
Migrating Code to DIRACCommon
This section documents the proper pattern for moving code from DIRAC to DIRACCommon to enable shared usage by DiracX and other projects.
Migration Pattern
The migration follows a specific pattern to maintain backward compatibility while making code stateless:
- Move core functionality to DIRACCommon - Create the stateless version
- Update DIRAC module - Make it a backward compatibility wrapper
- Move and update tests - Ensure both versions are tested
- Verify migration - Test both import paths work correctly
Step-by-Step Migration Process
1. Create DIRACCommon Module
Create the new module in DIRACCommon with the exact same directory structure as DIRAC:
# Example: Moving from src/DIRAC/ConfigurationSystem/Client/Helpers/Resources.py
# Create: dirac-common/src/DIRACCommon/ConfigurationSystem/Client/Helpers/Resources.py
2. Make Code Stateless
❌ Remove these dependencies:
# DON'T import these in DIRACCommon
from DIRAC import gConfig, gLogger, gMonitor, Operations
from DIRAC.Core.Security import getProxyInfo
# Any other DIRAC global state
✅ Use these instead:
# Use DIRACCommon's own utilities
from DIRACCommon.Core.Utilities.ReturnValues import S_OK, S_ERROR
from DIRACCommon.Core.Utilities.DErrno import strerror
# Accept configuration data as parameters
def my_function(data, config_dict):
# Use config_dict instead of gConfig.getOptionsDict()
pass
3. Handle Configuration Data
❌ Don't do this:
# DIRACCommon function taking config object
def getDIRACPlatform(OSList, config):
result = config.getOptionsDict("/Resources/Computing/OSCompatibility")
# ...
✅ Do this instead:
# DIRACCommon function taking configuration data directly
def getDIRACPlatform(osList: str | list[str], osCompatibilityDict: dict[str, set[str]]) -> DReturnType[list[str]]:
if not osCompatibilityDict:
return S_ERROR("OS compatibility info not found")
# Use osCompatibilityDict directly
# ...
4. Update DIRAC Module for Backward Compatibility
Transform the original DIRAC module into a backward compatibility wrapper:
"""Backward compatibility wrapper - moved to DIRACCommon
This module has been moved to DIRACCommon.ConfigurationSystem.Client.Helpers.Resources
to avoid circular dependencies and allow DiracX to use these utilities without
triggering DIRAC's global state initialization.
All exports are maintained for backward compatibility.
"""
# Re-export everything from DIRACCommon for backward compatibility
from DIRACCommon.ConfigurationSystem.Client.Helpers.Resources import (
getDIRACPlatform as _getDIRACPlatform,
_platformSortKey,
)
from DIRAC import S_ERROR, S_OK, gConfig
def getDIRACPlatform(OSList):
"""Get standard DIRAC platform(s) compatible with the argument.
Backward compatibility wrapper that uses gConfig.
"""
result = gConfig.getOptionsDict("/Resources/Computing/OSCompatibility")
if not (result["OK"] and result["Value"]):
return S_ERROR("OS compatibility info not found")
# Convert string values to sets for DIRACCommon function
platformsDict = {k: set(v.replace(" ", "").split(",")) for k, v in result["Value"].items()}
for k, v in platformsDict.items():
if k not in v:
v.add(k)
return _getDIRACPlatform(OSList, platformsDict)
# Re-export the helper function
_platformSortKey = _platformSortKey
5. Move and Update Tests
Create DIRACCommon tests:
# dirac-common/tests/ConfigurationSystem/Client/Helpers/test_Resources.py
from DIRACCommon.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
def test_getDIRACPlatform():
# Test with configuration data directly
osCompatibilityDict = {
"plat1": {"OS1", "OS2"},
"plat2": {"OS3", "OS4"}
}
result = getDIRACPlatform("OS1", osCompatibilityDict)
assert result["OK"]
assert "plat1" in result["Value"]
Update DIRAC tests:
# src/DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py
from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
def test_getDIRACPlatform():
# Test backward compatibility wrapper
# (existing tests should continue to work)
pass
6. Create Directory Structure
Ensure the DIRACCommon directory structure mirrors DIRAC exactly:
dirac-common/src/DIRACCommon/
├── ConfigurationSystem/
│ ├── __init__.py
│ └── Client/
│ ├── __init__.py
│ └── Helpers/
│ ├── __init__.py
│ └── Resources.py
└── tests/
└── ConfigurationSystem/
├── __init__.py
└── Client/
├── __init__.py
└── Helpers/
├── __init__.py
└── test_Resources.py
Requirements for DIRACCommon Code
Code in DIRACCommon MUST be:
- Completely stateless - No global variables or state
- No DIRAC dependencies - Cannot import from DIRAC
- No global state access - Cannot use
gConfig,gLogger,gMonitor, etc. - No database connections - Cannot establish DB connections
- No side effects on import - Importing should not trigger any initialization
- Pure functions - Functions should be deterministic and side-effect free
Configuration Data Handling
When DIRACCommon functions need configuration data:
- Accept data as parameters - Don't accept config objects
- Use specific data types - Pass dictionaries, not config objects
- Let DIRAC wrapper handle gConfig - DIRAC gets data and passes it to DIRACCommon
Example Migration
See the migration of getDIRACPlatform in:
dirac-common/src/DIRACCommon/ConfigurationSystem/Client/Helpers/Resources.pysrc/DIRAC/ConfigurationSystem/Client/Helpers/Resources.py
This demonstrates the complete pattern from stateless DIRACCommon implementation to backward-compatible DIRAC wrapper.
Testing the Migration
After migration, verify:
- DIRACCommon tests pass -
pixi run python -m pytest dirac-common/tests/ - DIRAC tests pass -
pixi run python -m pytest src/DIRAC/ - Both import paths work:
# DIRACCommon (stateless) from DIRACCommon.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform # DIRAC (backward compatibility) from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getDIRACPlatform
- No linting errors - All code should pass linting checks
Metadata
Release files for DIRACCommon 9.1.17
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| diraccommon-9.1.17.tar.gz | 50.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| diraccommon-9.1.17-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 99.6 kB
Release files / diraccommon-9.1.17.tar.gz
| Download URL | diraccommon-9.1.17.tar.gz |
|---|---|
| Size | 50.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
080d223e2d93c9a16f1eefb5eabbf881e779a62889e4b09bc744f3c98f545285
|
|
BLAKE2b-256 checksum How to use checksums |
0afc1e3a3f8720b4b6eff435fbfda1085e38e57960a5f91ffcdaf288c2961713
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency logRelease files / diraccommon-9.1.17-py3-none-any.whl
| Download URL | diraccommon-9.1.17-py3-none-any.whl |
|---|---|
| Size | 49.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4171031cd3bd2ab6193c11477edf8728d4d3a597cd6dc54e747d3e0ad00cd2ae
|
|
BLAKE2b-256 checksum How to use checksums |
2f422352bff9740601c365aafdbcd2e3dcc6c9514fd0c5c411613945904e4569
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.
Transparency log