Skip to content

Commit a01b01f

Browse files
committed
Docs, examples
1 parent ca4bcbf commit a01b01f

26 files changed

Lines changed: 4785 additions & 54 deletions

.github/CONTRIBUTING.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,20 @@ SPDX-FileCopyrightText: 2025 Alexandre Gomes Gaigalas <alganet@gmail.com>
33
44
SPDX-License-Identifier: ISC
55
-->
6-
# Contributing
6+
# Contributing to apywire
77

8-
## Development Setup
8+
Thanks for your interest in contributing!
99

10-
1. Clone the repository
11-
2. Install dependencies: `pip install -e .[dev]`
12-
3. Run tests: `make test`
13-
14-
## Commit Messages
10+
For the complete development guide, please see **[docs/development.md](../docs/development.md)**.
1511

16-
Use meaningful titles and a brief body describing your changes.
12+
## Quick Start
1713

18-
Commit titles must not exceed 72 characters.
19-
Commit body lines must not exceed 72 characters.
14+
1. Clone the repository
15+
2. Run `make .venv && source .venv/bin/activate && make pip`
16+
3. Run `make all` to verify everything works
2017

21-
## Code Quality
18+
## Before Submitting a Pull Request
2219

23-
- Format: `make format`
24-
- Lint: `make lint`
25-
- Test: `make test`
26-
- All: `make all`
20+
- **Development**: See [docs/development.md](../docs/development.md) for setup, testing, and workflow
21+
- **Code Standards**: All code must pass `make lint` and maintain test coverage requirements
22+
- **Commit Messages**: Keep titles ≤ 72 characters with meaningful descriptions

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ Brief description of changes.
1010
## Type of Change
1111

1212
- [ ] Bug fix
13+
- [ ] Refactoring
1314
- [ ] New feature
1415
- [ ] Breaking change
1516
- [ ] Documentation update
1617

1718
## Checklist
1819

