Skip to content

Commit

Permalink
👽 📦 Update packaging for Poetry 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
shnizzedy committed Jan 10, 2025
1 parent 88dfbd3 commit 6d9ce13
Show file tree
Hide file tree
Showing 6 changed files with 792 additions and 551 deletions.
7 changes: 6 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ repos:
hooks:
- id: poetry-check
- id: poetry-lock
args: [--no-update]

- repo: local
hooks:
- id: store-optional-dependencies
name: Store optional dependencies
entry: ./src/cpac/helpers/store_optional_dependencies.py
language: python
additional_dependencies: [packaging]
always_run: true
- id: update-README
name: Update README from usage string
entry: ./.pre-commit-hooks/update_README.py
Expand Down
1,165 changes: 675 additions & 490 deletions poetry.lock

Large diffs are not rendered by default.

115 changes: 57 additions & 58 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
[project]
name = "cpac"
description = "C-PAC Python Package"
authors = [{name = "C-PAC developers", email = "cpac@cnl.childmind.org"}]
license = "MIT"
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Topic :: Scientific/Engineering :: Bio-Informatics"
]
requires-python = ">=3.10,<4.0"
dependencies = [
"docker>=7.1.0",
"dockerpty",
"docker-pycreds",
"pandas>=0.23.4",
"poetry>=2.0.0",
"pyyaml",
"rich",
"semver",
"spython>=0.3.0",
"tabulate>=0.8.6",
"tornado",
"websocket-client"
]
readme = "README.rst"
version = "1.8.8.dev1"

[project.optional-dependencies]
dev = ["coveralls", "pytest", "pytest-remotedata>=0.3.2", "pytest-runner", "sphinx"]
gradients = []
testing = ["alabaster", "imagesize", "pytest", "pytest-cov", "pytest-runner", "sphinx"]
tsconcat = [
"ba-tsconcat>=0.1.2,<0.2.0; python_version >= '3.11' and python_version < '4.0'",
"bids2table==0.1.0",
"elbow==0.1.1",
"imagesize",
"nibabel==5.3.2",
"numpy>=1.26.3,<2.0.0",
"pandas==2.2.2",
"pyarrow==18.1.0"
]

[project.scripts]
cpac = "cpac.__main__:run"

[project.urls]
documentation = "https://fcp-indi.github.io/docs/latest/user/cpac"
repository = "https://github.com/FCP-INDI/cpac"

[build-system]
requires = ["poetry-core>=1.0.0"]
requires = ["poetry-core>=2.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.aliases]
Expand Down Expand Up @@ -42,63 +96,7 @@ no-vcs = "1"
formats = "bdist_wheel"

[tool.poetry]
name = "cpac"
description = "C-PAC Python Package"
authors = ["C-PAC developers <cpac@cnl.childmind.org>"]
license = "MIT"
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Topic :: Scientific/Engineering :: Bio-Informatics"
]
documentation = "https://fcp-indi.github.io/docs/latest/user/cpac"
readme = "README.rst"
repository = "https://github.com/FCP-INDI/cpac"
version = "1.8.8.dev1"

[tool.poetry.dependencies]
python = ">=3.10,<4.0"
docker = ">=7.1.0"
dockerpty = "*"
docker-pycreds = "*"
pandas = [
{version = ">=0.23.4"},
{version = "2.2.2", markers = "python_version >= '3.11' and python_version < '4.0' and extra == 'tsconcat'"}
]
poetry = ">=1.8.2"
pyyaml = "*"
rich = "*"
semver = "*"
spython = ">=0.3.0"
tabulate = ">=0.8.6"
tornado = "*"
websocket-client = "*"
alabaster = {version = "*", optional = true}
ba-tsconcat = {version = ">=0.1.2,<0.2.0", optional = true, markers = "python_version >= '3.11' and python_version < '4.0'"}
bids2table = {version = "0.1.0", markers = "extra == 'tsconcat'"}
coveralls = {version = "*", optional = true}
elbow = {version = "0.1.1", markers = "extra == 'tsconcat'"}
imagesize = {version = "*", optional = true}
nibabel = {version = "5.3.2", markers = "extra == 'tsconcat'"}
pyarrow = {version = "18.1.0", markers = "extra == 'tsconcat'"}
pytest = {version = "*", optional = true}
pytest-cov = {version = "*", optional = true}
pytest-remotedata = {version = ">=0.3.2", optional = true}
pytest-runner = {version = "*", optional = true}
sphinx = {version = "*", optional = true}

