Manifests#
Manifest parsers and the detection/registry system.
Each parser handles both workspace configuration and task definitions
for its file format. The manifests/ package is conda-workspaces’
internal substrate; the package-root modules env_spec.py,
lockfile.py and export.py sit on top and expose the public
plugin API.
Manifest detection and parser registry (workspaces and tasks).
Search order (same for workspaces and tasks)#
conda.toml– conda-native manifest formatpixi.toml– pixi-native format (compatibility)pyproject.toml– pixi or conda tables embedded
The first file that exists and contains the relevant configuration wins.
- conda_workspaces.manifests.detect_and_parse(start_dir: str | Path | None = None) tuple[Path, WorkspaceConfig][source]#
Detect the workspace manifest and parse it.
Returns
(manifest_path, workspace_config).
- conda_workspaces.manifests.detect_and_parse_tasks(file_path: Path | None = None, start_dir: Path | None = None) tuple[Path, dict[str, Task]][source]#
Detect (or use file_path) a task file and parse it.
Returns
(resolved_path, {task_name: Task}). RaisesNoTaskFileErrorwhen no file is found.
- conda_workspaces.manifests.detect_task_file(start_dir: Path | None = None) Path | None[source]#
Walk up from start_dir looking for a file that contains tasks.
Returns the first match according to
_SEARCH_FILES, orNone.
- conda_workspaces.manifests.detect_workspace_file(start_dir: str | Path | None = None) Path[source]#
Walk up from start_dir to find a workspace manifest.
Returns the path to the first matching file. Raises
WorkspaceNotFoundErrorif none is found.
- conda_workspaces.manifests.find_parser(path: Path) ManifestParser[source]#
Return the parser that can handle path.
Raises
WorkspaceParseErrorif no parser matches.
Abstract base class for manifest parsers (workspaces and tasks).
- class conda_workspaces.manifests.base.ManifestParser[source]#
Interface that every manifest parser must implement.
Each parser handles one file format (
conda.toml,pixi.toml, orpyproject.toml). Subclasses declare which files they can handle via filenames and a short format_alias ("conda"/"pixi"/"pyproject") that the CLI uses for--formatvalues. The registry inconda_workspaces.manifestsuses these to auto-detect the right parser and to resolve--formataliases to the parser that owns the matching filename.A single parser instance handles both workspace configuration and task definitions from the same file.
- classmethod copy_manifest(source: Path, dest_dir: Path) Path[source]#
Copy the manifest at source into dest_dir; return the target path.
source may be a directory (walked via
resolve_source()) or a manifest file. RaisesFileNotFoundError,conda_workspaces.exceptions.WorkspaceNotFoundError, orconda_workspaces.exceptions.ManifestExistsErroras appropriate; callers layer their own dry-run / console policy on top.
- export(envs: Iterable[Environment]) str[source]#
Serialize envs to this parser’s manifest format.
Produces a manifest that, when written to disk and parsed by
parse(), describes the same requested dependencies, channels, and declared platforms that envs carry. EachEnvironmentis one(name, platform)pair; envs must all share the samename(conda’sCondaEnvironmentExporterhook callsmultiplatform_exportwith per-platform copies of the same logical environment).The default implementation writes top-level
[workspace],[dependencies],[pypi-dependencies], and[target.<platform>.*]tables — the shapeconda.tomlandpixi.tomlshare.PyprojectTomlParseroverrides it to nest the same content under[tool.conda]without disturbing the rest of the pyproject. Used as themultiplatform_exportcallable on the exporter plugins registered fromconda_workspaces.plugin.
- exporter_aliases: ClassVar[tuple[str, ...]] = ()#
Optional user-friendly aliases for the exporter plugin (e.g.
("conda",)forconda-toml). Empty tuple is fine.
- exporter_format: ClassVar[str] = ''#
Canonical
conda_environment_exportersplugin name. Empty disables exporter registration for that parser (seeconda_workspaces.plugin).
- filenames: ClassVar[tuple[str, ...]] = ()#
- classmethod for_exporter_format(name: str) ManifestParser | None[source]#
Return the registered parser whose
exporter_formatmatches name.Companion to
for_format_alias()for theconda_environment_exportersplugin side:conda workspace export --format <name>uses the exporter plugin name (e.g.pyproject-toml), which is stored onexporter_formatrather thanformat_alias. ReturnsNonewhen name is not a manifest-format exporter — the CLI uses this to decide whether to route writes throughmerge_export(), and aNoneresult simply means “not one of ours, write verbatim”.
- classmethod for_format_alias(alias: str) ManifestParser[source]#
Return the registered parser whose
format_aliasmatches alias.Used by
conda workspace init/quickstartto turn a--formatvalue like"pyproject"/"conda"/"pixi"into the parser (and therefore the filename) it implies. RaisesValueErrorwhen no parser claims alias. The companion lookup forconda workspace export --formatisfor_exporter_format()— that side matches the longerconda_environment_exportersplugin name ("pyproject-toml","conda-toml","pixi-toml") which is stored onexporter_format. The registry isconda_workspaces.manifests._PARSERS.
- format_alias: ClassVar[str] = ''#
- abstractmethod has_workspace(path: Path) bool[source]#
Return True if path contains workspace configuration.
- classmethod manifest_data(envs: Iterable[Environment]) dict[str, Any][source]#
Fold one or more
Environmentobjects into a manifest-shaped dict.Returns the data that
export()writers need, with the format-agnostic parts decided once:name/platforms/channelsdescribe the[workspace]table (platforms are the sorted union across envs; channels are taken from the first env — exporter callers pass the same channel list on every platform).conda_deps/pypi_depsare the intersection across envs — specs that match by name and value on every platform, the ones a round-trip parse would put under the top-level[dependencies]/[pypi-dependencies]tables.target[<platform>]["conda"|"pypi"]holds the per-platform delta — specs that appear on some platforms but not others, or whose value differs across platforms. A round-trip parse restores these under[target.<platform>.dependencies]/[target.<platform>.pypi-dependencies].
Used by
export()(via_emit_manifest()) and exposed as a classmethod so individual parsers and exporter plugin shims can drive the same folding logic without duplicating it.
- property manifest_filename: str#
Canonical filename this parser reads and writes.
The first entry in
filenames— e.g."conda.toml"forCondaTomlParser. Used bymanifest_path()and theconda workspace init/quickstartCLI paths so the format-to-filename mapping lives in exactly one place.
- manifest_path(root: Path) Path[source]#
Return the manifest path this parser would (or did) write inside root.
- merge_export(existing_path: Path, exported: str) str[source]#
Return exported ready to write into an existing existing_path.
The default implementation returns exported unchanged —
conda.tomlandpixi.tomlare manifests we own end-to-end, so regenerating them from an environment is a full replacement (same asconda export -f environment.yamloverwriting an existing environment.yaml).PyprojectTomlParseroverrides this to splice the exporter’s[tool.conda]subtree into the existingpyproject.tomldocument without disturbing peer tables ([project],[build-system],[tool.ruff]etc.), becausepyproject.tomlis a shared manifest owned by the Python ecosystem. Called fromconda_workspaces.cli.workspace.exportonly when--filepoints to an existing file, so a fresh export still writes the exporter output verbatim.
- abstractmethod parse(path: Path) WorkspaceConfig[source]#
Parse path and return a
WorkspaceConfig.
- parse_tasks(path: Path) dict[str, Task][source]#
Parse path and return a mapping of task-name to Task.
- remove_target_overrides(container: Container, name: str) None[source]#
Remove name from every
[target.<platform>.tasks]under container.
- classmethod resolve_source(source: Path) Path[source]#
Resolve source (directory or file) to a concrete manifest path.
Directories are walked via
conda_workspaces.manifests.detect_workspace_file(); files are returned as-is. RaisesFileNotFoundErrorwhen source does not exist andconda_workspaces.exceptions.WorkspaceNotFoundErrorwhen the directory contains no recognisable manifest.
- task_to_toml_inline(task: Task) str | InlineTable[source]#
Convert a task to a TOML-serializable value (string or inline table).
- write_workspace_stub(base_dir: Path, name: str, channels: list[str], platforms: list[str]) tuple[Path, str][source]#
Create a minimal workspace manifest under base_dir.
Writes a fresh TOML document with
[workspace]and an empty[dependencies]table atmanifest_path()and returns(path, "Created"). RaisesManifestExistsErrorif the target file is already present — subclasses that share their file with other tooling (seePyprojectTomlParser) override this method to append their configuration under a nested table instead of refusing outright, and report"Updated"when they did so.
Parser for conda.toml manifests and shared TOML helpers.
The CondaTomlParser handles conda.toml — the conda-native
manifest format for both workspace configuration and task definitions.
Helper functions for parsing channels, dependencies, environments,
and target overrides are shared with pixi_toml.py and
pyproject_toml.py.
- class conda_workspaces.manifests.toml.CondaTomlParser[source]#
Parse
conda.tomlmanifests (workspace and tasks).This is the conda-native format that mirrors pixi.toml structure but uses
[workspace]exclusively (no[project]fallback).- exporter_format = 'conda-toml'#
Canonical
conda_environment_exportersplugin name. Empty disables exporter registration for that parser (seeconda_workspaces.plugin).
- filenames = ('conda.toml',)#
- format_alias = 'conda'#
- parse(path: Path) WorkspaceConfig[source]#
Parse path and return a
WorkspaceConfig.
- conda_workspaces.manifests.toml.tasks_to_toml(tasks: dict[str, Task]) str[source]#
Serialize a full task dict to
conda.tomlTOML string.
Parser for pixi.toml workspace manifests.
Reads [workspace] (or [project] for legacy manifests),
[dependencies], [pypi-dependencies], [feature.*],
[environments], and [target.*] tables from pixi.toml.
- class conda_workspaces.manifests.pixi_toml.PixiTomlParser[source]#
Parse
pixi.tomlmanifests (workspace and tasks).- exporter_format = 'pixi-toml'#
Canonical
conda_environment_exportersplugin name. Empty disables exporter registration for that parser (seeconda_workspaces.plugin).
- filenames = ('pixi.toml',)#
- format_alias = 'pixi'#
- parse(path: Path) WorkspaceConfig[source]#
Parse path and return a
WorkspaceConfig.
Parser for pyproject.toml workspace manifests.
Reads workspace configuration from pyproject.toml, trying these
tables in order:
[tool.conda.workspace]– conda-native table[tool.pixi.workspace]– pixi compatibility
- class conda_workspaces.manifests.pyproject_toml.PyprojectTomlParser[source]#
Parse workspace and task config from
pyproject.toml.Tries these tool tables in priority order:
[tool.conda.*]– conda-native tables[tool.pixi.*]– pixi compatibility
- export(envs: Iterable[Environment]) str[source]#
Serialize envs as a
pyproject.tomlwith[tool.conda.*].Same content as
ManifestParser.export()— workspace table, dependencies, optional pypi-dependencies, optional per-platform overrides — but wrapped under[tool.conda]so the output drops straight into PEP 621 /pyproject.tomlalongside[project],[build-system], and peer tables.
- exporter_format = 'pyproject-toml'#
Canonical
conda_environment_exportersplugin name. Empty disables exporter registration for that parser (seeconda_workspaces.plugin).
- filenames = ('pyproject.toml',)#
- format_alias = 'pyproject'#
- merge_export(existing_path: Path, exported: str) str[source]#
Splice exported’s
[tool.conda]into existing_path.pyproject.tomlis a shared packaging manifest owned by the Python ecosystem; the default “overwrite the file wholesale” behaviour ofManifestParser.merge_export()would silently destroy[project]/[build-system]/[tool.ruff]/ etc. Instead we parse the existing document, replace its[tool.conda]subtree with the oneexport()just produced, and serialise the result.This is the export-side companion to
write_workspace_stub(), which does the same kind of nested-table merge forconda workspace init. Existing[tool.pixi]content is preserved untouched — users who mix both tools stay functional.
- parse(path: Path) WorkspaceConfig[source]#
Parse path and return a
WorkspaceConfig.
- parse_tasks(path: Path) dict[str, Task][source]#
Parse path and return a mapping of task-name to Task.
- tool_section_for_tasks(doc: tomlkit.TOMLDocument) Table[source]#
Return the
toolsub-table that owns tasks.Uses the same precedence as
parse_tasks: non-emptytool.condawins, then non-emptytool.pixi, then falls back totool.condafor new manifests.
- write_workspace_stub(base_dir: Path, name: str, channels: list[str], platforms: list[str]) tuple[Path, str][source]#
Add
[tool.conda.workspace]to base_dir/pyproject.toml.Unlike the default
ManifestParser.write_workspace_stub()(which refuses to touch an existing file),pyproject.tomlis a shared packaging manifest owned by the Python ecosystem — PEP 621[project],[build-system], and other tooling tables routinely coexist with ours. We read the existing document if any, add our configuration under the nested[tool.conda]table, and report"Updated"so the CLI can distinguish an append from a create. An existing[tool.conda]or[tool.pixi]raisesManifestExistsError.
Shared logic for normalizing raw task dicts into Task model objects.
- conda_workspaces.manifests.normalize.normalize_args(raw: list[Any] | None) list[TaskArg][source]#
Convert raw arg definitions into TaskArg objects.
Accepted shapes: -
["name"](required arg, no default) -[{"arg": "name", "default": "value"}]-[{"arg": "name", "default": "value", "choices": ["a", "b"]}]
- conda_workspaces.manifests.normalize.normalize_depends_on(raw: list[Any] | str | None) list[TaskDependency][source]#
Convert the various
depends-onformats into TaskDependency objects.Accepted shapes: -
["foo", "bar"](simple list of task names) -[{"task": "foo", "args": ["x"]}, ...](full dict form) -[{"task": "foo"}, {"task": "bar"}](pixi alias shorthand)
- conda_workspaces.manifests.normalize.normalize_override(raw: dict[str, Any]) TaskOverride[source]#
Parse a raw dict into a TaskOverride.
- conda_workspaces.manifests.normalize.normalize_task(name: str, raw: str | list[Any] | dict[str, Any]) Task[source]#
Convert a single raw task value into a Task object.
Handles all the shorthand forms: -
"command string"(simple string command) -["dep1", "dep2"]or[{"task": ...}](alias / dependency-only) -{cmd: ..., depends-on: ..., ...}(full dict definition)
- conda_workspaces.manifests.normalize.parse_feature_tasks(data: dict[str, Any], tasks: dict[str, Task]) None[source]#
Parse
[feature.<name>.tasks]and their target overrides.Merges feature-scoped tasks into tasks in place. Shared by
PixiTomlParserandPyprojectTomlParser.
- conda_workspaces.manifests.normalize.parse_tasks_and_targets(data: dict[str, Any]) dict[str, Task][source]#
Parse
[tasks]and[target.<platform>.tasks]from a data dict.Shared by
CondaTomlParser,PixiTomlParser, andPyprojectTomlParser— the core parsing logic is identical across all three formats once the root data dict is resolved.