env-module-manager 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. env_module_manager-0.3.0/AGENTS.md +98 -0
  2. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/PKG-INFO +14 -6
  3. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/README.md +11 -3
  4. env_module_manager-0.3.0/docs/collective-environments.md +82 -0
  5. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/environment-modules.md +3 -0
  6. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/index.md +6 -2
  7. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/reference.md +21 -2
  8. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/rust-tools.md +10 -0
  9. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/shell-tools.md +10 -0
  10. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/mkdocs.yml +2 -1
  11. env_module_manager-0.3.0/module_manager/cli.py +544 -0
  12. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/module_manager/config.py +101 -10
  13. env_module_manager-0.3.0/module_manager/deploy.py +801 -0
  14. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/module_manager/modulefile.py +52 -6
  15. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/pyproject.toml +2 -2
  16. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/tests/test_cli.py +158 -1
  17. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/tests/test_config.py +11 -2
  18. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/tests/test_modulefile.py +301 -9
  19. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/uv.lock +1 -1
  20. env_module_manager-0.2.0/AGENTS.md +0 -54
  21. env_module_manager-0.2.0/module_manager/cli.py +0 -300
  22. env_module_manager-0.2.0/module_manager/deploy.py +0 -265
  23. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/.github/workflows/publish.yml +0 -0
  24. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/.github/workflows/tag.yml +0 -0
  25. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/.github/workflows/test.yml +0 -0
  26. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/.gitignore +0 -0
  27. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/.python-version +0 -0
  28. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/.readthedocs.yaml +0 -0
  29. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/CONTRIBUTING.md +0 -0
  30. /env_module_manager-0.2.0/LICENSE → /env_module_manager-0.3.0/LICENSE.md +0 -0
  31. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/configuration.md +0 -0
  32. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/development.md +0 -0
  33. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/installation.md +0 -0
  34. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/python-tools.md +0 -0
  35. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/stylesheets/extra.css +0 -0
  36. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/docs/uninstall.md +0 -0
  37. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/example.bash +0 -0
  38. {env_module_manager-0.2.0 → env_module_manager-0.3.0}/module_manager/__init__.py +0 -0
