conda-workspaces 0.1.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.
- conda_workspaces-0.1.0/.github/workflows/docs.yml +56 -0
- conda_workspaces-0.1.0/.github/workflows/release.yml +74 -0
- conda_workspaces-0.1.0/.github/workflows/tests.yml +70 -0
- conda_workspaces-0.1.0/.gitignore +62 -0
- conda_workspaces-0.1.0/AGENTS.md +148 -0
- conda_workspaces-0.1.0/CHANGELOG.md +25 -0
- conda_workspaces-0.1.0/CODE_OF_CONDUCT.md +126 -0
- conda_workspaces-0.1.0/CONTRIBUTING.md +98 -0
- conda_workspaces-0.1.0/DESIGN.md +290 -0
- conda_workspaces-0.1.0/LICENSE +28 -0
- conda_workspaces-0.1.0/PKG-INFO +144 -0
- conda_workspaces-0.1.0/README.md +121 -0
- conda_workspaces-0.1.0/conda.lock +2266 -0
- conda_workspaces-0.1.0/conda_workspaces/__init__.py +8 -0
- conda_workspaces-0.1.0/conda_workspaces/__main__.py +29 -0
- conda_workspaces-0.1.0/conda_workspaces/_version.py +34 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/__init__.py +7 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/activate.py +33 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/add.py +91 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/clean.py +52 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/info.py +71 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/init.py +114 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/install.py +67 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/list.py +55 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/lock.py +43 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/main.py +320 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/remove.py +98 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/run.py +64 -0
- conda_workspaces-0.1.0/conda_workspaces/cli/shell.py +46 -0
- conda_workspaces-0.1.0/conda_workspaces/context.py +87 -0
- conda_workspaces-0.1.0/conda_workspaces/env_export.py +94 -0
- conda_workspaces-0.1.0/conda_workspaces/env_spec.py +198 -0
- conda_workspaces-0.1.0/conda_workspaces/envs.py +209 -0
- conda_workspaces-0.1.0/conda_workspaces/exceptions.py +130 -0
- conda_workspaces-0.1.0/conda_workspaces/lockfile.py +222 -0
- conda_workspaces-0.1.0/conda_workspaces/models.py +235 -0
- conda_workspaces-0.1.0/conda_workspaces/parsers/__init__.py +99 -0
- conda_workspaces-0.1.0/conda_workspaces/parsers/base.py +42 -0
- conda_workspaces-0.1.0/conda_workspaces/parsers/pixi_toml.py +133 -0
- conda_workspaces-0.1.0/conda_workspaces/parsers/pyproject_toml.py +161 -0
- conda_workspaces-0.1.0/conda_workspaces/parsers/toml.py +145 -0
- conda_workspaces-0.1.0/conda_workspaces/plugin.py +68 -0
- conda_workspaces-0.1.0/conda_workspaces/resolver.py +119 -0
- conda_workspaces-0.1.0/docs/_static/css/custom.css +1 -0
- conda_workspaces-0.1.0/docs/changelog.md +2 -0
- conda_workspaces-0.1.0/docs/conf.py +57 -0
- conda_workspaces-0.1.0/docs/configuration.md +192 -0
- conda_workspaces-0.1.0/docs/features.md +210 -0
- conda_workspaces-0.1.0/docs/index.md +153 -0
- conda_workspaces-0.1.0/docs/motivation.md +99 -0
- conda_workspaces-0.1.0/docs/quickstart.md +169 -0
- conda_workspaces-0.1.0/docs/reference/api/context.md +9 -0
- conda_workspaces-0.1.0/docs/reference/api/environments.md +9 -0
- conda_workspaces-0.1.0/docs/reference/api/models.md +13 -0
- conda_workspaces-0.1.0/docs/reference/api/parsers.md +25 -0
- conda_workspaces-0.1.0/docs/reference/api/resolver.md +9 -0
- conda_workspaces-0.1.0/docs/reference/api.md +51 -0
- conda_workspaces-0.1.0/docs/reference/cli.md +10 -0
- conda_workspaces-0.1.0/docs/robots.txt +4 -0
- conda_workspaces-0.1.0/docs/tutorials/ci-pipeline.md +96 -0
- conda_workspaces-0.1.0/docs/tutorials/coming-from-pixi.md +93 -0
- conda_workspaces-0.1.0/docs/tutorials/first-project.md +119 -0
- conda_workspaces-0.1.0/docs/tutorials/index.md +37 -0
- conda_workspaces-0.1.0/pixi.lock +7325 -0
- conda_workspaces-0.1.0/pyproject.toml +134 -0
- conda_workspaces-0.1.0/schema/conda-toml-1.schema.json +340 -0
- conda_workspaces-0.1.0/tests/__init__.py +1 -0
- conda_workspaces-0.1.0/tests/cli/__init__.py +1 -0
- conda_workspaces-0.1.0/tests/cli/conftest.py +33 -0
- conda_workspaces-0.1.0/tests/cli/test_activate.py +62 -0
- conda_workspaces-0.1.0/tests/cli/test_add_remove.py +247 -0
- conda_workspaces-0.1.0/tests/cli/test_clean.py +127 -0
- conda_workspaces-0.1.0/tests/cli/test_info.py +114 -0
- conda_workspaces-0.1.0/tests/cli/test_init.py +173 -0
- conda_workspaces-0.1.0/tests/cli/test_install.py +223 -0
- conda_workspaces-0.1.0/tests/cli/test_list.py +83 -0
- conda_workspaces-0.1.0/tests/cli/test_lock.py +125 -0
- conda_workspaces-0.1.0/tests/cli/test_main.py +147 -0
- conda_workspaces-0.1.0/tests/cli/test_run.py +126 -0
- conda_workspaces-0.1.0/tests/cli/test_shell.py +130 -0
- conda_workspaces-0.1.0/tests/conftest.py +118 -0
- conda_workspaces-0.1.0/tests/parsers/__init__.py +1 -0
- conda_workspaces-0.1.0/tests/parsers/test_detection.py +129 -0
- conda_workspaces-0.1.0/tests/parsers/test_pixi_toml.py +246 -0
- conda_workspaces-0.1.0/tests/parsers/test_pyproject_toml.py +251 -0
- conda_workspaces-0.1.0/tests/parsers/test_toml.py +189 -0
- conda_workspaces-0.1.0/tests/test___main__.py +76 -0
- conda_workspaces-0.1.0/tests/test_context.py +138 -0
- conda_workspaces-0.1.0/tests/test_env_export.py +155 -0
- conda_workspaces-0.1.0/tests/test_env_spec.py +278 -0
- conda_workspaces-0.1.0/tests/test_envs.py +535 -0
- conda_workspaces-0.1.0/tests/test_exceptions.py +113 -0
- conda_workspaces-0.1.0/tests/test_lockfile.py +323 -0
- conda_workspaces-0.1.0/tests/test_models.py +257 -0
- conda_workspaces-0.1.0/tests/test_plugin.py +48 -0
- conda_workspaces-0.1.0/tests/test_resolver.py +181 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- ".github/workflows/docs.yml"
|
|
9
|
+
- "conda_workspaces/**"
|
|
10
|
+
- "docs/**"
|
|
11
|
+
- "pyproject.toml"
|
|
12
|
+
pull_request:
|
|
13
|
+
paths:
|
|
14
|
+
- ".github/workflows/docs.yml"
|
|
15
|
+
- "docs/**"
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
concurrency:
|
|
19
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
|
20
|
+
cancel-in-progress: true
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
docs:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
27
|
+
with:
|
|
28
|
+
fetch-depth: 0
|
|
29
|
+
- uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3
|
|
30
|
+
with:
|
|
31
|
+
environments: docs
|
|
32
|
+
- name: Build docs
|
|
33
|
+
run: pixi run -e docs docs
|
|
34
|
+
- name: Upload artifact
|
|
35
|
+
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
|
|
36
|
+
with:
|
|
37
|
+
path: "docs/_build/dirhtml"
|
|
38
|
+
|
|
39
|
+
pages:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
if: github.ref == 'refs/heads/main'
|
|
42
|
+
needs: [docs]
|
|
43
|
+
|
|
44
|
+
permissions:
|
|
45
|
+
contents: read
|
|
46
|
+
pages: write
|
|
47
|
+
id-token: write
|
|
48
|
+
|
|
49
|
+
environment:
|
|
50
|
+
name: github-pages
|
|
51
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
52
|
+
|
|
53
|
+
steps:
|
|
54
|
+
- name: Deploy to GitHub Pages
|
|
55
|
+
id: deployment
|
|
56
|
+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: Build distribution
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
|
|
23
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.13"
|
|
26
|
+
|
|
27
|
+
- name: Build sdist and wheel
|
|
28
|
+
run: pipx run build
|
|
29
|
+
|
|
30
|
+
- name: Upload distributions
|
|
31
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
publish-pypi:
|
|
37
|
+
name: Publish to PyPI
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
needs: [build]
|
|
40
|
+
environment: pypi
|
|
41
|
+
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
47
|
+
with:
|
|
48
|
+
name: dist
|
|
49
|
+
path: dist/
|
|
50
|
+
|
|
51
|
+
- uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
|
52
|
+
with:
|
|
53
|
+
packages-dir: dist/
|
|
54
|
+
|
|
55
|
+
upload-release-assets:
|
|
56
|
+
name: Upload release assets
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
needs: [publish-pypi]
|
|
59
|
+
|
|
60
|
+
permissions:
|
|
61
|
+
contents: write
|
|
62
|
+
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
65
|
+
with:
|
|
66
|
+
name: dist
|
|
67
|
+
path: dist/
|
|
68
|
+
|
|
69
|
+
- name: Upload assets to GitHub Release
|
|
70
|
+
env:
|
|
71
|
+
GH_TOKEN: ${{ github.token }}
|
|
72
|
+
GH_REPO: ${{ github.repository }}
|
|
73
|
+
TAG_NAME: ${{ github.event.release.tag_name }}
|
|
74
|
+
run: gh release upload "$TAG_NAME" dist/* --repo "$GH_REPO"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- ".github/workflows/tests.yml"
|
|
9
|
+
- "conda_workspaces/**"
|
|
10
|
+
- "pixi.lock"
|
|
11
|
+
- "pyproject.toml"
|
|
12
|
+
- "tests/**"
|
|
13
|
+
pull_request:
|
|
14
|
+
branches:
|
|
15
|
+
- main
|
|
16
|
+
paths:
|
|
17
|
+
- ".github/workflows/tests.yml"
|
|
18
|
+
- "conda_workspaces/**"
|
|
19
|
+
- "pixi.lock"
|
|
20
|
+
- "pyproject.toml"
|
|
21
|
+
- "tests/**"
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
lint:
|
|
29
|
+
name: Lint
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
33
|
+
- uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3
|
|
34
|
+
with:
|
|
35
|
+
environments: dev
|
|
36
|
+
- name: Lint
|
|
37
|
+
run: pixi run -e dev lint
|
|
38
|
+
- name: Format check
|
|
39
|
+
run: pixi run -e dev format-check
|
|
40
|
+
|
|
41
|
+
tests:
|
|
42
|
+
name: ${{ matrix.os }}, Python ${{ matrix.python-version }}
|
|
43
|
+
runs-on: ${{ matrix.os }}
|
|
44
|
+
strategy:
|
|
45
|
+
fail-fast: false
|
|
46
|
+
matrix:
|
|
47
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
48
|
+
python-version: ["3.10", "3.13"]
|
|
49
|
+
include:
|
|
50
|
+
- os: ubuntu-latest
|
|
51
|
+
python-version: "3.11"
|
|
52
|
+
- os: ubuntu-latest
|
|
53
|
+
python-version: "3.12"
|
|
54
|
+
- os: ubuntu-latest
|
|
55
|
+
python-version: "3.14"
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
58
|
+
with:
|
|
59
|
+
fetch-depth: 0
|
|
60
|
+
- uses: prefix-dev/setup-pixi@82d477f15f3a381dbcc8adc1206ce643fe110fb7 # v0.9.3
|
|
61
|
+
with:
|
|
62
|
+
environments: test
|
|
63
|
+
- name: Run tests
|
|
64
|
+
run: pixi run -e test test-cov
|
|
65
|
+
- name: Upload coverage
|
|
66
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
|
|
67
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
68
|
+
with:
|
|
69
|
+
name: coverage-report
|
|
70
|
+
path: htmlcov/
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# Virtual environments
|
|
28
|
+
.venv/
|
|
29
|
+
venv/
|
|
30
|
+
ENV/
|
|
31
|
+
|
|
32
|
+
# pixi
|
|
33
|
+
.pixi/
|
|
34
|
+
|
|
35
|
+
# conda project-local envs
|
|
36
|
+
.conda/
|
|
37
|
+
|
|
38
|
+
# IDE
|
|
39
|
+
.idea/
|
|
40
|
+
.vscode/
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
43
|
+
*~
|
|
44
|
+
|
|
45
|
+
# Testing
|
|
46
|
+
.pytest_cache/
|
|
47
|
+
.coverage
|
|
48
|
+
htmlcov/
|
|
49
|
+
|
|
50
|
+
# Docs
|
|
51
|
+
docs/_build/
|
|
52
|
+
|
|
53
|
+
# OS
|
|
54
|
+
.DS_Store
|
|
55
|
+
Thumbs.db
|
|
56
|
+
|
|
57
|
+
# Type checking
|
|
58
|
+
.ty/
|
|
59
|
+
.mypy_cache/
|
|
60
|
+
|
|
61
|
+
# Version file (auto-generated)
|
|
62
|
+
conda_workspaces/_version.py
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# AGENTS.md — conda-workspaces coding guidelines
|
|
2
|
+
|
|
3
|
+
## Project structure
|
|
4
|
+
|
|
5
|
+
- CLI modules are separated by subcommand, mirroring conda's own CLI
|
|
6
|
+
layout. Each subcommand lives in its own module under
|
|
7
|
+
`conda_workspaces/cli/` (e.g., `init.py`, `install.py`, `list.py`,
|
|
8
|
+
`info.py`, `add.py`, `remove.py`, `clean.py`, `run.py`, `activate.py`).
|
|
9
|
+
`cli/main.py` contains parser configuration and dispatch;
|
|
10
|
+
`cli/__init__.py` is a thin re-export shim (`configure_parser`,
|
|
11
|
+
`execute`, `generate_parser`).
|
|
12
|
+
|
|
13
|
+
- Parser implementations use submodules, not subpackages. The canonical
|
|
14
|
+
format parsers live at `conda_workspaces/parsers/toml.py`,
|
|
15
|
+
`conda_workspaces/parsers/pixi_toml.py`, and
|
|
16
|
+
`conda_workspaces/parsers/pyproject_toml.py` — plain modules, not
|
|
17
|
+
directories with `__init__.py`. Only create a subpackage when there
|
|
18
|
+
are multiple files to group.
|
|
19
|
+
|
|
20
|
+
- Tests mirror the source structure. Tests for
|
|
21
|
+
`conda_workspaces/cli/install.py` live in `tests/cli/test_install.py`,
|
|
22
|
+
tests for `conda_workspaces/parsers/toml.py` live in
|
|
23
|
+
`tests/parsers/test_toml.py`, etc. Test module names match their
|
|
24
|
+
corresponding source module names.
|
|
25
|
+
|
|
26
|
+
## Imports
|
|
27
|
+
|
|
28
|
+
- Use relative imports for all intra-package references
|
|
29
|
+
(`from .models import WorkspaceConfig`,
|
|
30
|
+
`from ..exceptions import CondaWorkspacesError`).
|
|
31
|
+
Absolute `conda_workspaces.*` imports should only appear in tests
|
|
32
|
+
and entry points.
|
|
33
|
+
|
|
34
|
+
- Inline (lazy) imports are reserved for performance-critical paths.
|
|
35
|
+
Acceptable cases: `plugin.py` hooks (loaded on every `conda`
|
|
36
|
+
invocation), `cli/main.py` subcommand dispatch (only the chosen
|
|
37
|
+
handler is loaded), `context.py` property methods (lazy by design),
|
|
38
|
+
and `parsers/toml.py` where `CondaTomlParser.parse()` delegates to
|
|
39
|
+
`PixiTomlParser` (breaks a real circular dependency since
|
|
40
|
+
`pixi_toml` imports helpers from `toml`). Everywhere else, imports
|
|
41
|
+
belong at the top of the module.
|
|
42
|
+
|
|
43
|
+
## Dependencies
|
|
44
|
+
|
|
45
|
+
- Minimize the dependency graph. Prefer stdlib or already-required
|
|
46
|
+
packages over adding new ones. When a single library covers multiple
|
|
47
|
+
use cases (e.g., `tomlkit` for both reading and writing TOML), use
|
|
48
|
+
it instead of carrying separate read-only and read-write libraries.
|
|
49
|
+
|
|
50
|
+
- Pin minimum versions in `pyproject.toml` dependencies (e.g.,
|
|
51
|
+
`"tomlkit >=0.13"`), not exact versions.
|
|
52
|
+
|
|
53
|
+
## Typing and linting
|
|
54
|
+
|
|
55
|
+
- All code must be typed using modern annotations (`str | None` not
|
|
56
|
+
`Optional[str]`, `list[str]` not `List[str]`). `ClassVar` from
|
|
57
|
+
`typing` is the correct annotation for class-level attributes — it
|
|
58
|
+
is not deprecated.
|
|
59
|
+
|
|
60
|
+
- Use `ty` for type checking and `ruff` for linting and formatting.
|
|
61
|
+
Both are configured in `pyproject.toml`.
|
|
62
|
+
|
|
63
|
+
- Use `from __future__ import annotations` in all modules.
|
|
64
|
+
|
|
65
|
+
## Testing
|
|
66
|
+
|
|
67
|
+
- Tests are plain `pytest` functions — no `unittest.TestCase` or other class-based test grouping.
|
|
68
|
+
Do not group tests in classes; use module-level functions with descriptive names.
|
|
69
|
+
|
|
70
|
+
- Do not use section comments (e.g., `# --- Section ---`) to group tests.
|
|
71
|
+
Relay on function naming and module structure for organization.
|
|
72
|
+
|
|
73
|
+
- Use `pytest` native fixtures (`tmp_path`, `monkeypatch`, `capsys`)
|
|
74
|
+
instead of `unittest.mock`. Prefer `monkeypatch.setattr` with simple
|
|
75
|
+
fakes or recording closures over `MagicMock` / `patch`.
|
|
76
|
+
|
|
77
|
+
- Use `pytest.mark.parametrize` extensively. When multiple test cases
|
|
78
|
+
exercise the same logic with different inputs, consolidate them into
|
|
79
|
+
a single parameterized test.
|
|
80
|
+
|
|
81
|
+
- Shared fixtures belong in `conftest.py` at the appropriate level
|
|
82
|
+
(root `tests/conftest.py` for cross-cutting fixtures, subdirectory
|
|
83
|
+
`conftest.py` for module-specific ones).
|
|
84
|
+
|
|
85
|
+
- Coverage is measured with `pytest-cov`. Thresholds and exclusions are
|
|
86
|
+
configured in `pyproject.toml` under `[tool.coverage.*]`. Run
|
|
87
|
+
`pixi run -e <test-env> test-cov` to generate a coverage report.
|
|
88
|
+
|
|
89
|
+
## Conda integration
|
|
90
|
+
|
|
91
|
+
- Follow standard conda CLI patterns: use `-n`/`--name` and
|
|
92
|
+
`-p`/`--prefix` for environment targeting, not custom flags like
|
|
93
|
+
`--environment`.
|
|
94
|
+
|
|
95
|
+
- Use conda's own APIs where available (e.g., `conda.base.constants`,
|
|
96
|
+
`conda.base.context.context`, `context.plugins.raw_data` for
|
|
97
|
+
`.condarc` settings) rather than reimplementing platform detection or
|
|
98
|
+
config parsing.
|
|
99
|
+
|
|
100
|
+
- The `add_output_and_prompt_options` helper from conda already
|
|
101
|
+
provides `--json`, `--dry-run`, `--yes`, `-v`, `-q`, `--debug`,
|
|
102
|
+
`--trace`, and `--console`. Do not add custom arguments that
|
|
103
|
+
duplicate these — it causes `ArgumentError: conflicting option
|
|
104
|
+
string` at runtime.
|
|
105
|
+
|
|
106
|
+
- The plugin registers via `pluggy` hooks (`conda_subcommands`) and
|
|
107
|
+
the `[project.entry-points.conda]` entry point.
|
|
108
|
+
|
|
109
|
+
## Parser search order
|
|
110
|
+
|
|
111
|
+
- The parser registry searches for workspace manifests in this order:
|
|
112
|
+
1. `conda.toml` — conda-native workspace manifest
|
|
113
|
+
2. `pixi.toml` — pixi-native format (compatibility)
|
|
114
|
+
3. `pyproject.toml` — embedded under `[tool.conda.*]`,
|
|
115
|
+
`[tool.conda-workspaces.*]` (legacy), or `[tool.pixi.*]`
|
|
116
|
+
|
|
117
|
+
- All parsers produce a `WorkspaceConfig` model, regardless of source
|
|
118
|
+
format. Parser-specific logic stays in the parser; downstream code
|
|
119
|
+
only depends on the model.
|
|
120
|
+
|
|
121
|
+
## Documentation
|
|
122
|
+
|
|
123
|
+
- Docs use Sphinx with `conda-sphinx-theme`, `myst-parser`, and
|
|
124
|
+
`sphinx-design`.
|
|
125
|
+
|
|
126
|
+
- Follow the Diataxis framework: tutorials, how-to guides, reference,
|
|
127
|
+
and explanation sections.
|
|
128
|
+
|
|
129
|
+
- Key relationship with pixi must be documented prominently:
|
|
130
|
+
`conda-workspaces` reads pixi-compatible manifests but delegates
|
|
131
|
+
solving and environment management to conda's own infrastructure.
|
|
132
|
+
It does not replace pixi — it brings workspace management into the
|
|
133
|
+
conda CLI.
|
|
134
|
+
|
|
135
|
+
- Avoid excessive bold and italic in prose, list items, and headings.
|
|
136
|
+
Don't bold every list item or key term — let the text speak for
|
|
137
|
+
itself. In docstrings, use `*param*` for parameter names (standard
|
|
138
|
+
Sphinx convention) but avoid bold elsewhere.
|
|
139
|
+
|
|
140
|
+
- Keep `sphinx-design` tab labels short. Use "pixi.toml" / "TOML" /
|
|
141
|
+
"pyproject.toml" instead of verbose labels when the tab content
|
|
142
|
+
already identifies the format. This prevents tab overflow on narrow
|
|
143
|
+
viewports.
|
|
144
|
+
|
|
145
|
+
- The API reference is split into focused sub-pages by concern (models,
|
|
146
|
+
parsers, resolver, context, environments) rather than a single
|
|
147
|
+
monolithic page. The index uses `sphinx-design` grid cards for
|
|
148
|
+
navigation.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to conda-workspaces will be documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
## 0.1.0 — 2026-03-05
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Initial implementation of conda-workspaces plugin
|
|
14
|
+
- `conda workspace` subcommand with `init`, `install`, `list`, `info`,
|
|
15
|
+
`add`, `remove`, `clean`, `run`, and `activate` subcommands
|
|
16
|
+
- `cw` standalone CLI shortcut
|
|
17
|
+
- Parser support for `pixi.toml`, `conda.toml`, and `pyproject.toml`
|
|
18
|
+
manifests
|
|
19
|
+
- Multi-environment workspace model with composable features
|
|
20
|
+
- Solve-group support for version coordination across environments
|
|
21
|
+
- Per-platform dependency overrides via `[target.<platform>]`
|
|
22
|
+
- PyPI dependency parsing (requires conda-pypi for installation)
|
|
23
|
+
- Project-local environments under `.conda/envs/`
|
|
24
|
+
- Sphinx documentation with conda-sphinx-theme
|
|
25
|
+
- PyPI release workflow with trusted publishing
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Conda Organization Code of Conduct
|
|
2
|
+
|
|
3
|
+
# The Short Version
|
|
4
|
+
|
|
5
|
+
Be kind to others. Do not insult or put down others. Behave professionally. Remember that harassment and sexist, racist, or exclusionary jokes are not appropriate for the conda Organization.
|
|
6
|
+
|
|
7
|
+
All communication should be appropriate for a professional audience including people of many different backgrounds. Sexual language and imagery is not appropriate.
|
|
8
|
+
|
|
9
|
+
The conda Organization is dedicated to providing a harassment-free community for everyone, regardless of gender, sexual orientation, gender identity and expression, disability, physical appearance, body size, race, or religion. We do not tolerate harassment of community members in any form.
|
|
10
|
+
|
|
11
|
+
Thank you for helping make this a welcoming, friendly community for all.
|
|
12
|
+
|
|
13
|
+
## Report an Incident
|
|
14
|
+
|
|
15
|
+
* Report a code of conduct incident [using a form](https://form.jotform.com/221527028480048).
|
|
16
|
+
* Report a code of conduct incident via email: [conduct@conda.org](mailto:conduct@conda.org).
|
|
17
|
+
* Contact [an individual committee member](#committee-membership) or [CoC event representative](#coc-representatives) to report an incident in confidence.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
And now the longer version...
|
|
22
|
+
|
|
23
|
+
# Conda Organization Diversity Statement
|
|
24
|
+
|
|
25
|
+
The conda Organization welcomes and encourages participation in our community by people of all backgrounds and identities. We are committed to promoting and sustaining a culture that values mutual respect, tolerance, and learning, and we work together as a community to help each other live out these values.
|
|
26
|
+
|
|
27
|
+
We have created this diversity statement because we believe that a diverse community is stronger, more vibrant, and produces better software and better science. A diverse community where people treat each other with respect has more potential contributors, more sources for ideas, and fewer shared assumptions that might hinder development or research.
|
|
28
|
+
|
|
29
|
+
Although we have phrased the formal diversity statement generically to make it all-inclusive, we recognize that there are specific identities that are impacted by systemic discrimination and marginalization. We welcome all people to participate in the conda Organization community regardless of their identity or background.
|
|
30
|
+
|
|
31
|
+
# Conda Organization Code of Conduct: Introduction & Scope
|
|
32
|
+
|
|
33
|
+
This code of conduct should be honored by everyone who participates in the conda Organization community. It should be honored in any conda Organization-related activities, by anyone claiming affiliation with the conda Organization, and especially when someone is representing the conda Organization in any role (including as an event volunteer or speaker).
|
|
34
|
+
|
|
35
|
+
This code of conduct applies to all spaces managed by the conda Organization, including all public and private mailing lists, issue trackers, wikis, forums, and any other communication channel used by our community. The code of conduct equally applies at conda Organization events and governs standards of behavior for attendees, speakers, volunteers, booth staff, and event sponsors.
|
|
36
|
+
|
|
37
|
+
This code is not exhaustive or complete. It serves to distill our understanding of a collaborative, inclusive community culture. Please try to follow this code in spirit as much as in letter, to create a friendly and productive environment that enriches the conda Organization community.
|
|
38
|
+
|
|
39
|
+
The conda Organization Code of Conduct follows below.
|
|
40
|
+
|
|
41
|
+
# Standards for Behavior
|
|
42
|
+
|
|
43
|
+
The conda Organization is a worldwide community. All communication should be appropriate for a professional audience including people of many different backgrounds.
|
|
44
|
+
|
|
45
|
+
**Please always be kind and courteous. There's never a need to be mean or rude or disrespectful.** Thank you for helping make this a welcoming, friendly community for all.
|
|
46
|
+
|
|
47
|
+
We strive to:
|
|
48
|
+
|
|
49
|
+
**Be empathetic, welcoming, friendly, and patient.** We remember that the conda Organization is crafted by human beings who deserve to be treated with kindness and empathy. We work together to resolve conflict and assume good intentions. We may all experience some frustration from time to time, but we do not allow frustration to turn into a personal attack. A community where people feel uncomfortable or threatened is not a productive one.
|
|
50
|
+
|
|
51
|
+
**Be collaborative.** Our work depends on the participation of many people, and in turn others depend on our work. Open source communities depend on effective and friendly collaboration to achieve their goals.
|
|
52
|
+
|
|
53
|
+
**Be inquisitive.** Nobody knows everything! Asking questions early avoids many problems later, so we encourage questions, although we may direct them to the appropriate forum. We will try hard to be responsive and helpful.
|
|
54
|
+
|
|
55
|
+
**Be careful in the words that we choose.** We are careful and respectful in our communication and we take responsibility for our own speech. Be kind to others. Do not insult or put down other members of the community.
|
|
56
|
+
|
|
57
|
+
## Unacceptable Behavior
|
|
58
|
+
|
|
59
|
+
We are committed to making participation in this community a harassment-free experience.
|
|
60
|
+
|
|
61
|
+
We will not accept harassment or other exclusionary behaviors, such as:
|
|
62
|
+
|
|
63
|
+
- The use of sexualized language or imagery
|
|
64
|
+
- Excessive profanity (please avoid curse words; people differ greatly in their sensitivity to swearing)
|
|
65
|
+
- Posting sexually explicit or violent material
|
|
66
|
+
- Violent or intimidating threats or language directed against another person
|
|
67
|
+
- Inappropriate physical contact and/or unwelcome sexual attention or sexual comments
|
|
68
|
+
- Sexist, racist, or otherwise discriminatory jokes and language
|
|
69
|
+
- Trolling or insulting and derogatory comments
|
|
70
|
+
- Written or verbal comments which have the effect of excluding people on the basis of membership in a specific group, including level of experience, gender, gender identity and expression, sexual orientation, disability, neurotype, personal appearance, body size, race, ethnicity, age, religion, or nationality
|
|
71
|
+
- Public or private harassment
|
|
72
|
+
- Sharing private content, such as emails sent privately or non-publicly, or direct message history, without the sender's consent
|
|
73
|
+
- Continuing to initiate interaction (such as photography, recording, messaging, or conversation) with someone after being asked to stop
|
|
74
|
+
- Sustained disruption of talks, events, or communications, such as heckling of a speaker
|
|
75
|
+
- Publishing (or threatening to post) other people's personally identifying information ("doxing"), such as physical or electronic addresses, without explicit permission
|
|
76
|
+
- Other unethical or unprofessional conduct
|
|
77
|
+
- Advocating for, or encouraging, any of the above behaviors
|
|
78
|
+
|
|
79
|
+
The conda Organization prioritizes marginalized people's safety over privileged people's comfort. The conda CoC Committee reserves the right not to act on complaints including, but not limited to:
|
|
80
|
+
|
|
81
|
+
* 'Reverse' -isms, including 'reverse racism,' 'reverse sexism,' and 'cisphobia'.
|
|
82
|
+
* Reasonable communication of boundaries, such as "leave me alone," "go away," or "I'm not discussing this with you."
|
|
83
|
+
* Communicating in a 'tone' you don't find congenial.
|
|
84
|
+
* Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions.
|
|
85
|
+
|
|
86
|
+
## Behavior Outside of conda Organization Spaces
|
|
87
|
+
|
|
88
|
+
The CoC Committee does not influence behavior and membership in spaces outside the conda Organization. However, if you are being harassed by a member of the conda community outside our spaces, you may still report it to the CoC Committee. We will take all good-faith reports of harassment by conda community members seriously. This includes harassment outside our spaces and harassment that took place at any point in time.
|
|
89
|
+
|
|
90
|
+
The CoC Committee reserves the right to exclude people from conda Organization spaces based on their past behavior, including behavior outside conda Organization spaces and behavior towards people who are not in the conda community.
|
|
91
|
+
|
|
92
|
+
# Confidentiality and Public Statements to the Community
|
|
93
|
+
|
|
94
|
+
The CoC Committee will keep the identity of the reporter confidential.
|
|
95
|
+
|
|
96
|
+
Whenever possible, CoC cases will be reported to the community. The level of detail in reports will vary from case to case. Reports will describe at least the type of infraction that was reported, and the Committee's decision and any action taken. In most cases, the report will not include personally identifiable information.
|
|
97
|
+
|
|
98
|
+
# Reporting Guidelines
|
|
99
|
+
|
|
100
|
+
If you believe someone is violating the code of conduct, please report this in a timely manner. Code of conduct violations reduce the value of the community for everyone. The conda Code of Conduct (CoC) Committee and the conda Organization take reports of misconduct very seriously and are committed to preserving and maintaining the welcoming nature of our community.
|
|
101
|
+
|
|
102
|
+
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The conda CoC Committee commits to maintaining confidentiality with regard to the reporter of an incident.
|
|
103
|
+
|
|
104
|
+
## How to Submit a Report
|
|
105
|
+
|
|
106
|
+
You can report an incident:
|
|
107
|
+
|
|
108
|
+
* via the [Incident Reporting Form](https://form.jotform.com/221527028480048)
|
|
109
|
+
* via email: [conduct@conda.org](mailto:conduct@conda.org)
|
|
110
|
+
* contact [an individual committee member](#committee-membership) to report an incident in confidence.
|
|
111
|
+
|
|
112
|
+
## Enforcement
|
|
113
|
+
|
|
114
|
+
The CoC Committee will review all reports and determine appropriate action. Potential consequences include:
|
|
115
|
+
|
|
116
|
+
- Nothing (if no violation occurred)
|
|
117
|
+
- Private feedback or reprimand
|
|
118
|
+
- Warning to cease the behavior
|
|
119
|
+
- Temporary or permanent ban from conda Organization spaces
|
|
120
|
+
- Other responses deemed necessary and appropriate
|
|
121
|
+
|
|
122
|
+
For the full details on enforcement, reporting, and committee membership, see the [conda Organization Code of Conduct](https://github.com/conda/conda/blob/main/CODE_OF_CONDUCT.md).
|
|
123
|
+
|
|
124
|
+
# License
|
|
125
|
+
|
|
126
|
+
This code of conduct is based on the [conda Organization Code of Conduct](https://github.com/conda/conda/blob/main/CODE_OF_CONDUCT.md), which is licensed under the [Creative Commons Attribution 3.0 Unported License](https://creativecommons.org/licenses/by/3.0/).
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Contributing to conda-workspaces
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in improving conda-workspaces! This document
|
|
4
|
+
describes how to contribute to the project.
|
|
5
|
+
|
|
6
|
+
## Code of Conduct
|
|
7
|
+
|
|
8
|
+
This project follows the [conda Organization Code of Conduct](CODE_OF_CONDUCT.md).
|
|
9
|
+
Please read it before participating.
|
|
10
|
+
|
|
11
|
+
## Getting started
|
|
12
|
+
|
|
13
|
+
1. Fork the repository on [GitHub](https://github.com/conda-incubator/conda-workspaces).
|
|
14
|
+
2. Clone your fork locally.
|
|
15
|
+
3. Install [pixi](https://pixi.sh) (used for development environments).
|
|
16
|
+
4. Run the tests to make sure everything works:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pixi run test
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Development setup
|
|
23
|
+
|
|
24
|
+
conda-workspaces uses pixi for development environment management. The
|
|
25
|
+
available tasks are defined in `pixi.toml`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pixi run test # run tests
|
|
29
|
+
pixi run test-cov # run tests with coverage
|
|
30
|
+
pixi run lint # run ruff linter
|
|
31
|
+
pixi run format # run ruff formatter
|
|
32
|
+
pixi run typecheck # run ty type checker
|
|
33
|
+
pixi run docs # build documentation
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Making changes
|
|
37
|
+
|
|
38
|
+
### Branch workflow
|
|
39
|
+
|
|
40
|
+
1. Create a new branch from `main` for your changes.
|
|
41
|
+
2. Keep changes focused on a single issue or feature.
|
|
42
|
+
3. Write tests for new functionality.
|
|
43
|
+
4. Make sure all tests pass before submitting.
|
|
44
|
+
|
|
45
|
+
### Code style
|
|
46
|
+
|
|
47
|
+
- All code must be typed using modern annotations (`str | None`, `list[str]`).
|
|
48
|
+
- Use `from __future__ import annotations` in all modules.
|
|
49
|
+
- Use relative imports for intra-package references.
|
|
50
|
+
- Run `pixi run lint` and `pixi run format` before committing.
|
|
51
|
+
- Run `pixi run typecheck` to verify type annotations.
|
|
52
|
+
|
|
53
|
+
### Testing
|
|
54
|
+
|
|
55
|
+
- Tests are plain `pytest` functions — no `unittest.TestCase` classes.
|
|
56
|
+
- Use `pytest.mark.parametrize` for multiple test cases with the same logic.
|
|
57
|
+
- Use `monkeypatch` and native pytest fixtures instead of `unittest.mock`.
|
|
58
|
+
- Tests mirror the source structure (e.g., tests for
|
|
59
|
+
`conda_workspaces/cli/install.py` live in `tests/cli/test_install.py`).
|
|
60
|
+
|
|
61
|
+
### Documentation
|
|
62
|
+
|
|
63
|
+
- Docs use Sphinx with MyST Markdown.
|
|
64
|
+
- Build locally with `pixi run docs`.
|
|
65
|
+
- Follow the [Diataxis framework](https://diataxis.fr/) for new content.
|
|
66
|
+
|
|
67
|
+
## Submitting a pull request
|
|
68
|
+
|
|
69
|
+
1. Push your branch to your fork.
|
|
70
|
+
2. Open a pull request against `main`.
|
|
71
|
+
3. Describe what your change does and why.
|
|
72
|
+
4. Link any related issues.
|
|
73
|
+
5. Make sure CI passes.
|
|
74
|
+
|
|
75
|
+
## Conda Contributor License Agreement
|
|
76
|
+
|
|
77
|
+
To contribute to conda ecosystem projects, you need to sign the
|
|
78
|
+
[Conda Contributor License Agreement (CLA)](https://conda.io/en/latest/contributing.html#conda-contributor-license-agreement).
|
|
79
|
+
|
|
80
|
+
## Generative AI
|
|
81
|
+
|
|
82
|
+
You're welcome to use generative AI tools when contributing. However:
|
|
83
|
+
|
|
84
|
+
- You are responsible for all of your contributions. Review and understand any
|
|
85
|
+
AI-generated content before including it in a pull request.
|
|
86
|
+
- Be prepared to discuss changes during review — do not paste AI responses
|
|
87
|
+
verbatim.
|
|
88
|
+
- Make minimal, focused changes that match the existing style and patterns.
|
|
89
|
+
- Ensure AI-assisted changes actually fix the underlying problem rather than
|
|
90
|
+
altering tests to make them pass.
|
|
91
|
+
|
|
92
|
+
Pull requests consisting of unchecked AI-generated content may be closed.
|
|
93
|
+
|
|
94
|
+
## Getting help
|
|
95
|
+
|
|
96
|
+
- Open an [issue](https://github.com/conda-incubator/conda-workspaces/issues) for
|
|
97
|
+
bug reports or feature requests.
|
|
98
|
+
- Join the [conda community chat](https://conda.zulipchat.com) for questions.
|