You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+54-31Lines changed: 54 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,43 +5,58 @@ SPDX-License-Identifier: ISC
5
5
-->
6
6
# AI Coding Guidelines for apywire
7
7
8
-
## Overview
8
+
For detailed development workflow and standards, see **[docs/development.md](docs/development.md)**.
9
+
10
+
## Project Context
11
+
9
12
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.
10
13
11
-
## Core API
14
+
**Core API:**
12
15
-**`Wiring(spec, thread_safe=False)`**: Main container for lazy instantiation from a spec dict
13
16
-**`wired.name()`**: Returns callable `Accessor` that instantiates object on invocation
14
17
-**`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
-`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`
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
0 commit comments