aio-libs / aio-libs/aiobotocore

Move to a src/ layout

Aperta
#1,685 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
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.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.