ADR-001 — Python module packaging and structure
Status: Accepted
Context
The project is a standalone Python module that exposes an interface for communicating with the Hanel automatic warehouse via SOAP. Before writing code, the packaging structure and source file layout must be established.
Options evaluated
| Option | Pros | Cons |
|---|---|---|
setup.py legacy |
Familiar, universally supported | Deprecated, not PEP 621 standard |
setup.cfg |
Separation of config from code | Semi-legacy, superseded by pyproject.toml |
pyproject.toml (PEP 517/621) |
Modern standard, supported by pip/build/hatch/uv | None relevant |
Decision
We adopt pyproject.toml with a src/ layout (PEP 517/621).
The src/ layout prevents the package from being importable directly from the project root during development, enforcing installation via uv sync and reducing false positives in tests.
Directory structure
hanel_warehouse_gateway/ ← repository root
├── src/
│ └── hanel_warehouse_gateway/
│ ├── __init__.py ← exposes HanelWarehouseGateway, GatewayConfig, public dataclasses, exceptions
│ ├── gateway.py ← Layer 3: HanelWarehouseGateway (public interface)
│ ├── operations.py ← Layer 2: SOAP operation mapping
│ ├── transport.py ← Layer 1: HTTP/SOAP client, retry, timeout
│ ├── models.py ← dataclasses: MovementLine, MovementResult, StockRecord…
│ ├── exceptions.py ← HanelGatewayError hierarchy
│ ├── config.py ← GatewayConfig dataclass + validation
│ └── _xml.py ← private helper: envelope construction + response parsing
├── tests/
│ ├── fixtures/ ← XML response files for tests
│ ├── test_config.py
│ ├── test_exceptions.py
│ ├── test_models.py
│ ├── test_xml.py
│ ├── test_transport.py
│ └── test_operations.py
├── docs/
│ ├── requirements/
│ └── adr/
├── CLAUDE.md
├── pyproject.toml
└── .claude/
├── agents/
└── commands/
File responsibilities
| File | Responsibility |
|---|---|
gateway.py |
Single point of contact for the caller; delegates to operations.py |
operations.py |
Builds the specific SOAP call, deserialises the response |
transport.py |
Executes HTTP POST, handles retry and timeout, logs payloads |
models.py |
Defines all public and internal dataclasses |
exceptions.py |
Defines the exception hierarchy |
config.py |
Validates and normalises incoming configuration |
_xml.py |
f-string envelope templates + ElementTree parsing functions |
Consequences
- Editable mode installation required for development:
uv sync - The package is importable only after installation, not directly from
src/ __init__.pyexposes exclusivelyHanelWarehouseGateway,GatewayConfig, the public dataclasses (MovementLine,MovementLineResult,MovementResult,StockRecord), and the exception hierarchy — nothing from_xml.pyor the internal layers.GatewayConfigis part of the public surface because callers must construct it (typically viaGatewayConfig.from_env()) to instantiate the gateway.