@@ -0,0 +1,98 @@
1
+ # Agents
2
+
3
+ This file gives coding agents the local rules for working in this repository.
4
+
5
+ ## Project Shape
6
+
7
+ `module-manager` is a Python CLI for deploying versioned command-line tools
8
+ behind GNU Environment Modules on Linux/HPC systems. The published package name
9
+ is `env-module-manager`, the import package is `module_manager`, and the console
10
+ script is `module-manager`.
11
+
12
+ The core package lives in `module_manager/`, tests live in `tests/`, and MkDocs
13
+ documentation lives in `docs/`.
14
+
15
+ Important modules:
16
+
17
+ * `module_manager/cli.py`: Rich Click command group and CLI wrappers.
18
+ * `module_manager/config.py`: TOML and environment configuration loading.
19
+ * `module_manager/deploy.py`: filesystem deployment and uninstall behavior.
20
+ * `module_manager/modulefile.py`: Tcl modulefile and default-version rendering.
21
+ * `tests/test_cli.py`: command-line behavior tests.
22
+ * `tests/test_config.py`: configuration precedence tests.
23
+ * `tests/test_modulefile.py`: modulefile and deployment helper tests.
24
+
25
+ ## Commands
26
+
27
+ Use these commands when validating changes:
28
+
29
+ ```bash
30
+ uv run ruff format .
31
+ uv run ruff check .
32
+ uv run pytest
33
+ uv run mkdocs build --strict
34
+ uv build
35
+ uv run twine check dist/*
36
+ ```
37
+
38
+ The test suite is configured with coverage and a 90 percent fail-under
39
+ threshold, so targeted pytest runs can fail coverage even when the selected test
40
+ passes. Run the full suite before treating coverage as meaningful.
41
+
42
+ ## Coding Rules
43
+
44
+ * Preserve user changes. Do not revert unrelated dirty work.
45
+ * Use typed function signatures throughout tests and source code.
46
+ * Use Google-style docstrings for new or edited functions.
47
+ * Keep Click command functions thin; put filesystem behavior in
48
+ `module_manager.deploy`.
49
+ * Keep modulefile string generation in `module_manager.modulefile`.
50
+ * Prefer `pathlib.Path` over string path manipulation.
51
+ * Prefer structured subprocess calls such as `subprocess.run([...], check=True)`.
52
+ * Keep edits scoped. Avoid opportunistic refactors while fixing a bug.
53
+ * Update docs and `README.md` when changing user-facing CLI behavior.
54
+
55
+ ## CLI Behavior
56
+
57
+ Deploy commands create versioned install roots under `<prefix>/<name>/<version>`
58
+ and modulefiles under `<module-root>/<name>/<version>`.
59
+
60
+ Supported deploy commands:
61
+
62
+ * `deploy-python`: writes a modulefile for a Python CLI, and can install it with
63
+ `uv tool install`.
64
+ * `deploy-rust`: copies a compiled binary into the versioned `bin` directory.
65
+ * `deploy-script`: copies a shell script into the versioned `bin` directory.
66
+ * `deploy-env`: reads a TOML manifest and deploys Python, Rust, and script
67
+ tools into one shared environment module.
68
+
69
+ Deployments write `<module-root>/<name>/.version` by default so `module load
70
+ <name>` resolves to the deployed version. Use `--no-default` to skip that.
71
+
72
+ Rust, script, collective environment, and uninstall workflows support
73
+ `--dry-run`. Individual `deploy-python` intentionally keeps `--execute-install`
74
+ for its two-step metadata-first workflow.
75
+
76
+ `uninstall` removes one versioned install root and modulefile. It removes the
77
+ default selector only when it still points at the version being removed. Use
78
+ `--dry-run` to show paths without deleting them, and `--keep-default` to leave
79
+ the default selector untouched.
80
+
81
+ ## Configuration
82
+
83
+ Configuration can come from `~/.config/module-manager/config.toml`, a path set
84
+ with `MODULE_MANAGER_CONFIG`, environment variables, or CLI options. CLI options
85
+ take precedence over environment values, which take precedence over TOML.
86
+
87
+ Common settings:
88
+
89
+ * `prefix` or `MODULE_MANAGER_PREFIX`
90
+ * `module_root` or `MODULE_MANAGER_MODULE_ROOT`
91
+ * `[python].indexes`, `MODULE_MANAGER_INDEX`, or `MODULE_MANAGER_INDEXES`
92
+ * `[python].find_links` or `MODULE_MANAGER_FIND_LINKS`
93
+
94
+ ## Documentation
95
+
96
+ MkDocs Material is used for documentation. Update `mkdocs.yml` navigation when
97
+ adding pages. The Material theme currently prints an upstream warning during
98
+ `mkdocs build --strict`; the build is still valid when the command exits zero.
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: env-module-manager
3
- Version: 0.2.0
4
- Summary: Deploy Python, Rust, and shell CLI tools behind GNU environment modulefiles
3
+ Version: 0.3.0
4
+ Summary: Deploy Python, Rust, shell, and collective CLI environments behind GNU environment modulefiles
5
5
  Project-URL: Homepage, https://github.com/ejb90/module-manager
6
6
  Project-URL: Documentation, https://module-manager.readthedocs.io/
7
7
  Project-URL: Tests, https://app.codecov.io/gh/ejb90/module-manager
8
8
  Project-URL: Repository, https://github.com/ejb90/module-manager
9
9
  Author: ejb90
10
10
  License-Expression: MIT
