Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ on:
branches: [master]
paths:
- "benchmarks/**"
- "cellpy/**"
- "src/cellpy/**"
- "pyproject.toml"
- "uv.lock"
- ".github/workflows/benchmarks.yml"
push:
branches: [master]
paths:
- "benchmarks/**"
- "cellpy/**"
- "src/cellpy/**"
- "pyproject.toml"
- "uv.lock"
- ".github/workflows/benchmarks.yml"
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ settings.json
/examples/cellpy batch utility/data/cellpyfiles/*
/examples/cellpy batch utility/out/*
/docs/jupyter_execute/
/cellpy/utils/data/*
/src/cellpy/utils/data/*
/import.cvs

0omvp50l.h5
Expand Down
2 changes: 1 addition & 1 deletion .issueflows/00-tools/migrate_prms_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2] / "cellpy"
ROOT = Path(__file__).resolve().parents[2] / "src" / "cellpy"

SKIP = {
ROOT / "parameters" / "_shim.py",
Expand Down
7 changes: 7 additions & 0 deletions .issueflows/03-solved-issues/issue1109_original.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Issue #1109: use src

Source: https://github.com/jepegit/cellpy/issues/1109

## Original issue text

cellpy is currently not using the src convention (package-name/src/package-name), instead the code is inside a folder called cellpy. Use the src-convention.
87 changes: 87 additions & 0 deletions .issueflows/03-solved-issues/issue1109_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Issue #1109 plan: use src layout

## Goal

Move the installable package from `cellpy/` to `src/cellpy/` so the repo
matches the src convention (same shape as cellpy-core). Import path
`cellpy` and the CLI entry point stay the same.

## Constraints

- Public API and `cellpy = "cellpy.cli:cli"` do not change.
- Toolchain stays **uv** + hatchling + git-tag version
([this-project.md](../04-designs-and-guides/this-project.md)).
- Tests keep importing `cellpy` via the editable install (`uv sync`). Do not
add `sys.path` hacks.
- Non-Python package data must still ship:
`logging.json`, `parameters/.cellpy_prms_default.conf`,
`readers/instruments/SQL Table IDs.txt`.
- Do not mix behaviour changes with the move.
- One PR is enough: this is one layout change, not several features.
`/iflow-split` / `/iflow-epic` only if you want docs/CI follow-ups later.

### Prior art

- cellpy-core hatch wheel: `packages = ["src/cellpycore"]` in
`../cellpy-core/pyproject.toml` — **mirror**.
- Current wheel: `packages = ["cellpy"]` in
[`pyproject.toml`](../../pyproject.toml) — **replace**.
- Coverage omit uses `cellpy/libs/*` etc. — **update** to `src/cellpy/...`.
- Toolbox: nothing for a tree move (`00-tools/` is AST scanners).
- Graph: no `graphify-out/` in this worktree checkout.

## Approach

1. **`git mv cellpy src/cellpy`.** Keep history. Create `src/` only for this
package (do not move `tests/`, `docs/`, `examples/`).
2. **Hatch.** Set
```toml
[tool.hatch.build.targets.wheel]
packages = ["src/cellpy"]
```
Confirm `uv build` / `uv sync` still installs `import cellpy` and
`cellpy --help`. If hatchling drops the data files, add a
`force-include` for the three files above.
3. **Tool paths.** Update `[tool.coverage.run]` `source` / `omit` to
`src/cellpy`. Grep workflows, scripts, and Cursor Cloud notes for
`flake8 cellpy`, `black … cellpy`, and path filters `cellpy/**`
(known: `.github/workflows/benchmarks.yml`) and point them at
`src/cellpy`.
4. **Docs / brief.** `this-project.md` entry point line
(`Main package: cellpy/`) → `src/cellpy/`. Short CONTRIBUTING /
developers_guide mention if they describe the tree. Do not rewrite
GitHub URLs that are not filesystem paths.
5. **Sanity.** `uv sync` then `uv run pytest -m essential`. If that is
green, run the full `uv run pytest` before close.
6. **Design note** (during build):
`.issueflows/04-designs-and-guides/src-layout.md` — hatch stanza,
data files, why tests stay at repo-root `tests/`.

## Files to touch

| Path | Change |
| --- | --- |
| `cellpy/` → `src/cellpy/` | `git mv` |
| `pyproject.toml` | hatch `packages`, coverage paths |
| `.github/workflows/benchmarks.yml` | path filters `src/cellpy/**` |
| other CI / lint path hits from grep | same |
| `.issueflows/04-designs-and-guides/this-project.md` | package path |
| `.issueflows/04-designs-and-guides/src-layout.md` | **New.** |
| CONTRIBUTING / `docs/contributing/…` | tree description if present |

## Test strategy

```bash
uv sync
uv run pytest -m essential
uv run pytest
```

No new behavioural tests. Optional: one assert that
`importlib.resources` (or `files("cellpy")`) can open
`.cellpy_prms_default.conf` after the move.

## Open questions

None. Default: hatch `packages = ["src/cellpy"]` like cellpy-core, not
a second top-level name.
16 changes: 16 additions & 0 deletions .issueflows/03-solved-issues/issue1109_status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Issue #1109 status

- [x] Done

## What's done

- `git mv cellpy src/cellpy`
- Hatch wheel `packages = ["src/cellpy"]`; coverage omit paths updated
- Source-walking tests and repo-root `__main__` walks use `src/cellpy`
- CI benchmark path filters, AGENTS lint paths, this-project + src-layout note
- `uv run pytest -m essential`: 959 passed
- `uv run pytest`: 1757 passed, 12 xfailed

## Remaining work

- None
25 changes: 25 additions & 0 deletions .issueflows/04-designs-and-guides/src-layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Src layout

**Issue:** [#1109](https://github.com/jepegit/cellpy/issues/1109)

The installable package lives at `src/cellpy/`. Tests stay at repo-root
`tests/`. Hatch matches cellpy-core:

```toml
[tool.hatch.build.targets.wheel]
packages = ["src/cellpy"]
```

Import path and CLI stay `cellpy`. Editable installs (`uv sync`) put the
package on `sys.path`; tests must not add repo-root `cellpy/` to the path.

Non-Python files that ship in the wheel stay next to the modules
(`logging.json`, `parameters/.cellpy_prms_default.conf`,
`readers/instruments/SQL Table IDs.txt`).

Helpers that walk up from a source file to the **repo root** need three
parents from `src/cellpy/<subdir>/file.py` (`parents[3]`), not two.

Docs: mkdocstrings/Griffe inventories from `src/` (`zensical.toml`
`[project.plugins.mkdocstrings.handlers.python] paths = ["src"]`), same as
cellpy-core. The Docs workflow does not install cellpy.
4 changes: 2 additions & 2 deletions .issueflows/04-designs-and-guides/test-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ current issue**. `/iflow-doctor` may audit the whole suite against this table.
| tests/test_batch_v3_runner.py::test_load_cell_reraises_missing_files_when_not_accepting | yes | yes | batch.runner.load_cell accept_errors | #962 | |
| tests/test_batch_v3_facade.py::test_load_warns_when_no_raw_files_were_found | yes | yes | batch.facade._finalize | #962 | batch.load warning + result.report |
| tests/test_batch_v3_facade.py::test_batch_public_methods_have_shift_tab_docs | yes | yes | batch.facade.Batch | #963 | Shift-Tab docstrings on b.plot etc. |
| tests/test_no_sphinx_doc_roles.py::test_no_sphinx_doc_roles_in_cellpy_source | no | no | cellpy/**/*.py docstrings | #967 | docs chrome; not a merge-gate oracle |
| tests/test_no_sphinx_doc_roles.py::test_no_sphinx_doc_roles_in_cellpy_source | no | no | src/cellpy/**/*.py docstrings | #967 | docs chrome; not a merge-gate oracle |
| tests/test_ica_api.py::test_an_empty_frame_says_the_cycle_is_missing | yes | yes | ica._half_cycles_from_frame | #971 | empty DataFrame() is not a missing-column error |
| tests/test_ica_api.py::test_an_empty_frame_with_curve_columns_says_the_cycle_is_missing | yes | yes | ica._half_cycles_from_frame | #971 | empty-with-columns |
| tests/test_ica_api.py::test_a_missing_cycle_on_a_cell_says_the_frame_is_empty | yes | yes | ica._resolve_source | #971 | CellpyCell + missing cycle |
Expand All @@ -146,7 +146,7 @@ current issue**. `/iflow-doctor` may audit the whole suite against this table.
| tests/test_cli_api.py::test_create_project_with_no_input_creates_the_project_dir | yes | yes | cli_api._new project-dir branch | #990 | no_input must not read stdin (scriptable `cellpy new`) |
| tests/test_cli_api.py::test_list_templates_returns_the_templates_as_data | yes | yes | cli_api.list_templates | #991 | shape contract for non-CLI callers |
| tests/test_cli_api.py::test_the_template_listing_is_rendered_from_list_templates | yes | yes | cli_api._new list_ branch | #991 | printed listing cannot drift from the data |
| tests/test_doc_cross_references.py::test_every_see_reference_names_an_importable_target | yes | yes | cellpy/**/*.py docstring `See `…`` targets | #993 | guards the targets; test_no_sphinx_doc_roles guards the syntax |
| tests/test_doc_cross_references.py::test_every_see_reference_names_an_importable_target | yes | yes | src/cellpy/**/*.py docstring `See `…`` targets | #993 | guards the targets; test_no_sphinx_doc_roles guards the syntax |
| tests/test_doc_cross_references.py::test_the_thinnest_delegates_point_at_their_documentation | yes | yes | CellpyCell.get_cap / to_csv / to_excel | #993 | the three pointers carrying the most undocumented arguments |
| tests/test_batch_summary_ir.py::test_pick_optional_summary_prefers_then_falls_back | yes | yes | plotting.batch_summary._pick_optional_summary | #949 | |
| tests/test_batch_summary_ir.py::test_select_ir_falls_back_and_warns | yes | yes | plotting.batch_summary._select_ir_column | #949 | discharge missing → ir_charge |
Expand Down
2 changes: 1 addition & 1 deletion .issueflows/04-designs-and-guides/this-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ See also [testing-and-coverage.md](testing-and-coverage.md) and [ci-tiers.md](ci

## Entry points

- Main package: `cellpy/` (Python library).
- Main package: `src/cellpy/` (Python library).
- Issue-flow: `.issueflows/` (current issue under `01-current-issues/`).
- **cellpy 2 plans:** sibling repo `../cellpy-design-and-development/` (start at `CURRENT.md`; not `code-reviews/`).
- v2 epic: [cellpy-v2-epic.md](cellpy-v2-epic.md).
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ resolves from PyPI). No manual install is normally needed.
run under `MPLBACKEND=Agg` (no file `--ignore` in Tier 1 / scheduled / release).
Full suite is `uv run pytest` (default `addopts` deselects slow/local/unfinished
markers).
- **Lint/format:** `uv run flake8 cellpy` and `uv run black --check cellpy` (line
- **Lint/format:** `uv run flake8 src/cellpy` and `uv run black --check src/cellpy` (line
length 120). These are not wired into the Tier-1 CI gate, and the repo currently
has pre-existing `black` reformat suggestions and some `flake8 F821` findings —
do not treat those as regressions from your change.
Expand Down
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

* Move the installable package from `cellpy/` to `src/cellpy/`. (#1109)

* Pluggable external metadata sources (read path). New
`cellpy.readers.metadata_sources`: a `MetadataSource` Protocol
(`name`, `fetch(MetaQuery) -> tuple[MetaRecord, ...]`), the
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/developers_guide/dev_various.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Session config lives in **`cellpy.config`** (pydantic models + layered TOML).
do not hand-edit `.cellpy_prms_default.conf` as the source of defaults.

1. Add the field (with type and default) on the right section model in
[`cellpy/config/models.py`](https://github.com/jepegit/cellpy/blob/master/cellpy/config/models.py).
[`src/cellpy/config/models.py`](https://github.com/jepegit/cellpy/blob/master/src/cellpy/config/models.py).
2. Read it as `cellpy.config.<section>.<field>` (or via `get_config()`).
3. Regenerate the user-facing reference:

Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pattern = "default-unprefixed"
fallback-version = "0.0.0"

[tool.hatch.build.targets.wheel]
packages = ["cellpy"]
packages = ["src/cellpy"]

[tool.hatch.build.targets.sdist]
exclude = [
Expand Down Expand Up @@ -157,12 +157,12 @@ filterwarnings = [
line-length = 120

[tool.coverage.run]
source = ["cellpy"]
source = ["src/cellpy"]
branch = true
omit = [
"cellpy/libs/*",
"cellpy/parameters/legacy/*",
"cellpy/_version.py",
"src/cellpy/libs/*",
"src/cellpy/parameters/legacy/*",
"src/cellpy/_version.py",
"*/tests/*",
]

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,6 @@ def write_reference_md(path: str | Path) -> None:


if __name__ == "__main__":
target = Path(__file__).resolve().parents[2] / DOC_PATH
target = Path(__file__).resolve().parents[3] / DOC_PATH
write_reference_md(target)
print(f"wrote {target}")
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ def pages_dict(self, value: PagesDict):
pd.set_option("display.max_columns", None)
print(f"pandas version: {pd.__version__}")

local_dir = pathlib.Path(__file__).parent.parent.parent / "local"
local_dir = pathlib.Path(__file__).resolve().parents[3] / "local"
json_file = local_dir / "cellpy_journal_table.json"
reader = BatBaseJSONReader(json_file, store_raw_data=True)
print(80 * "=")
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -1773,7 +1773,7 @@ def _cell_and_output_path():
this_file = pathlib.Path(__file__)
# p = this_file.parent.parent.parent / "testdata/hdf5/20160805_test001_45_cc.h5"
p = pathlib.Path(r"C:\scripting\cellpy\local\20240516_nor000_01_fccc_01.h5")
out = this_file.parent.parent.parent / "tmp"
out = this_file.resolve().parents[3] / "tmp"

print(f"{p=}")
print(f"{out=}")
Expand Down
2 changes: 1 addition & 1 deletion tests/test_cli_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def test_click_is_gone_from_the_packaging_manifests(manifest):
def test_the_cli_module_does_not_import_click():
"""A declared-dependency check alone would miss a stray `import click`."""
source = (
Path(__file__).resolve().parents[1] / "cellpy" / "cli.py"
Path(__file__).resolve().parents[1] / "src" / "cellpy" / "cli.py"
).read_text(encoding="utf-8")
offenders = [
line.strip()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dependency_budget.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def test_the_dropped_packages_left_the_other_manifests(manifest):
def test_no_source_file_imports_the_dropped_packages():
"""The manifest tests alone would pass with a stray import still around."""
offenders = []
roots = [REPO_ROOT / "cellpy", REPO_ROOT / "tests", REPO_ROOT / "dev"]
roots = [REPO_ROOT / "src" / "cellpy", REPO_ROOT / "tests", REPO_ROOT / "dev"]
for py in (f for root in roots for f in root.rglob("*.py")):
if "libs" in py.parts or py.name == "test_dependency_budget.py":
continue
Expand Down
2 changes: 1 addition & 1 deletion tests/test_doc_cross_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import pytest

CELLPY_SRC = pathlib.Path(__file__).resolve().parents[1] / "cellpy"
CELLPY_SRC = pathlib.Path(__file__).resolve().parents[1] / "src" / "cellpy"

REFERENCE_RE = re.compile(r"See `([A-Za-z_][A-Za-z0-9_.]*)`")

Expand Down
2 changes: 1 addition & 1 deletion tests/test_ica_plot_prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

@pytest.mark.essential
def test_prepare_ica_module_does_not_import_converter():
source = Path("cellpy/plotting/prepare/ica.py").read_text(encoding="utf-8")
source = Path("src/cellpy/plotting/prepare/ica.py").read_text(encoding="utf-8")
tree = ast.parse(source)
imported_names: set[str] = set()
for node in ast.walk(tree):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_index_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import re
import warnings

CELLPY_SRC = pathlib.Path(__file__).resolve().parents[1] / "cellpy"
CELLPY_SRC = pathlib.Path(__file__).resolve().parents[1] / "src" / "cellpy"

# Sanctioned boundary locations (relative, forward-slash) — index use allowed.
ALLOWED_PARTS = (
Expand Down
2 changes: 1 addition & 1 deletion tests/test_no_sphinx_doc_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pathlib
import re

CELLPY_SRC = pathlib.Path(__file__).resolve().parents[1] / "cellpy"
CELLPY_SRC = pathlib.Path(__file__).resolve().parents[1] / "src" / "cellpy"

ROLE_RE = re.compile(
r":(?:class|meth|func|mod|attr|data|exc|obj|paramref):`[^`]+`"
Expand Down
2 changes: 1 addition & 1 deletion tests/test_plotting_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def test_collectors_has_no_import_time_plotly_calls():
import pathlib

source = (
pathlib.Path(__file__).resolve().parents[1] / "cellpy" / "utils" / "collectors.py"
pathlib.Path(__file__).resolve().parents[1] / "src" / "cellpy" / "utils" / "collectors.py"
).read_text(encoding="utf-8")

plotly_aliases = {"go", "pio", "px", "plotly"}
Expand Down
2 changes: 1 addition & 1 deletion zensical.toml
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ auto_append = ["docs/.snippets/abbreviations.md"]
# https://zensical.org/docs/setup/extensions/mkdocstrings/
# ----------------------------------------------------------------------------
[project.plugins.mkdocstrings.handlers.python]
paths = ["."]
paths = ["src"]
inventories = ["https://docs.python.org/3/objects.inv"]

[project.plugins.mkdocstrings.handlers.python.options]
Expand Down
Loading