[tool.poetry.extras]
dev = ["coveralls", "pytest", "pytest-remotedata", "pytest-runner", "sphinx"]
gradients = []
testing = ["alabaster", "imagesize", "pytest", "pytest-cov", "pytest-runner", "sphinx"]
tsconcat = ["ba-tsconcat"]

[tool.poetry.scripts]
cpac = "cpac.__main__:run"
requires-poetry = ">=2.0"

[tool.pytest.ini_options]
addopts = "-s"
Expand All @@ -121,6 +119,7 @@ extend-select = ["A", "C4", "D", "G", "I", "ICN", "NPY", "PL", "RET", "RSE", "RU

[tool.ruff.lint.isort]
combine-as-imports = true
extra-standard-library = ["tomllib"]
force-sort-within-sections = true
known-first-party = ["cpac"]
no-lines-before = ["collab", "other-first-party", "local-folder"]
Expand Down
41 changes: 41 additions & 0 deletions src/cpac/helpers/store_optional_dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""Store optional dependencies for dynamic metadata access."""

from itertools import chain
from pathlib import Path
from pickle import dump, load
import tomllib
from typing import cast

from packaging.requirements import Requirement

PICKLE_PATH = Path(__file__).parents[1] / "optional_dependencies.pkl"


def store_optional_dependencies(output_path: str) -> None:
"""Store optional dependencies."""
# Extract optional dependencies
with open("pyproject.toml", "rb") as f:
toml_data = tomllib.load(f)
optional_deps: dict[str, Requirement] = {}
reqs = [
Requirement(req)
for req in chain.from_iterable(
toml_data.get("project", {}).get("optional-dependencies", {}).values()
)
]
for req in reqs:
if req.name in optional_deps:
optional_deps[req.name].specifier &= req.specifier
else:
optional_deps[req.name] = req

with open(output_path, "rb") as f:
existing_optional_deps = cast(dict[str, Requirement], load(f))
if not optional_deps == existing_optional_deps:
with open(output_path, "wb") as f:
dump(optional_deps, f)


if __name__ == "__main__":
store_optional_dependencies(str(PICKLE_PATH))
Binary file added src/cpac/optional_dependencies.pkl
Binary file not shown.
15 changes: 13 additions & 2 deletions src/cpac/utils/bare_wrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from argparse import _SubParsersAction, ArgumentParser, HelpFormatter, REMAINDER
from dataclasses import dataclass
from importlib.metadata import requires
from importlib.resources import files
from logging import ERROR, log
from pathlib import Path
import pickle
from shutil import which
from subprocess import call as sub_call, CalledProcessError
from sys import exit as sys_exit, version_info
Expand Down Expand Up @@ -132,7 +135,15 @@ def helpstring(self):
@property
def package_info(self) -> Optional[Requirement]:
"""Return metadata about how a package is required for this version of cpac."""
return self.requirements().get(self.package)
pkg_info = self.requirements().get(self.package)
if not pkg_info:
optional_deps = Path(
str(files("cpac").joinpath("optional_dependencies.pkl"))
)
if optional_deps.exists():
with optional_deps.open("rb") as _pickle:
pkg_info = pickle.load(_pickle).get(self.package)
return pkg_info

@classmethod
def requirements(cls) -> dict[str, Requirement]:
Expand Down Expand Up @@ -172,7 +183,7 @@ def version(self) -> str:
"""Return the supported version(s) of the wrapped package."""
if self.package_info:
if self.package_info.specifier:
return self.package_info.specifier
return str(self.package_info.specifier)
return getattr(self.package_info, "url", "*")
return "*"

Expand Down

0 comments on commit 6d9ce13

Please sign in to comment.