Skip to content

fix: load concrete Env/EnvSpec classes instead of abstract bases#58

Merged
johanneskoester merged 1 commit into
snakemake:mainfrom
jiangyun-fun:fix/load-concrete-env-spec-class
Jun 26, 2026
Merged

fix: load concrete Env/EnvSpec classes instead of abstract bases#58
johanneskoester merged 1 commit into
snakemake:mainfrom
jiangyun-fun:fix/load-concrete-env-spec-class

Conversation

@jiangyun-fun

@jiangyun-fun jiangyun-fun commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Problem

SoftwareDeploymentPluginRegistry.load_plugin() populated the Plugin with:

_env_cls=module.EnvBase,
_env_spec_cls=module.EnvSpecBase,

Each plugin module imports EnvBase/EnvSpecBase as the abstract base classes for its own Env/EnvSpec subclasses, so module.EnvBase / module.EnvSpecBase resolve to those abstract bases — not the concrete classes the plugin defines. As a result plugin.env_spec_cls was always EnvSpecBase (and _env_cls always EnvBase) for every plugin.

This is inconsistent with expected_attributes(), which already correctly requires the concrete Env and EnvSpec attributes.

Impact

Because plugin.env_spec_cls was the abstract EnvSpecBase, methods like source_path_attributes() (abstract body ...) returned None. Snakemake's software-deployment directive factory iterates plugin.env_spec_cls.source_path_attributes() and crashed:

TypeError: 'NoneType' object is not iterable

This broke every software: <kind>(...) directive at parse time (conda/container/envmodules), so the whole generic software-deployment feature was unusable with the published plugin versions.

Fix

Read the concrete classes that plugins actually expose:

_env_cls=module.Env,
_env_spec_cls=module.EnvSpec,

Verification

With this change plus the corresponding snakemake-side fixes, the software: conda(envfile=...) path works end-to-end (the conda env is created and the rule runs); before this, any software: directive crashed in the factory. plugin.env_spec_cls now resolves to the concrete class for all plugins, e.g.:

conda:      env_spec_cls=EnvSpec, source_path_attributes=['envfile', 'pinfile']
container:  env_spec_cls=EnvSpec, source_path_attributes=[]
envmodules: env_spec_cls=EnvSpec

Context: snakemake/snakemake#4209.

Summary by CodeRabbit

  • Bug Fixes
    • Improved plugin loading so deployment plugins now use the correct environment classes during initialization.
    • This helps ensure plugins are recognized and configured properly without changing their public interface.

load_plugin() read module.EnvBase / module.EnvSpecBase, which resolve to the
abstract base classes (each plugin imports them as base classes), so
plugin.env_spec_cls was always EnvSpecBase. As a result, e.g.
source_path_attributes() returned None and snakemake's software-deployment
directive factory crashed when wrapping source path attributes. Read
module.Env / module.EnvSpec -- the concrete classes that expected_attributes()
already requires -- instead.
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fdff41bb-72f8-44c4-8b5a-596f8c869989

📥 Commits

Reviewing files that changed from the base of the PR and between 4f0156a and b021cb0.

📒 Files selected for processing (1)
  • snakemake_interface_software_deployment_plugins/registry/__init__.py

📝 Walkthrough

Walkthrough

The plugin registry now constructs Plugin using module.Env and module.EnvSpec for environment classes instead of module.EnvBase and module.EnvSpecBase.

Changes

Plugin registry environment classes

Layer / File(s) Summary
Environment class sources
snakemake_interface_software_deployment_plugins/registry/__init__.py
load_plugin passes module.Env and module.EnvSpec into Plugin instead of module.EnvBase and module.EnvSpecBase.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: loading concrete Env/EnvSpec classes instead of abstract bases.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@johanneskoester johanneskoester merged commit 78c2d62 into snakemake:main Jun 26, 2026
6 checks passed
johanneskoester pushed a commit that referenced this pull request Jun 26, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.18.3](v0.18.2...v0.18.3)
(2026-06-26)


### Bug Fixes

* load concrete Env/EnvSpec classes instead of abstract bases
([#58](#58))
([78c2d62](78c2d62))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
johanneskoester added a commit to snakemake/snakemake-software-deployment-plugin-envmodules that referenced this pull request Jun 28, 2026
## Problem

`EnvSpec.identity_attributes` and `EnvSpec.source_path_attributes` are
defined as instance methods (`self`), but the interface base
(`snakemake_interface_software_deployment_plugins.EnvSpecBase`) and the
sibling plugins (conda, container) declare them as `@classmethod`
(`cls`).

## Impact

`EnvSpecBase.__hash__` -> `managed_identity_attributes()` (a
classmethod) calls `cls.identity_attributes()`. Because this plugin's
`identity_attributes` is an instance method, that call raises:

```
TypeError: EnvSpec.identity_attributes() missing 1 required positional argument: 'self'
```

So every envmodules spec is **unhashable**. Anywhere a spec is used as a
dict key or set member it crashes — in particular
`SoftwareDeploymentManager.get_env()` does `if env_spec in
self.specs_to_envs:`, which hashes the spec. This breaks standalone
`envmodules(...)` usage and the fallback chain `envmodules(...) or
conda(...)` (the headline composition form).

## Fix

Make both methods `@classmethod`, matching the interface and the other
plugins:

```python
@classmethod
def identity_attributes(cls) -> Iterable[str]:
    yield "names"

@classmethod
def source_path_attributes(cls) -> Iterable[str]:
    return ()
```

Neither body uses `self`, so this is a drop-in fix.

## Verification

After the change, envmodules specs are hashable (`hash(spec)` succeeds)
and `get_env()` no longer crashes on the fallback path.

Context: snakemake/snakemake#4209; related interface fix:
snakemake/snakemake-interface-software-deployment-plugins#58.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved how environment module details are handled, making
environment identification and hashing more reliable.
* Fixed shell command handling so module names with unsafe characters
are quoted correctly.
* Ensured environment records are created consistently and can be used
as dictionary keys without issues.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Johannes Köster <johannes.koester@uni-due.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants