aio-libs / aio-libs/aiobotocore
Move to a src/ layout
- Lingua principale
- Python
- Stelle
- 1.4k
- Fork
- 209
- Merge medio
- 4g 15h
- PR unite (30g)
- 16
Descrizione
## Summary
Move the package from a flat layout (`aiobotocore/` at the repo root) to a `src/` layout
(`src/aiobotocore/`).
This is deliberately **not** bundled with the "test the dists" work, because renaming the
package directory touches every path in the repo and would conflict with anything in flight.
Filing it so the reasoning isn't lost.
## Why
With a flat layout, `aiobotocore/` and `tests/` live in the same directory, so a single
`sys.path` entry controls both. That single entry is over-subscribed:
* Tests must be able to import `tests.mock_server` — `conftest.py` forces the multiprocessing
`spawn` start method, and the child process unpickles `AIOServer` by its qualified name
`tests.mock_server.AIOServer`, inheriting the parent's `sys.path`.
* The suite must **not** be able to import `aiobotocore` from the checkout, or CI silently
tests the source tree instead of the wheel it just installed.
Both are served by the same directory, so the two requirements are in direct conflict.
Measured, running the suite out of an unpacked sdist with the wheel installed:
| rootdir on `sys.path`? | installed wheel wins | moto-server tests |
|-|-|-|
| no (`--import-mode=importlib`, no `pythonpath`) | pass | fail — `ModuleNotFoundError: No module named 'tests'` |
| yes | fail — checkout shadows the wheel | pass |
The current workaround is in `tests/conftest.py`: **append** (never insert) the rootdir to
`sys.path`, so `spawn` children can import `tests` while `site-packages` still precedes the
source tree. It works, but it is an ordering convention. Any future `sys.path.insert(0, ...)`,
or a plugin that prepends the rootdir, silently flips CI back to testing the checkout — and
the failure is invisible, because everything still passes.
A `src/` layout removes the conflict instead of balancing it: the rootdir would hold `tests/`
but no importable `aiobotocore`, so putting it on `sys.path` is simply safe. This is PyPA's
stated rationale for the layout:
> if an import package exists in the current working directory with the same name as an
> installed import package, the variant from the current working directory will be used
— https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/
urllib3, cryptography, pip, attrs, black, flask, poetry and trio all use `src/` for this reason.
## What it takes
Mechanical, one commit:
- [ ] `git mv aiobotocore src/aiobotocore`
- [ ] `[tool.hatch.version] path` → `src/aiobotocore/__init__.py`
- [ ] `[tool.hatch.build.targets.wheel] packages` → `["src/aiobotocore"]`
- [ ] `[tool.hatch.build.targets.sdist] include` → `/src` instead of `/aiobotocore`
- [ ] `[tool.coverage.paths]` → `src/aiobotocore/` as the canonical prefix
- [ ] drop `--import-mode=importlib` from `addopts` and the `sys.path.append` block in
`tests/conftest.py` (both exist only to work around the flat layout)
- [ ] `.git-blame-ignore-revs` entry so `git blame` stays useful
- [ ] sweep `docs/`, `plugins/aiobotocore-bot/skills/`, `.github/*-prompt.md` for
`aiobotocore/` path references
No behavior change, no user-visible change — the wheel contents are identical either way.
## When
After the current batch of PRs lands, to avoid mass conflicts.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.