Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ build: $(UV) .venv ## Build virtual-env and install deps
build-release: build ## Build artefacts (sdist & wheel)
$(UV) run python -m build --sdist --wheel

clean: ## Remove build artifacts
clean: ## Remove build artefacts
rm -rf build dist *.egg-info \
.mypy_cache .pytest_cache .coverage coverage.* \
lcov.info htmlcov .venv
Expand Down
12 changes: 6 additions & 6 deletions docs/developers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,15 +366,15 @@ property test in `tests/unit/test_bump_command_internals.py`, which exercises

### Workspace path normalization (`lading/utils/path.py`)

`normalise_workspace_root(value)` is the shared helper that turns a
`normalize_workspace_root(value)` is the shared helper that turns a
user-supplied workspace root into a canonical `Path`. Import it from
`lading.utils`:

```python
from lading.utils import normalise_workspace_root
from lading.utils import normalize_workspace_root

normalise_workspace_root("~/workspace") # -> absolute, ~ expanded
normalise_workspace_root(None) # -> Path.cwd().resolve()
normalize_workspace_root("~/workspace") # -> absolute, ~ expanded
normalize_workspace_root(None) # -> Path.cwd().resolve()
```

It accepts `Path`, `str`, or `None`. `None` selects the resolved current
Expand Down Expand Up @@ -451,7 +451,7 @@ metadata = load_cargo_metadata(Path("/path/to/workspace"))
print(metadata["workspace_root"])
```

The helper normalizes the workspace path with `normalise_workspace_root`,
The helper normalizes the workspace path with `normalize_workspace_root`,
invokes `cargo metadata --format-version 1` through the active `CommandRunner`,
and returns the parsed JSON mapping. Any execution errors or invalid output
raise `CargoMetadataError` with a descriptive message, so callers can present
Expand Down Expand Up @@ -647,7 +647,7 @@ canonical replacement callers and tests now use directly:

| Removed shim | Location | Canonical replacement |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Eleven `publish_preflight` private aliases (`_preflight_argument_sets`, `_CargoPreflightOptions`, `_apply_compiletest_externs`, `_build_preflight_environment`, `_build_test_arguments`, `_compose_preflight_arguments`, `_normalise_test_excludes`, `_run_aux_build_commands`, `_run_cargo_preflight`, `_validate_lockfile_freshness`, `_verify_clean_working_tree`) | `publish.py` | `lading.commands.publish_preflight` (patch/call the defining module directly) |
| Eleven `publish_preflight` private aliases (`_preflight_argument_sets`, `_CargoPreflightOptions`, `_apply_compiletest_externs`, `_build_preflight_environment`, `_build_test_arguments`, `_compose_preflight_arguments`, `_normalize_test_excludes`, `_run_aux_build_commands`, `_run_cargo_preflight`, `_validate_lockfile_freshness`, `_verify_clean_working_tree`) | `publish.py` | `lading.commands.publish_preflight` (patch/call the defining module directly) |
| `_run_preflight_checks` thin wrapper | `publish.py` | `publish_preflight._run_preflight_checks` (called directly by `run()`) |
| Re-exports `_append_section`, `_format_plan` | `publish.py` | `publish_plan.append_section`, `publish_plan.format_plan` |
| Re-export `metadata_module` | `publish.py` | `lading.workspace.metadata` |
Expand Down
2 changes: 1 addition & 1 deletion docs/documentation-style-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ consistent, and easy to maintain across projects.
- suffix -ogue in words such as _analogue_ and _catalogue_,
- and so forth.
- The words **"outwith"** and **"caveat"** are acceptable.
- Keep United States (US) spelling when used in an API, for example, `color`.
- Use Oxford spelling in internal APIs, for example, `colour`.
- The project uses the filename `LICENSE` for community consistency.

## Punctuation and grammar
Expand Down
2 changes: 1 addition & 1 deletion docs/execplans/regenerate-lockfiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ fixture lockfile and seeing that lockfile listed in the bump output with a
- [x] (2026-07-07 12:20Z) Stage A: prototype proved
`cargo update --workspace --manifest-path <nested>` restores freshness for a
nested fixture package with a path dependency on a bumped workspace crate. See
`Artifacts and notes`. No fallback command needed.
`Artefacts and notes`. No fallback command needed.
- [x] (2026-07-07 13:10Z) Stage B: red tests landed and observed failing for
the expected reasons — three new unit tests plus the two extended wiring
tests failed with
Expand Down
6 changes: 3 additions & 3 deletions docs/lading-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ lading [--workspace-root <path>] <subcommand> [options]
- `--workspace-root` is implemented as a global flag that can be positioned
before or after the subcommand. The bootstrapper removes the flag from the
argument list, normalizes it via the shared
`lading.utils.normalise_workspace_root` helper (implemented with
`lading.utils.normalize_workspace_root` helper (implemented with
`pathlib.Path` alone), and stores the resolved path in the
`LADING_WORKSPACE_ROOT` environment variable so that Cyclopts can hydrate
per-command options without bespoke parsing hooks.
Expand Down Expand Up @@ -226,7 +226,7 @@ build scripts, and complex workspace configurations.
- Workspace discovery is anchored in `lading.workspace.metadata`. The module
invokes `cargo metadata --format-version 1` through the active
`CommandRunner`, normalizing the workspace root via
`lading.utils.normalise_workspace_root` before invoking the command.
`lading.utils.normalize_workspace_root` before invoking the command.
- Failures to locate the `cargo` executable raise
`CargoExecutableNotFoundError`; non-zero exit codes raise
`CargoMetadataInvocationError`; malformed JSON payloads raise
Expand Down Expand Up @@ -602,7 +602,7 @@ lading/
├── config.py # Frozen dataclasses for `lading.toml`
├── utils/
│ ├── __init__.py
│ └── path.py # Filesystem helpers such as `normalise_workspace_root`
│ └── path.py # Filesystem helpers such as `normalize_workspace_root`
└── workspace/
├── __init__.py
├── metadata.py # `cargo metadata` invocation and parsing
Expand Down
2 changes: 1 addition & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ invocation and path utilities.

- **Outcome:** Path normalization uses `pathlib.Path` directly, removing the
`plumbum.local.path()` dependency.
- **Completion Criteria:** `normalise_workspace_root()` behaviour unchanged;
- **Completion Criteria:** `normalize_workspace_root()` behaviour unchanged;
plumbum import removed from the module.

______________________________________________________________________
Expand Down
4 changes: 2 additions & 2 deletions docs/scripting-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,9 @@ from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parents[1]
DIST = PROJECT_ROOT / "dist"
(DIST / "artifacts").mkdir(parents=True, exist_ok=True)
(DIST / "artefacts").mkdir(parents=True, exist_ok=True)

# Portable joins and normalisation
# Portable joins and normalization
cfg = PROJECT_ROOT.joinpath("config", "release.toml").resolve()
```

