Skip to content

Commit 1446dee

Browse files
fix: typing, add pyrefly, migrate to pixi
1 parent 50d05de commit 1446dee

4 files changed

Lines changed: 82 additions & 37 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ __pycache__/
33
*.py[cod]
44
*$py.class
55

6+
pixi.lock
7+
68
# C extensions
79
*.so
810

@@ -159,4 +161,4 @@ cython_debug/
159161
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
160162
#.idea/
161163

162-
poetry.lock
164+
poetry.lock

pyproject.toml

Lines changed: 58 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,69 @@
1-
[tool.poetry]
2-
authors = ["Johannes Köster <johannes.koester@uni-due.de>"]
1+
[project]
2+
authors = [
3+
{ name = "Johannes Köster", email = "johannes.koester@uni-due.de" }
4+
]
35
description = "This package provides a stable interface for interactions between Snakemake and its software deployment plugins."
46
license = "MIT"
57
name = "snakemake-interface-software-deployment-plugins"
6-
packages = [{include = "snakemake_interface_software_deployment_plugins"}]
78
readme = "README.md"
89
version = "0.9.0"
10+
requires-python = ">=3.11,<4.0"
11+
dependencies = [
12+
"argparse-dataclass >=2.0.0,<3.0",
13+
"snakemake-interface-common >=1.17.4,<2.0.0"
14+
]
915

10-
[tool.poetry.dependencies]
11-
argparse-dataclass = "^2.0.0"
12-
python = "^3.11"
13-
snakemake-interface-common = "^1.17.4"
16+
[project.urls]
17+
repository = "https://github.com/snakemake/snakemake-interface-software-deployment-plugins"
1418

15-
[tool.poetry.group.dev.dependencies]
16-
coverage = {extras = ["toml"], version = "^6.3.1"}
17-
flake8-bugbear = "^22.1.11"
18-
pytest = "^7.0"
19-
ruff = "^0.9.9"
20-
snakemake-software-deployment-plugin-envmodules = "^0.1.2"
19+
[build-system]
20+
requires = ["hatchling"]
21+
build-backend = "hatchling.build"
22+
23+
[tool.pixi.pypi-dependencies]
24+
snakemake-interface-software-deployment-plugins = { path = ".", editable = true }
25+
26+
[tool.pixi.workspace]
27+
channels = ["conda-forge"]
28+
platforms = ["osx-arm64", "linux-64"]
29+
30+
[tool.pixi.environments]
31+
dev = { features = ["dev"] }
32+
publish = { features = ["publish"] }
33+
34+
[tool.pixi.feature.dev.dependencies]
35+
pytest = ">=8.3.5,<9"
36+
ruff = ">=0.10.0,<0.11"
37+
pytest-cov = ">=6.0.0,<7"
38+
pyrefly = ">=0.52.0,<0.53"
2139

22-
[tool.coverage.run]
23-
omit = [".*", "*/site-packages/*"]
40+
[tool.pixi.feature.dev.tasks]
41+
format = "ruff format"
42+
lint = "ruff check"
43+
typecheck = "pyrefly check"
44+
qc = { depends-on = ["format", "lint"] }
45+
coverage-report = "coverage report -m"
46+
47+
[tool.pixi.feature.dev.tasks.test]
48+
cmd = [
49+
"pytest",
50+
"--cov=snakemake_software_deployment_plugin_envmodules",
51+
"--cov-report=xml:coverage-report/coverage.xml",
52+
"--cov-report=term-missing",
53+
"tests/test_plugin.py",
54+
]
2455

2556
[tool.coverage.report]
26-
fail_under = 60
57+
exclude_lines = ["pass", "\\.\\.\\."]
58+
fail_under = 70.0
2759

28-
[build-system]
29-
build-backend = "poetry.core.masonry.api"
30-
requires = ["poetry-core"]
60+
[tool.pixi.feature.publish.dependencies]
61+
twine = ">=6.1.0,<7"
62+
python-build = ">=1.2.2,<2"
63+
64+
65+
[tool.pixi.feature.publish.tasks]
66+
build = { cmd = "python -m build", description = "Build the package into the dist/ directory" }
67+
check-build = { cmd = "python -m twine check dist/*", depends-on = [
68+
"build",
69+
], description = "Check that the package can be uploaded" }

