-
Notifications
You must be signed in to change notification settings - Fork 184
feat: create DIRACCommon package for stateless utilities #8287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| name: DIRACCommon Tests | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - integration | ||
| - rel-* | ||
| paths: | ||
| - 'dirac-common/**' | ||
| - '.github/workflows/dirac-common.yml' | ||
| pull_request: | ||
| branches: | ||
| - integration | ||
| - rel-* | ||
| paths: | ||
| - 'dirac-common/**' | ||
| - '.github/workflows/dirac-common.yml' | ||
|
|
||
| jobs: | ||
| test-dirac-common: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Need full history for setuptools_scm | ||
|
|
||
| - uses: prefix-dev/setup-pixi@v0.9.0 | ||
| with: | ||
| run-install: false | ||
| post-cleanup: false | ||
|
|
||
| - name: Apply workarounds | ||
| run: | | ||
| # Workaround for https://github.com/prefix-dev/pixi/issues/3762 | ||
| sed -i.bak 's@editable = true@editable = false@g' dirac-common/pyproject.toml | ||
| rm dirac-common/pyproject.toml.bak | ||
| # Show any changes | ||
| git diff | ||
|
|
||
| - uses: prefix-dev/setup-pixi@v0.9.0 | ||
| with: | ||
| cache: false | ||
| environments: testing | ||
| manifest-path: dirac-common/pyproject.toml | ||
|
|
||
| - name: Run tests with pixi | ||
| run: | | ||
| cd dirac-common | ||
| pixi add --feature testing pytest-github-actions-annotate-failures | ||
| pixi run pytest |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Pin DIRACCommon version in setup.cfg during deployment. | ||
|
|
||
| This script is used during the deployment process to ensure DIRAC | ||
| depends on the exact version of DIRACCommon being released. | ||
| """ | ||
|
|
||
| import re | ||
| import sys | ||
| from pathlib import Path | ||
| import subprocess | ||
|
|
||
|
|
||
| def get_diraccommon_version(): | ||
| """Get the current version of DIRACCommon from setuptools_scm.""" | ||
| result = subprocess.run( | ||
| ["python", "-m", "setuptools_scm"], cwd="dirac-common", capture_output=True, text=True, check=True | ||
| ) | ||
| # Extract version from output like "Guessed Version 9.0.0a65.dev7+g995f95504" | ||
| version_match = re.search(r"Guessed Version (\S+)", result.stdout) | ||
| if not version_match: | ||
| # Try direct output format | ||
| version = result.stdout.strip() | ||
| else: | ||
| version = version_match.group(1) | ||
|
|
||
| # Clean up the version for release (remove dev and git hash parts) | ||
| version = re.sub(r"(\.dev|\+g).+", "", version) | ||
| return version | ||
|
|
||
|
|
||
| def pin_diraccommon_version(version): | ||
| """Pin DIRACCommon to exact version in setup.cfg.""" | ||
| setup_cfg = Path("setup.cfg") | ||
| content = setup_cfg.read_text() | ||
|
|
||
| # Replace the DIRACCommon line with exact version pin | ||
| updated_content = re.sub(r"^(\s*)DIRACCommon\s*$", f"\\1DIRACCommon=={version}", content, flags=re.MULTILINE) | ||
|
|
||
| if content == updated_content: | ||
| print(f"Warning: DIRACCommon line not found or already pinned in setup.cfg") | ||
| return False | ||
|
|
||
| setup_cfg.write_text(updated_content) | ||
| print(f"Pinned DIRACCommon to version {version} in setup.cfg") | ||
| return True | ||
|
|
||
|
|
||
| def main(): | ||
| if len(sys.argv) > 1: | ||
| version = sys.argv[1] | ||
| else: | ||
| version = get_diraccommon_version() | ||
|
|
||
| if pin_diraccommon_version(version): | ||
| print(f"Successfully pinned DIRACCommon to {version}") | ||
| sys.exit(0) | ||
| else: | ||
| print("Failed to pin DIRACCommon version") | ||
| sys.exit(1) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # 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.Utils.ReturnValues`: DIRAC's S_OK/S_ERROR return value system | ||
| - `DIRACCommon.Utils.DErrno`: DIRAC error codes and utilities | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| pip install DIRACCommon | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ```python | ||
| from DIRACCommon.Utils.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. | ||
|
|
||
| ```bash | ||
| pixi install | ||
| pixi run pytest | ||
| ``` | ||
|
|
||
| ## Guidelines for Adding Code | ||
|
|
||
| Code added to DIRACCommon must: | ||
| - Be completely stateless | ||
| - Not import or use any of DIRAC's global objects (`gConfig`, `gLogger`, `gMonitor`, `Operations`) | ||
| - Not establish database connections | ||
| - Not have side effects on import | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| [build-system] | ||
| requires = ["hatchling", "hatch-vcs"] | ||
| build-backend = "hatchling.build" | ||
|
|
||
| [project] | ||
| name = "DIRACCommon" | ||
| description = "Stateless utilities extracted from DIRAC for use by DiracX and other projects" | ||
| readme = "README.md" | ||
| requires-python = ">=3.11" | ||
| license = {text = "GPL-3.0-only"} | ||
| authors = [ | ||
| {name = "DIRAC Collaboration", email = "dirac-dev@cern.ch"}, | ||
| ] | ||
| classifiers = [ | ||
| "Development Status :: 5 - Production/Stable", | ||
| "Intended Audience :: Science/Research", | ||
| "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", | ||
| "Programming Language :: Python :: 3", | ||
| "Topic :: Scientific/Engineering", | ||
| "Topic :: System :: Distributed Computing", | ||
| ] | ||
| dependencies = [ | ||
| "typing-extensions>=4.0.0", | ||
| ] | ||
| dynamic = ["version"] | ||
|
|
||
| [project.optional-dependencies] | ||
| testing = [ | ||
| "pytest>=7.0.0", | ||
| "pytest-cov>=4.0.0", | ||
| ] | ||
|
|
||
| [project.urls] | ||
| Homepage = "https://github.com/DIRACGrid/DIRAC" | ||
| Documentation = "https://dirac.readthedocs.io/" | ||
| "Source Code" = "https://github.com/DIRACGrid/DIRAC" | ||
|
|
||
| [tool.hatch.version] | ||
| source = "vcs" | ||
|
|
||
| [tool.hatch.version.raw-options] | ||
| root = ".." | ||
|
|
||
| [tool.hatch.build.targets.sdist] | ||
| include = [ | ||
| "/src", | ||
| "/tests", | ||
| ] | ||
|
|
||
| [tool.hatch.build.targets.wheel] | ||
| packages = ["src/DIRACCommon"] | ||
|
|
||
| [tool.pytest.ini_options] | ||
| testpaths = ["tests"] | ||
| python_files = "test_*.py" | ||
| python_classes = "Test*" | ||
| python_functions = "test_*" | ||
| addopts = ["-v", "--cov=DIRACCommon", "--cov-report=term-missing"] | ||
|
|
||
| [tool.coverage.run] | ||
| source = ["src/DIRACCommon"] | ||
| omit = ["*/tests/*"] | ||
|
|
||
| [tool.coverage.report] | ||
| exclude_lines = [ | ||
| "pragma: no cover", | ||
| "def __repr__", | ||
| "raise AssertionError", | ||
| "raise NotImplementedError", | ||
| "if __name__ == .__main__.:", | ||
| "if TYPE_CHECKING:", | ||
| ] | ||
|
|
||
| [tool.mypy] | ||
| python_version = "3.11" | ||
| files = ["src/DIRACCommon"] | ||
| strict = true | ||
| warn_return_any = true | ||
| warn_unused_configs = true | ||
| disallow_untyped_defs = true | ||
| disallow_incomplete_defs = true | ||
| check_untyped_defs = true | ||
| no_implicit_optional = true | ||
| warn_redundant_casts = true | ||
| warn_unused_ignores = true | ||
| warn_no_return = true | ||
| warn_unreachable = true | ||
| strict_equality = true | ||
|
|
||
| [tool.ruff] | ||
| line-length = 120 | ||
| target-version = "py311" | ||
| select = [ | ||
| "E", # pycodestyle errors | ||
| "F", # pyflakes | ||
| "B", # flake8-bugbear | ||
| "I", # isort | ||
| "PLE", # pylint errors | ||
| "UP", # pyupgrade | ||
| ] | ||
| ignore = [ | ||
| "B905", # zip without explicit strict parameter | ||
chrisburr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "B008", # do not perform function calls in argument defaults | ||
| "B006", # do not use mutable data structures for argument defaults | ||
| ] | ||
|
|
||
| [tool.ruff.lint.flake8-tidy-imports.banned-api] | ||
| # This ensures DIRACCommon never imports from DIRAC | ||
| "DIRAC" = {msg = "DIRACCommon must not import from DIRAC to avoid global state initialization"} | ||
|
|
||
| [tool.black] | ||
| line-length = 120 | ||
| target-version = ['py311'] | ||
|
|
||
| [tool.isort] | ||
| profile = "black" | ||
| line_length = 120 | ||
|
|
||
| [tool.pixi.workspace] | ||
| channels = ["conda-forge"] | ||
| platforms = ["linux-64", "linux-aarch64", "osx-arm64"] | ||
|
|
||
| [tool.pixi.pypi-dependencies] | ||
| DIRACCommon = { path = ".", editable = true } | ||
|
|
||
| [tool.pixi.feature.testing.tasks.pytest] | ||
| cmd = "pytest" | ||
|
|
||
| [tool.pixi.environments] | ||
| default = { solve-group = "default" } | ||
| testing = { features = ["testing"], solve-group = "default" } | ||
|
|
||
| [tool.pixi.tasks] | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.