19-
- [ ] Tests pass
20-
- [ ] Code formatted
21-
- [ ] Documentation updated
20+
- [ ] Descriptive and concise commit message and PR details
21+
- [ ] Docstrings updated
22+
- [ ] Documentation updated

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
# Project Specific
66
apywire/**.c
7+
site/
78

89
# General
910
.venv/

AGENTS.md

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,58 @@ SPDX-License-Identifier: ISC
55
-->
66
# AI Coding Guidelines for apywire
77

8-
## Overview
8+
For detailed development workflow and standards, see **[docs/development.md](docs/development.md)**.
9+
10+
## Project Context
11+
912
apywire is a Python 3.12+ library for lazy object wiring and dependency injection. It uses spec-based configuration to instantiate objects on-demand with support for async access, thread safety, and code generation via Cython compilation.
1013

11-
## Core API
14+
**Core API:**
1215
- **`Wiring(spec, thread_safe=False)`**: Main container for lazy instantiation from a spec dict
1316
- **`wired.name()`**: Returns callable `Accessor` that instantiates object on invocation
1417
- **`await wired.aio.name()`**: Async access via `AioAccessor` using `run_in_executor`
15-
- **`wired.compile(aio=False, thread_safe=False)`**: Generates equivalent Python code as a `Compiled` class
18+
- **`compiler = WiringCompiler(spec)`**: For compiling into python code instead of runtime
19+
- **`code = compiler.compile(aio=True, thread_safe=True)`**: Generate python code for the spec
1620
- **Spec Format**: `{"module.Class name": {"param": "value", "ref": "{otherName}"}}`
1721

18-
## Architecture
19-
- **Lazy Loading**: Objects instantiated via `__getattr__` only when accessed, cached after first use
20-
- **Placeholders**: `{name}` in spec values resolve to other wired objects at instantiation
21-
- **Thread Safety**: Optional `thread_safe=True` uses optimistic per-attribute locking with global fallback via `CompiledThreadSafeMixin`
22-
- **Cython Build**: `setup.py` uses Cython to compile `wiring.py``wiring.c` with SPDX headers
23-
- **Equivalence**: Compiled output behaves identically to runtime `Wiring` (lazy, async, thread-safe)
24-
25-
## Development Workflow
26-
- **Setup**: `make .venv` and `source .venv/bin/activate`, then `make pip`
27-
- **Check**: `make all` (format, lint, coverage, build)
28-
- **Test**: `pytest -xvs` (verbose), `make coverage` (95% required)
29-
- **Build**: `make build` (Cython compile), `make dist` (package)
30-
- **Clean**: `make clean` (remove artifacts/caches)
31-
32-
## Code Standards
33-
- **Typing**: Strict mypy with `disallow_any_*=true`, use `object` not `Any`
34-
- **Style**: 79-char lines, `black` + `isort` formatting
35-
- **Licensing**: SPDX headers required on all files, validate with `make reuse`
36-
- **Tests**: Cover sync, async (`test_compile_aio.py`), threading (`test_threading.py`), edge cases
37-
38-
## Key Components
39-
- `apywire/wiring.py`: `Wiring`, `Accessor`, `AioAccessor`, `compile()` method
40-
- `apywire/thread_safety.py`: `CompiledThreadSafeMixin` with optimistic/global locking
41-
- `apywire/exceptions.py`: `WiringError`, `CircularWiringError`, `UnknownPlaceholderError`, `LockUnavailableError`
42-
- `setup.py`: Cython build config with SPDX header injection
43-
44-
## Examples
22+
## Critical Architectural Patterns
23+
24+
**Lazy Loading via `__getattr__`:**
25+
Objects are instantiated only when accessed, using `__getattr__` to intercept attribute access and return `Accessor` callables that handle instantiation and caching.
26+
27+
**Placeholder Resolution:**
28+
Strings like `{name}` in spec values are converted to `_WiredRef` markers during parsing, then resolved to actual objects at instantiation time. See `constants.py` for delimiter patterns.
29+
30+
**Thread Safety Model:**
31+
Uses optimistic per-attribute locking (`dict[str, threading.Lock]`) with a global fallback lock. Thread-local state tracks the resolving stack for circular dependency detection. See `threads.py` for `ThreadSafeMixin` implementation.
32+
33+
**Compilation Equivalence:**
34+
Generated code must behave identically to runtime `Wiring`. The compiler generates accessor methods that replicate lazy loading, caching, and optional async/thread-safe behavior.
35+
36+
## AI-Specific Development Notes
37+
38+
**Strict Mypy Configuration:**
39+
The project uses extremely strict mypy settings including `disallow_any_expr=true`. Never use `Any`—use `object` instead. All functions need complete type annotations. See [Code Standards](docs/development.md#type-annotations) for details.
40+
41+
**Module Structure:**
42+
- `wiring.py`: Base class `WiringBase`, type system, placeholder parsing
43+
- `runtime.py`: Runtime `Wiring` class with `Accessor`/`AioAccessor`
44+
- `compiler.py`: Code generation via `WiringCompiler`
45+
- `threads.py`: Thread safety mixins and utilities
46+
- `exceptions.py`: Custom exception classes
47+
- `constants.py`: Shared constants (placeholder patterns, delimiters)
48+
49+
**Testing Requirements:**
50+
All changes must maintain 100% branch coverage. Test both runtime and compiled behavior, plus async and thread-safe variants where applicable. Use descriptive test names: `test_<feature>_<scenario>_<expected_behavior>()`.
51+
52+
**Common Gotchas:**
53+
- SPDX headers required on all files (run `make format` to auto-add)
54+
- 79-character line limit enforced by `black`
55+
- Compiled output is verified against runtime behavior in tests
56+
- Thread-safe tests use actual threading to verify lock behavior
57+
58+
## Quick Reference
59+
4560
```python
4661
# Basic lazy access
4762
wired = Wiring({"datetime.datetime now": {"year": 2025}})
@@ -54,5 +69,13 @@ obj = await wired.aio.now()
5469
wired = Wiring(spec, thread_safe=True)
5570

5671
# Code generation
57-
code = wired.compile(aio=True, thread_safe=True)
72+
compiler = WiringCompiler(spec)
73+
code = compiler.compile(aio=True, thread_safe=True)
5874
```
75+
76+
**Make Commands:**
77+
- `make all` - Complete check (format, lint, coverage, build)
78+
- `make test` - Run pytest suite
79+
- `make coverage` - Check coverage requirements
80+
- `make lint` - Run reuse, flake8, mypy
81+
- `make format` - Run black, isort, add SPDX headers

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# SPDX-License-Identifier: ISC
44

5-
.PHONY: all format lint test coverage clean publish pip reuse .venv
5+
.PHONY: all format lint test coverage clean publish pip reuse .venv docs-serve docs-build
66

77
all: format lint coverage build
88

@@ -50,3 +50,9 @@ dist:
5050

5151
publish:
5252
python -m twine upload dist/*
53+
54+
docs-serve:
55+
python -m mkdocs serve
56+
57+
docs-build:
58+
python -m mkdocs build

README.md

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,61 @@ SPDX-FileCopyrightText: 2025 Alexandre Gomes Gaigalas <alganet@gmail.com>
33
44
SPDX-License-Identifier: ISC
55
-->
6+
67
# apywire
78

8-
A Python package to wire up objects.
9+
[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
10+
[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
11+
12+
Lazy object wiring and dependency injection for Python 3.12+
13+
14+
## Features
15+
16+
- 🚀 Lazy Loading
17+
- ⚡ Async Support
18+
- 🔒 Thread Safety
19+
- 📦 Code Generation
20+
- 📄 Naturally Configurable
21+
- 🎯 Zero Dependencies
22+
23+
## Installation
24+
25+
```bash
26+
pip install apywire
27+
```
28+
29+
## Quick Example
930

10-
---
31+
```python
32+
from apywire import Wiring
1133

12-
Under development and unstable, API might change at any moment.
34+
spec = {
35+
"datetime.datetime now": {"year": 2025, "month": 1, "day": 1},
36+
"MyService service": {"start_time": "{now}"}, # Dependency injection
37+
}
38+
39+
wired = Wiring(spec)
40+
service = wired.service() # Lazy instantiation + caching
41+
```
42+
43+
## Documentation
44+
45+
📚 **[Full Documentation](docs/index.md)**[Getting Started](docs/getting-started.md)[API Reference](docs/api-reference.md)[Examples](docs/examples.md)
46+
47+
Build docs locally:
48+
```bash
49+
make docs-serve # http://127.0.0.1:8000
50+
```
1351

1452
## Development
1553

16-
See [AGENTS.md](AGENTS.md) for coding guidelines and architecture overview.
54+
```bash
55+
make .venv && source .venv/bin/activate # Setup
56+
make all # Format, lint, test, build
57+
```
58+
59+
See [AGENTS.md](AGENTS.md) for guidelines.
60+
61+
## License
62+
63+
ISC License - see [LICENSES/ISC.txt](LICENSES/ISC.txt)

0 commit comments

Comments
 (0)