snakemake_interface_software_deployment_plugins/__init__.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
from abc import ABC, abstractmethod
77
from copy import copy
8+
from inspect import getmodule
89
from dataclasses import dataclass, field
910
import hashlib
1011
from pathlib import Path
1112
import shutil
13+
from types import ModuleType
1214
from typing import (
1315
Any,
1416
ClassVar,
@@ -19,6 +21,7 @@
1921
Self,
2022
Tuple,
2123
Type,
24+
TypeVar,
2225
Union,
2326
)
2427
import subprocess as sp
@@ -43,16 +46,22 @@ class EnvSpecSourceFile:
4346

4447

4548
class EnvSpecBase(ABC):
49+
@classmethod
50+
def module(cls) -> ModuleType:
51+
class_module = getmodule(cls)
52+
assert class_module is not None, f"bug: cannot detect class module of {cls}"
53+
return class_module
54+
4655
def technical_init(self):
4756
"""This has to be called by Snakemake upon initialization"""
4857
self.within: Optional["EnvSpecBase"] = None
4958
self.fallback: Optional["EnvSpecBase"] = None
50-
self.kind: str = self.__class__.__module__.common_settings.provides
59+
self.kind: str = self.module().common_settings.provides
5160
self._obj_hash: Optional[int] = None
5261

5362
@classmethod
5463
def env_cls(cls):
55-
return cls.__module__.EnvBase
64+
return cls.module().EnvBase
5665

5766
@classmethod
5867
@abstractmethod
@@ -148,19 +157,11 @@ def run(self, cmd: str, **kwargs) -> sp.CompletedProcess:
148157
return sp.run([self.executable] + self.args + [self.command_arg, cmd], **kwargs)
149158

150159

160+
TSettings = TypeVar("TSettings", bound="SoftwareDeploymentSettingsBase")
161+
162+
151163
class EnvBase(ABC):
152164
_cache: ClassVar[Dict[Tuple[Type["EnvBase"], Optional["EnvBase"]], Any]] = {}
153-
spec: EnvSpecBase
154-
within: Optional["EnvBase"]
155-
settings: Optional[SoftwareDeploymentSettingsBase]
156-
shell_executable: ShellExecutable
157-
tempdir: Path
158-
_cache_prefix: Path
159-
_deployment_prefix: Path
160-
_pinfile_prefix: Path
161-
_managed_hash_store: Optional[str] = None
162-
_managed_deployment_hash_store: Optional[str] = None
163-
_obj_hash: Optional[int] = None
164165

165166
def __init__(
166167
self,
@@ -174,15 +175,18 @@ def __init__(
174175
deployment_prefix: Path,
175176
pinfile_prefix: Path,
176177
):
177-
self.spec: EnvSpecBase = spec
178-
self.within: Optional["EnvBase"] = within
178+
self.spec = spec
179+
self.within = within
179180
self.settings: Optional[SoftwareDeploymentSettingsBase] = settings
180181
self.shell_executable = shell_executable
181182
self.tempdir = tempdir
182183
self.source_cache: Path = source_cache
183184
self._deployment_prefix: Path = deployment_prefix
184185
self._cache_prefix: Path = cache_prefix
185186
self._pinfile_prefix: Path = pinfile_prefix
187+
self._managed_hash_store: Optional[str] = None
188+
self._managed_deployment_hash_store: Optional[str] = None
189+
self._obj_hash: Optional[int] = None
186190
self.__post_init__()
187191

188192
def __post_init__(self) -> None: # noqa B027

tests/tests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ def get_test_plugin_name(self) -> str:
2020

2121
def validate_plugin(self, plugin: PluginBase):
2222
assert plugin.settings_cls is None
23-
assert plugin.env_cls is not None
24-
assert plugin.env_spec_cls is not None
23+
assert plugin.env_cls is not None # pyrefly: ignore[missing-attribute]
24+
assert plugin.env_spec_cls is not None # pyrefly: ignore[missing-attribute]
2525

2626
def validate_settings(self, settings: SettingsBase, plugin: PluginBase):
2727
# assert isinstance(settings, plugin.settings_cls)

0 commit comments

Comments
 (0)