Expand Down
8 changes: 4 additions & 4 deletions lading/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
WorkspaceRootOption,
)
from .runtime import CommandRunner, subprocess_runner
from .utils import metrics, normalise_workspace_root
from .utils import metrics, normalize_workspace_root
from .workspace import WorkspaceGraph, WorkspaceModelError, load_workspace
from .workspace import metadata as metadata_module

Expand Down Expand Up @@ -262,7 +262,7 @@ def main(argv: cabc.Sequence[str] | None = None) -> int:
# an import-time side effect of lading.utils.metrics.
metrics.register_summary_atexit()
workspace_override, remaining = _extract_workspace_override(list(argv))
workspace_root = normalise_workspace_root(workspace_override)
workspace_root = normalize_workspace_root(workspace_override)
if not remaining:
_dispatch_and_print(remaining) # Print usage message
return 2 # Standard exit code for missing subcommand
Expand Down Expand Up @@ -353,7 +353,7 @@ def bump(
>>> "Dry run; would update version to 1.2.3 in" in summary # doctest: +SKIP
True
"""
resolved = normalise_workspace_root(workspace_root)
resolved = normalize_workspace_root(workspace_root)
return _run_with_context(
resolved,
lambda root, configuration, workspace, command_runner: commands.bump.run(
Expand Down Expand Up @@ -420,7 +420,7 @@ def publish(
>>> readmes in summary # doctest: +SKIP
True
"""
resolved = normalise_workspace_root(workspace_root)
resolved = normalize_workspace_root(workspace_root)
return _run_with_context(
resolved,
lambda root, configuration, workspace, command_runner: commands.publish.run(
Expand Down
4 changes: 2 additions & 2 deletions lading/commands/bump.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
_workspace_dependency_sections,
)
from lading.commands.bump_output import BumpChanges, _format_result_message
from lading.utils import normalise_workspace_root
from lading.utils import normalize_workspace_root

if typ.TYPE_CHECKING:
from pathlib import Path
Expand Down Expand Up @@ -193,7 +193,7 @@ def _initialize_bump_context(
) -> _BumpContext:
"""Return the initialised bump context for ``workspace_root``."""
resolved_options = BumpOptions() if options is None else options
root_path = normalise_workspace_root(workspace_root)
root_path = normalize_workspace_root(workspace_root)
configuration = resolved_options.configuration
if configuration is None:
configuration = config_module.current_configuration()
Expand Down
16 changes: 8 additions & 8 deletions lading/commands/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
from lading.commands.publish_plan import (
PublishPlanError as PublishPlanError, # public re-export for plan_publication
)
from lading.utils.path import normalise_workspace_root
from lading.utils.path import normalize_workspace_root

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -136,7 +136,7 @@ class PublishOptions:
Defaults to :data:`False` so publishing remains a dry-run unless
explicitly enabled.
build_directory:
Optional directory used to stage workspace artifacts. When ``None``,
Optional directory used to stage workspace artefacts. When ``None``,
a temporary directory is created for each invocation.
preserve_symlinks:
Control whether staging preserves symbolic links in the workspace
Expand Down Expand Up @@ -180,10 +180,10 @@ class PublishPreparation:
copied_readmes: tuple[Path, ...]


def _normalise_build_directory(
def _normalize_build_directory(
workspace_root: Path, build_directory: Path | None
) -> Path:
"""Return a directory suitable for staging workspace artifacts."""
"""Return a directory suitable for staging workspace artefacts."""
if build_directory is None:
return Path(tempfile.mkdtemp(prefix="lading-publish-"))

Expand Down Expand Up @@ -244,7 +244,7 @@ def prepare_workspace(
PublishPreparationError
If the staging build directory or copied workspace path is unsafe or
invalid (for example nested within the workspace root); propagated
from :func:`_normalise_build_directory` and :func:`_copy_workspace_tree`.
from :func:`_normalize_build_directory` and :func:`_copy_workspace_tree`.

Examples
--------
Expand All @@ -253,7 +253,7 @@ def prepare_workspace(
PosixPath('/tmp/lading-publish-abcd1234/my-workspace')
"""
active_options = PublishOptions() if options is None else options
build_directory = _normalise_build_directory(
build_directory = _normalize_build_directory(
plan.workspace_root, active_options.build_directory
)
LOGGER.info(
Expand Down Expand Up @@ -550,7 +550,7 @@ def _execute_live_publication_pipeline(
)
except PublishPreparationError as exc:
# Preparation failures escape the preflight/publish error taxonomy;
# normalise them so the live pipeline reports a single abort class.
# normalize them so the live pipeline reports a single abort class.
LOGGER.exception(
"Live pipeline: aborted on crate %s — %d/%d crates completed (%s)",
crate.name,
Expand Down Expand Up @@ -712,7 +712,7 @@ def run(
>>> "Staged workspace at:" in summary # doctest: +SKIP
True
"""
root_path = normalise_workspace_root(workspace_root)
root_path = normalize_workspace_root(workspace_root)
LOGGER.info("Starting publish workflow for workspace %s", root_path)
effective_options = PublishOptions() if options is None else options
_validate_publication_options(effective_options)
Expand Down
44 changes: 22 additions & 22 deletions lading/commands/publish_diagnostics.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Compiletest stderr artifact discovery and diagnostics formatting."""
"""Compiletest stderr artefact discovery and diagnostics formatting."""

from __future__ import annotations

Expand All @@ -8,22 +8,22 @@
_STDERR_PATTERN = re.compile(r"(/[^\s)]+\.stderr)")


def _trim_artifact_token(token: str) -> str:
"""Normalise compiletest artifact tokens by stripping punctuation."""
def _trim_artefact_token(token: str) -> str:
"""Normalize compiletest artefact tokens by stripping punctuation."""
return token.rstrip(")]:,.;'\"")


def _discover_stderr_artifacts(stream: str) -> tuple[Path, ...]:
def _discover_stderr_artefacts(stream: str) -> tuple[Path, ...]:
"""Return ``Path`` objects extracted from compiletest output stream."""
artifacts: list[Path] = []
artefacts: list[Path] = []
seen: set[str] = set()
for match in _STDERR_PATTERN.finditer(stream):
raw = _trim_artifact_token(match.group(1))
raw = _trim_artefact_token(match.group(1))
if raw in seen:
continue
seen.add(raw)
artifacts.append(Path(raw))
return tuple(artifacts)
artefacts.append(Path(raw))
return tuple(artefacts)


def _read_tail_lines(path: Path, count: int) -> tuple[str, ...]:
Expand All @@ -38,13 +38,13 @@ def _read_tail_lines(path: Path, count: int) -> tuple[str, ...]:
return tuple(lines[-count:]) if lines else ()


def _format_artifact_diagnostics(artifact: Path, tail_lines: int) -> list[str]:
"""Return formatted diagnostic lines for a compiletest stderr artifact."""
lines = [f"- {artifact}"]
if not artifact.exists():
def _format_artefact_diagnostics(artefact: Path, tail_lines: int) -> list[str]:
"""Return formatted diagnostic lines for a compiletest stderr artefact."""
lines = [f"- {artefact}"]
if not artefact.exists():
lines.append(" (file not found)")
return lines
tail = _read_tail_lines(artifact, tail_lines)
tail = _read_tail_lines(artefact, tail_lines)
if not tail:
return lines
header = f" Last {tail_lines} line(s):"
Expand All @@ -60,22 +60,22 @@ def _append_compiletest_diagnostics(
*,
tail_lines: int,
) -> str:
"""Append compiletest stderr artifact hints to ``message`` when present."""
artifacts: list[Path] = []
"""Append compiletest stderr artefact hints to ``message`` when present."""
artefacts: list[Path] = []
seen: set[Path] = set()
for candidate in (
*_discover_stderr_artifacts(stdout),
*_discover_stderr_artifacts(stderr),
*_discover_stderr_artefacts(stdout),
*_discover_stderr_artefacts(stderr),
):
if candidate in seen:
continue
seen.add(candidate)
artifacts.append(candidate)
if not artifacts:
artefacts.append(candidate)
if not artefacts:
return message
lines = [message, "Compiletest stderr artifacts:"]
for artifact in artifacts:
lines.extend(_format_artifact_diagnostics(artifact, tail_lines))
lines = [message, "Compiletest stderr artefacts:"]
for artefact in artefacts:
lines.extend(_format_artefact_diagnostics(artefact, tail_lines))
return "\n".join(lines)


Expand Down
2 changes: 1 addition & 1 deletion lading/commands/publish_index_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def _raise_unpublished_dependency_override_required(


def _canonical_crate_name(name: str) -> str:
"""Return the canonical crate name by normalising hyphens to underscores."""
"""Return the canonical crate name by normalizing hyphens to underscores."""
return name.replace("-", "_")


Expand Down
4 changes: 2 additions & 2 deletions lading/commands/publish_preflight.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def _preflight_argument_sets(
return check_arguments, test_arguments


def _normalise_test_excludes(entries: cabc.Sequence[str]) -> tuple[str, ...]:
def _normalize_test_excludes(entries: cabc.Sequence[str]) -> tuple[str, ...]:
"""Return sorted, deduplicated, trimmed crate names for ``--exclude`` flags."""
return tuple(sorted({crate.strip() for crate in entries if crate.strip()}))

Expand All @@ -281,7 +281,7 @@ def _build_test_arguments(
) -> list[str]:
"""Return cargo test arguments derived from ``options``."""
arguments = list(base_arguments)
for crate_name in _normalise_test_excludes(options.test_excludes):
for crate_name in _normalize_test_excludes(options.test_excludes):
# Sorted unique values keep cargo invocations deterministic for tests/logging.
arguments.extend(("--exclude", crate_name))
if options.unit_tests_only:
Expand Down
6 changes: 3 additions & 3 deletions lading/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from lading import toml_coerce
from lading.exceptions import LadingError
from lading.utils import normalise_workspace_root
from lading.utils import normalize_workspace_root

if typ.TYPE_CHECKING: # pragma: no cover - type checking only
from pathlib import Path
Expand Down Expand Up @@ -385,7 +385,7 @@ def build_loader(workspace_root: Path) -> Toml:
>>> build_loader(Path("workspace")).path.name
'lading.toml'
"""
resolved = normalise_workspace_root(workspace_root)
resolved = normalize_workspace_root(workspace_root)
return Toml(
path=resolved / CONFIG_FILENAME,
must_exist=False,
Expand Down Expand Up @@ -516,7 +516,7 @@ def current_configuration() -> LadingConfig:


def _strip_patches(value: object) -> StripPatchesSetting:
"""Normalise the ``publish.strip_patches`` value."""
"""Normalize the ``publish.strip_patches`` value."""
if value is None:
return "per-crate"
if value in {"all", "per-crate"}:
Expand Down
4 changes: 2 additions & 2 deletions lading/runtime/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@


def coerce_text(value: str | bytes) -> str:
"""Normalise process output to text.
"""Normalize process output to text.

Parameters
----------
value : str | bytes
Process output to normalise, as returned by a subprocess call.
Process output to normalize, as returned by a subprocess call.

Returns
-------
Expand Down
Loading
Loading