11
- License-File: LICENSE
11
+ License-File: LICENSE.md
12
12
  Classifier: Development Status :: 3 - Alpha
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Intended Audience :: System Administrators
@@ -40,8 +40,8 @@ Description-Content-Type: text/markdown
40
40
  [![PyPI](https://img.shields.io/pypi/v/env-module-manager)](https://pypi.org/project/env-module-manager/)
41
41
  [![Python versions](https://img.shields.io/pypi/pyversions/env-module-manager)](https://pypi.org/project/env-module-manager/)
42
42
 
43
- `module-manager` deploys versioned Python, Rust, and shell CLI tools behind GNU
44
- environment modulefiles for Linux/HPC systems.
43
+ `module-manager` deploys versioned Python, Rust, shell, and collective CLI
44
+ environments behind GNU environment modulefiles for Linux/HPC systems.
45
45
 
46
46
  It writes tools and modulefiles into predictable versioned locations:
47
47
 
@@ -80,6 +80,13 @@ module-manager deploy-script my-tool 1.0.0 \
80
80
  --module-root /prod/modulefiles
81
81
  ```
82
82
 
83
+ Deploy a collective environment from a TOML manifest:
84
+
85
+ ```sh
86
+ module-manager deploy-env --file dev-tools.toml --dry-run
87
+ module-manager deploy-env --file dev-tools.toml
88
+ ```
89
+
83
90
  Use the generated module:
84
91
 
85
92
  ```sh
@@ -108,4 +115,5 @@ uv run mkdocs serve
108
115
  ```
109
116
 
110
117
  Start with `docs/index.md` for installation, configuration, Python tools, Rust
111
- tools, shell scripts, uninstall, and local development notes.
118
+ tools, shell scripts, collective environments, uninstall, and local development
119
+ notes.
@@ -8,8 +8,8 @@
8
8
  [![PyPI](https://img.shields.io/pypi/v/env-module-manager)](https://pypi.org/project/env-module-manager/)
9
9
  [![Python versions](https://img.shields.io/pypi/pyversions/env-module-manager)](https://pypi.org/project/env-module-manager/)
10
10
 
11
- `module-manager` deploys versioned Python, Rust, and shell CLI tools behind GNU
12
- environment modulefiles for Linux/HPC systems.
11
+ `module-manager` deploys versioned Python, Rust, shell, and collective CLI
12
+ environments behind GNU environment modulefiles for Linux/HPC systems.
13
13
 
14
14
  It writes tools and modulefiles into predictable versioned locations:
15
15
 
@@ -48,6 +48,13 @@ module-manager deploy-script my-tool 1.0.0 \
48
48
  --module-root /prod/modulefiles
49
49
  ```
50
50
 
51
+ Deploy a collective environment from a TOML manifest:
52
+
53
+ ```sh
54
+ module-manager deploy-env --file dev-tools.toml --dry-run
55
+ module-manager deploy-env --file dev-tools.toml
56
+ ```
57
+
51
58
  Use the generated module:
52
59
 
53
60
  ```sh
@@ -76,4 +83,5 @@ uv run mkdocs serve
76
83
  ```
77
84
 
78
85
  Start with `docs/index.md` for installation, configuration, Python tools, Rust
79
- tools, shell scripts, uninstall, and local development notes.
86
+ tools, shell scripts, collective environments, uninstall, and local development
87
+ notes.
@@ -0,0 +1,82 @@
1
+ # Collective Environments
2
+
3
+ Collective environments package several tools behind one modulefile. Use them
4
+ when a shared workflow needs Python CLIs, Rust binaries, and shell scripts to
5
+ appear together from one `module load`.
6
+
7
+ Create a TOML manifest:
8
+
9
+ ```toml
10
+ name = "dev-tools"
11
+ version = "2026.05"
12
+ description = "Shared developer command-line tools"
13
+ prefix = "/prod/tools"
14
+ module_root = "/prod/modulefiles"
15
+ default = true
16
+
17
+ [[tools]]
18
+ type = "python"
19
+ name = "ruff"
20
+ version = "0.8.0"
21
+ package = "ruff==0.8.0"
22
+ python = "3.12"
23
+ indexes = ["https://packages.example/simple"]
24
+ find_links = ["/prod/wheels"]
25
+
26
+ [[tools]]
27
+ type = "rust"
28
+ name = "ripgrep"
29
+ version = "14.1.1"
30
+ binary = "./target/release/rg"
31
+
32
+ [[tools]]
33
+ type = "script"
34
+ name = "lab-helper"
35
+ version = "1.0.0"
36
+ script = "./scripts/lab-helper"
37
+ ```
38
+
39
+ Deploy the environment:
40
+
41
+ ```sh
42
+ module-manager deploy-env --file dev-tools.toml
43
+ ```
44
+
45
+ This writes one shared environment:
46
+
47
+ ```text
48
+ /prod/tools/dev-tools/2026.05/bin
49
+ /prod/modulefiles/dev-tools/2026.05
50
+ ```
51
+
52
+ The generated modulefile prepends the shared `bin` directory to `PATH`, so all
53
+ tools in the manifest are available after:
54
+
55
+ ```sh
56
+ module use /prod/modulefiles
57
+ module load dev-tools
58
+ ```
59
+
60
+ Relative `binary` and `script` paths are resolved relative to the manifest file.
61
+
62
+ ## Preview
63
+
64
+ Use `--dry-run` to preview the install, copy, and modulefile actions without
65
+ creating files:
66
+
67
+ ```sh
68
+ module-manager deploy-env --file dev-tools.toml --dry-run
69
+ ```
70
+
71
+ ## Overrides
72
+
73
+ The manifest can define `prefix`, `module_root`, and `default`, but CLI options
74
+ can override them:
75
+
76
+ ```sh
77
+ module-manager deploy-env \
78
+ --file dev-tools.toml \
79
+ --prefix /scratch/tools \
80
+ --module-root /scratch/modulefiles \
81
+ --no-default
82
+ ```
@@ -55,3 +55,6 @@ module-manager deploy-python ruff 0.8.0 \
55
55
  Uninstall removes the default selector only when it still points at the version
56
56
  being removed. If another deployment has already made a newer version the
57
57
  default, that selector is left alone.
58
+
59
+ Collective environments use the same modulefile behavior, but the versioned
60
+ `bin` directory contains every tool listed in the manifest.
@@ -1,7 +1,7 @@
1
1
  # module-manager
2
2
 
3
- `module-manager` deploys versioned Python, Rust, and shell CLI tools behind GNU
4
- environment modulefiles for Linux/HPC systems.
3
+ `module-manager` deploys versioned Python, Rust, shell, and collective CLI
4
+ environments behind GNU environment modulefiles for Linux/HPC systems.
5
5
 
6
6
  It is designed for administrators who want reproducible command-line tool
7
7
  installations under a production prefix such as `/prod/tools`, with matching
@@ -27,6 +27,9 @@ The generated modulefile is written to:
27
27
  /prod/modulefiles/<name>/<version>
28
28
  ```
29
29
 
30
+ Collective environments use the same layout, but several tools share one
31
+ versioned `bin` directory and one modulefile.
32
+
30
33
  ## Common Workflow
31
34
 
32
35
  ```sh
@@ -48,4 +51,5 @@ ruff --version
48
51
  - Deploy Python packages with [Python Tools](python-tools.md).
49
52
  - Deploy Rust binaries with [Rust Tools](rust-tools.md).
50
53
  - Deploy shell scripts with [Shell Scripts](shell-tools.md).
54
+ - Deploy shared tool bundles with [Collective Environments](collective-environments.md).
51
55
  - Remove deployed versions with [Uninstall](uninstall.md).
@@ -24,6 +24,12 @@ Show shell script deployment options:
24
24
  module-manager deploy-script --help
25
25
  ```
26
26
 
27
+ Show collective environment deployment options:
28
+
29
+ ```sh
30
+ module-manager deploy-env --help
31
+ ```
32
+
27
33
  Show uninstall options:
28
34
 
29
35
  ```sh
@@ -51,7 +57,8 @@ module-manager deploy-rust NAME VERSION \
51
57
  [--binary PATH] \
52
58
  [--prefix PATH] \
53
59
  [--module-root PATH] \
54
- [--no-default]
60
+ [--no-default] \
61
+ [--dry-run]
55
62
  ```
56
63
 
57
64
  ## Shell Script Command
@@ -61,7 +68,19 @@ module-manager deploy-script NAME VERSION \
61
68
  [--script PATH] \
62
69
  [--prefix PATH] \
63
70
  [--module-root PATH] \
64
- [--no-default]
71
+ [--no-default] \
72
+ [--dry-run]
73
+ ```
74
+
75
+ ## Collective Environment Command
76
+
77
+ ```sh
78
+ module-manager deploy-env \
79
+ --file MANIFEST.toml \
80
+ [--prefix PATH] \
81
+ [--module-root PATH] \
82
+ [--no-default] \
83
+ [--dry-run]
65
84
  ```
66
85
 
67
86
  ## Uninstall Command
@@ -26,3 +26,13 @@ The generated modulefile prepends the deployed `bin` directory to `PATH`.
26
26
  Deployments make the deployed version the module default, so `module load
27
27
  ripgrep` resolves to `ripgrep/14.1.1`. Add `--no-default` to leave the current
28
28
  default unchanged.
29
+
30
+ Preview the paths that would be written without copying the binary:
31
+
32
+ ```sh
33
+ module-manager deploy-rust ripgrep 14.1.1 \
34
+ --binary ./target/release/rg \
35
+ --prefix /prod/tools \
36
+ --module-root /prod/modulefiles \
37
+ --dry-run
38
+ ```
@@ -27,3 +27,13 @@ the deployed `bin` directory to `PATH`.
27
27
  Deployments make the deployed version the module default, so `module load
28
28
  my-tool` resolves to `my-tool/1.0.0`. Add `--no-default` to leave the current
29
29
  default unchanged.
30
+
31
+ Preview the paths that would be written without copying the script:
32
+
33
+ ```sh
34
+ module-manager deploy-script my-tool 1.0.0 \
35
+ --script ./scripts/my-tool \
36
+ --prefix /prod/tools \
37
+ --module-root /prod/modulefiles \
38
+ --dry-run
39
+ ```
@@ -1,5 +1,5 @@
1
1
  site_name: module-manager
2
- site_description: Deploy Python, Rust, and shell CLI tools behind GNU environment modulefiles.
2
+ site_description: Deploy Python, Rust, shell, and collective CLI environments behind GNU environment modulefiles.
3
3
  repo_url: https://github.com/ellis/module-manager
4
4
 
5
5
  theme:
@@ -46,6 +46,7 @@ nav:
46
46
  - Python Tools: python-tools.md
47
47
  - Rust Tools: rust-tools.md
48
48
  - Shell Scripts: shell-tools.md
49
+ - Collective Environments: collective-environments.md
49
50
  - Uninstall: uninstall.md
50
51
  - Environment Modules: environment-modules.md
51
52
  - Local Development: development.md