wireup 2.3.0__tar.gz → 2.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wireup-2.5.0/.agent/rules.md +3 -0
- wireup-2.5.0/.agent/workflows/context.md +158 -0
- wireup-2.5.0/.github/contributing.md +44 -0
- wireup-2.5.0/.github/workflows/run_all.yml +61 -0
- wireup-2.5.0/.github/workflows/run_integration_tests.yml +23 -0
- wireup-2.5.0/.gitignore +10 -0
- wireup-2.5.0/.vscode/launch.json +26 -0
- wireup-2.5.0/.vscode/settings.json +18 -0
- wireup-2.5.0/Makefile +51 -0
- wireup-2.5.0/PKG-INFO +378 -0
- wireup-2.5.0/docs/mkdocs.yml +133 -0
- wireup-2.5.0/docs/overrides/main.html +9 -0
- wireup-2.5.0/docs/pages/class/aiohttp_integration.md +1 -0
- wireup-2.5.0/docs/pages/class/click_integration.md +3 -0
- wireup-2.5.0/docs/pages/class/config_store.md +1 -0
- wireup-2.5.0/docs/pages/class/django_integration.md +1 -0
- wireup-2.5.0/docs/pages/class/fastapi_integration.md +3 -0
- wireup-2.5.0/docs/pages/class/flask_integration.md +3 -0
- wireup-2.5.0/docs/pages/class/override_manager.md +1 -0
- wireup-2.5.0/docs/pages/class/starlette_integration.md +3 -0
- wireup-2.5.0/docs/pages/class/wireup.md +3 -0
- wireup-2.5.0/docs/pages/configuration.md +142 -0
- wireup-2.5.0/docs/pages/container.md +147 -0
- wireup-2.5.0/docs/pages/factories.md +255 -0
- wireup-2.5.0/docs/pages/function_injection.md +83 -0
- wireup-2.5.0/docs/pages/getting_started.md +266 -0
- wireup-2.5.0/docs/pages/index.md +358 -0
- wireup-2.5.0/docs/pages/injectables.md +168 -0
- wireup-2.5.0/docs/pages/integrations/aiohttp/class_based_handlers.md +52 -0
- wireup-2.5.0/docs/pages/integrations/aiohttp/index.md +162 -0
- wireup-2.5.0/docs/pages/integrations/click/index.md +105 -0
- wireup-2.5.0/docs/pages/integrations/django/index.md +394 -0
- wireup-2.5.0/docs/pages/integrations/fastapi/class_based_handlers.md +133 -0
- wireup-2.5.0/docs/pages/integrations/fastapi/direct_container_access.md +112 -0
- wireup-2.5.0/docs/pages/integrations/fastapi/index.md +306 -0
- wireup-2.5.0/docs/pages/integrations/flask/index.md +109 -0
- wireup-2.5.0/docs/pages/integrations/index.md +12 -0
- wireup-2.5.0/docs/pages/integrations/starlette/index.md +159 -0
- wireup-2.5.0/docs/pages/interfaces.md +157 -0
- wireup-2.5.0/docs/pages/lifetimes_and_scopes.md +201 -0
- wireup-2.5.0/docs/pages/resources.md +92 -0
- wireup-2.5.0/docs/pages/stylesheets/extra.css +53 -0
- wireup-2.5.0/docs/pages/testing.md +118 -0
- wireup-2.5.0/docs/pages/upgrading.md +125 -0
- wireup-2.5.0/docs/pages/versioning.md +29 -0
- wireup-2.5.0/license.md +7 -0
- wireup-2.5.0/profile_tests.py +18 -0
- {wireup-2.3.0 → wireup-2.5.0}/pyproject.toml +37 -32
- wireup-2.5.0/readme.md +340 -0
- wireup-2.5.0/test/conftest.py +18 -0
- wireup-2.5.0/test/integration/aiohttp/handler.py +27 -0
- wireup-2.5.0/test/integration/aiohttp/routes.py +35 -0
- wireup-2.5.0/test/integration/aiohttp/services.py +10 -0
- wireup-2.5.0/test/integration/aiohttp/test_aiohttp_integration.py +90 -0
- wireup-2.5.0/test/integration/click/__init__.py +0 -0
- wireup-2.5.0/test/integration/click/test_click_integration.py +128 -0
- wireup-2.5.0/test/integration/django/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/apps/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/apps/app_1/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/apps/app_1/app.py +5 -0
- wireup-2.5.0/test/integration/django/apps/app_1/urls.py +9 -0
- wireup-2.5.0/test/integration/django/apps/app_1/views.py +30 -0
- wireup-2.5.0/test/integration/django/apps/app_2/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/apps/app_2/app.py +5 -0
- wireup-2.5.0/test/integration/django/apps/app_2/urls.py +9 -0
- wireup-2.5.0/test/integration/django/apps/app_2/views.py +30 -0
- wireup-2.5.0/test/integration/django/apps/drf_app/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/apps/drf_app/app.py +5 -0
- wireup-2.5.0/test/integration/django/apps/drf_app/urls.py +13 -0
- wireup-2.5.0/test/integration/django/apps/drf_app/views.py +33 -0
- wireup-2.5.0/test/integration/django/apps/ninja_app/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/apps/ninja_app/app.py +5 -0
- wireup-2.5.0/test/integration/django/apps/ninja_app/urls.py +9 -0
- wireup-2.5.0/test/integration/django/apps/ninja_app/views.py +84 -0
- wireup-2.5.0/test/integration/django/factory/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/factory/factories.py +9 -0
- wireup-2.5.0/test/integration/django/injectable/__init__.py +0 -0
- wireup-2.5.0/test/integration/django/injectable/current_request_service.py +10 -0
- wireup-2.5.0/test/integration/django/injectable/random_service.py +6 -0
- wireup-2.5.0/test/integration/django/templates/bar.html +1 -0
- wireup-2.5.0/test/integration/django/templates/foo.html +1 -0
- wireup-2.5.0/test/integration/django/test_django_integration.py +340 -0
- wireup-2.5.0/test/integration/django/view.py +78 -0
- wireup-2.5.0/test/integration/fastapi/__init__.py +0 -0
- wireup-2.5.0/test/integration/fastapi/cbr.py +21 -0
- wireup-2.5.0/test/integration/fastapi/router.py +125 -0
- wireup-2.5.0/test/integration/fastapi/services.py +34 -0
- wireup-2.5.0/test/integration/fastapi/test_fastapi_integration.py +221 -0
- wireup-2.5.0/test/integration/fastapi/wireup_route.py +38 -0
- wireup-2.5.0/test/integration/flask/__init__.py +0 -0
- wireup-2.5.0/test/integration/flask/bp.py +41 -0
- wireup-2.5.0/test/integration/flask/services/__init__.py +0 -0
- wireup-2.5.0/test/integration/flask/services/factories.py +12 -0
- wireup-2.5.0/test/integration/flask/services/is_test_service.py +10 -0
- wireup-2.5.0/test/integration/flask/test_flask_integration.py +75 -0
- wireup-2.5.0/test/integration/starlette/__init__.py +0 -0
- wireup-2.5.0/test/integration/starlette/test_starlette_integration.py +179 -0
- wireup-2.5.0/test/shared/__init__.py +0 -0
- wireup-2.5.0/test/shared/shared_services/__init__.py +0 -0
- wireup-2.5.0/test/shared/shared_services/greeter.py +13 -0
- wireup-2.5.0/test/shared/shared_services/rand.py +7 -0
- wireup-2.5.0/test/shared/shared_services/scoped.py +13 -0
- wireup-2.5.0/test/unit/__init__.py +0 -0
- wireup-2.5.0/test/unit/service_refs/__init__.py +7 -0
- wireup-2.5.0/test/unit/services/__init__.py +3 -0
- wireup-2.5.0/test/unit/services/abstract_multiple_bases.py +48 -0
- wireup-2.5.0/test/unit/services/inheritance_test/__init__.py +7 -0
- wireup-2.5.0/test/unit/services/inheritance_test/base.py +12 -0
- wireup-2.5.0/test/unit/services/no_annotations/__init__.py +2 -0
- wireup-2.5.0/test/unit/services/no_annotations/random/__init__.py +0 -0
- wireup-2.5.0/test/unit/services/no_annotations/random/random_service.py +3 -0
- wireup-2.5.0/test/unit/services/no_annotations/random/truly_random_service.py +9 -0
- wireup-2.5.0/test/unit/services/with_annotations/__init__.py +0 -0
- wireup-2.5.0/test/unit/services/with_annotations/env/__init__.py +8 -0
- wireup-2.5.0/test/unit/services/with_annotations/services.py +59 -0
- wireup-2.5.0/test/unit/test_as_type.py +250 -0
- wireup-2.5.0/test/unit/test_concurrency.py +85 -0
- wireup-2.5.0/test/unit/test_container_core.py +388 -0
- wireup-2.5.0/test/unit/test_container_creation.py +213 -0
- wireup-2.5.0/test/unit/test_container_generator_factory.py +226 -0
- wireup-2.5.0/test/unit/test_container_override.py +94 -0
- wireup-2.5.0/test/unit/test_container_scope.py +102 -0
- wireup-2.5.0/test/unit/test_eval_type.py +62 -0
- wireup-2.5.0/test/unit/test_exit_stack.py +48 -0
- wireup-2.5.0/test/unit/test_inject_from_container.py +267 -0
- wireup-2.5.0/test/unit/test_inject_from_container_optional_types.py +82 -0
- wireup-2.5.0/test/unit/test_inject_from_container_stringified_types.py +42 -0
- wireup-2.5.0/test/unit/test_module_loading.py +28 -0
- wireup-2.5.0/test/unit/test_optional_type.py +61 -0
- wireup-2.5.0/test/unit/test_parameter.py +52 -0
- wireup-2.5.0/test/unit/test_service_deprecation.py +27 -0
- wireup-2.5.0/test/unit/test_service_registry.py +194 -0
- wireup-2.5.0/test/unit/test_signature_hiding.py +71 -0
- wireup-2.5.0/test/unit/test_type_analysis.py +111 -0
- wireup-2.5.0/test/unit/test_util.py +114 -0
- wireup-2.5.0/test/unit/util.py +10 -0
- wireup-2.5.0/tox.ini +64 -0
- wireup-2.5.0/uv.lock +3082 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/__init__.py +5 -5
- wireup-2.5.0/wireup/_annotations.py +220 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/_decorators.py +64 -43
- {wireup-2.3.0 → wireup-2.5.0}/wireup/_discovery.py +8 -8
- wireup-2.5.0/wireup/codegen.py +31 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/errors.py +18 -15
- wireup-2.5.0/wireup/integration/__init__.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/aiohttp.py +7 -8
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/django/apps.py +29 -12
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/fastapi.py +3 -4
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/starlette.py +4 -4
- wireup-2.5.0/wireup/ioc/__init__.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/_exit_stack.py +2 -0
- wireup-2.5.0/wireup/ioc/configuration.py +47 -0
- wireup-2.5.0/wireup/ioc/container/__init__.py +198 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/container/async_container.py +15 -3
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/container/base_container.py +26 -9
- wireup-2.5.0/wireup/ioc/container/lock_registry.py +20 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/container/sync_container.py +12 -0
- wireup-2.5.0/wireup/ioc/factory_compiler.py +245 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/override_manager.py +44 -13
- wireup-2.3.0/wireup/ioc/service_registry.py → wireup-2.5.0/wireup/ioc/registry.py +81 -71
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/types.py +27 -19
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/util.py +2 -5
- wireup-2.5.0/wireup/py.typed +0 -0
- wireup-2.5.0/wireup/util.py +18 -0
- wireup-2.5.0/z_test_bench.py +103 -0
- wireup-2.5.0/z_test_prep/__init__.py +0 -0
- wireup-2.5.0/z_test_prep/js_stack.py +67 -0
- wireup-2.5.0/z_test_prep/z_test_cit_code1.py +44 -0
- wireup-2.5.0/z_test_prep/z_test_cit_code2.py +42 -0
- wireup-2.5.0/z_test_prep/z_test_cit_palindrome.py +22 -0
- wireup-2.5.0/z_test_prep/z_test_citadel_oa1.py +51 -0
- wireup-2.5.0/z_test_prep/z_test_js_code1.py +72 -0
- wireup-2.5.0/z_test_prep/z_test_js_code2.py +0 -0
- wireup-2.5.0/z_test_repro_fastapi_race.py +123 -0
- wireup-2.5.0/z_test_repro_wireup_race.py +120 -0
- wireup-2.5.0/z_test_services/__init__.py +0 -0
- wireup-2.5.0/z_test_services/bar.py +7 -0
- wireup-2.5.0/z_test_services/foo.py +8 -0
- wireup-2.3.0/PKG-INFO +0 -284
- wireup-2.3.0/readme.md +0 -243
- wireup-2.3.0/wireup/_annotations.py +0 -133
- wireup-2.3.0/wireup/ioc/container/__init__.py +0 -125
- wireup-2.3.0/wireup/ioc/factory_compiler.py +0 -163
- wireup-2.3.0/wireup/ioc/parameter.py +0 -60
- {wireup-2.3.0/wireup/integration → wireup-2.5.0/test}/__init__.py +0 -0
- {wireup-2.3.0/wireup/ioc → wireup-2.5.0/test/integration}/__init__.py +0 -0
- /wireup-2.3.0/wireup/py.typed → /wireup-2.5.0/test/integration/aiohttp/__init__.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/click.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/django/__init__.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/django/decorators.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/integration/flask.py +0 -0
- {wireup-2.3.0 → wireup-2.5.0}/wireup/ioc/type_analysis.py +0 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Agent Rules
|
|
2
|
+
|
|
3
|
+
1. **Stdout/Stderr Redirection**: The `run_command` tool has a bug where it cannot reliably capture stdout/stderr directly. YOU MUST ALWAYS redirect output to a file (e.g., `cmd > output.txt 2>&1`) and then read that file using `view_file` or `read_resource` to inspect the output. Never rely on the `output` field of `run_command` or `command_status`.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Wireup - Dependency Injection Framework for Python
|
|
2
|
+
|
|
3
|
+
Wireup is a type-safe dependency injection framework for Python 3.8+ with async support and framework integrations.
|
|
4
|
+
|
|
5
|
+
## Core Architecture
|
|
6
|
+
|
|
7
|
+
Wireup follows a container-based DI pattern with three main components:
|
|
8
|
+
|
|
9
|
+
- **Container**: Central registry that resolves dependencies (`create_sync_container`/`create_async_container`)
|
|
10
|
+
- **Injectables**: Classes/functions marked with `@injectable` decorator
|
|
11
|
+
- **Configuration**: Configuration values injected via `config`
|
|
12
|
+
|
|
13
|
+
Key modules:
|
|
14
|
+
- `wireup/ioc/` - Core container and service registry implementation
|
|
15
|
+
- `wireup/integration/` - Framework integrations (FastAPI, Django, Flask, etc.)
|
|
16
|
+
- `wireup/_annotations.py` - Core decorators (`@injectable`, `@abstract`, `Inject`, `Injected`)
|
|
17
|
+
|
|
18
|
+
## Development Workflows
|
|
19
|
+
|
|
20
|
+
### Testing
|
|
21
|
+
- Use `make test` for unit tests (runs `pytest test/unit`)
|
|
22
|
+
- Tests use parameterized containers (both sync/async) via `conftest.py`
|
|
23
|
+
- Test services are in `test/unit/services/` with clear module structure
|
|
24
|
+
- Override services in tests using `container.override.service(target=Original, new=mock)`
|
|
25
|
+
- Integration tests are in `test/integration/` for framework-specific testing
|
|
26
|
+
|
|
27
|
+
### Linting & Type Checking
|
|
28
|
+
- `make lint` - Runs formatting, ruff, and mypy checks
|
|
29
|
+
- `make format` - Auto-format code with ruff
|
|
30
|
+
- Strict mypy compliance required (`mypy wireup --strict`)
|
|
31
|
+
- Ruff configured for Python 3.8+ with comprehensive rule set
|
|
32
|
+
- Note: `tool.mypy` excludes `wireup.integration` directory
|
|
33
|
+
|
|
34
|
+
### Building & Documentation
|
|
35
|
+
- Poetry-based project (`poetry install`, `poetry build`)
|
|
36
|
+
- Documentation via MkDocs Material (`make docs-deploy version=X.Y.Z`)
|
|
37
|
+
- Use `z_test_*.py` files for experimentation and examples
|
|
38
|
+
- Profile performance with `make profile ./profile_tests <num_runs>`
|
|
39
|
+
|
|
40
|
+
## Key Patterns
|
|
41
|
+
|
|
42
|
+
### Injectable Registration
|
|
43
|
+
```python
|
|
44
|
+
@injectable # Singleton by default
|
|
45
|
+
class Database: ...
|
|
46
|
+
|
|
47
|
+
@injectable(lifetime="scoped") # Per-request/scope
|
|
48
|
+
class RequestContext: ...
|
|
49
|
+
|
|
50
|
+
@injectable(lifetime="transient") # Always new instance
|
|
51
|
+
class OrderProcessor: ...
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Interface-Implementation Binding
|
|
55
|
+
```python
|
|
56
|
+
@abstract
|
|
57
|
+
class Cache: ...
|
|
58
|
+
|
|
59
|
+
@injectable(qualifier="redis")
|
|
60
|
+
class RedisCache(Cache): ...
|
|
61
|
+
|
|
62
|
+
# Inject specific implementation
|
|
63
|
+
def handler(cache: Annotated[Cache, Inject(qualifier="redis")]): ...
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Factory Functions with Cleanup
|
|
67
|
+
```python
|
|
68
|
+
@injectable
|
|
69
|
+
def database_factory() -> Iterator[Database]:
|
|
70
|
+
db = Database()
|
|
71
|
+
try:
|
|
72
|
+
yield db
|
|
73
|
+
finally:
|
|
74
|
+
db.close()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Function Injection
|
|
78
|
+
```python
|
|
79
|
+
@inject_from_container(container)
|
|
80
|
+
def process_data(service: Injected[UserService]):
|
|
81
|
+
# UserService automatically injected
|
|
82
|
+
pass
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Configuration Injection
|
|
86
|
+
```python
|
|
87
|
+
@injectable
|
|
88
|
+
class Database:
|
|
89
|
+
def __init__(self, db_url: Annotated[str, Inject(config="db_url")]) -> None:
|
|
90
|
+
self.db_url = db_url
|
|
91
|
+
|
|
92
|
+
# Templated string configuration
|
|
93
|
+
@injectable
|
|
94
|
+
class Logger:
|
|
95
|
+
def __init__(self, prefix: Annotated[str, Inject(expr="app-${env_name}")]) -> None:
|
|
96
|
+
self.prefix = prefix
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Framework Integration Notes
|
|
100
|
+
|
|
101
|
+
- Integrations are in `wireup/integration/` with separate files per framework
|
|
102
|
+
- Setup pattern: `wireup.integration.{framework}.setup(container, app)`
|
|
103
|
+
- FastAPI integration auto-wraps `Inject()` with `Depends()` for compatibility
|
|
104
|
+
- All integrations validate dependencies at startup, not runtime
|
|
105
|
+
|
|
106
|
+
## Error Handling & Validation
|
|
107
|
+
|
|
108
|
+
Wireup validates dependencies early to catch configuration errors:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# Container creation fails with clear error messages
|
|
112
|
+
@injectable
|
|
113
|
+
class Foo:
|
|
114
|
+
def __init__(self, unknown: NotManagedByWireup) -> None:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
container = wireup.create_sync_container(service_modules=[Foo])
|
|
118
|
+
# ❌ Parameter 'unknown' of 'Foo' depends on an unknown injectable 'NotManagedByWireup'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Common error types:
|
|
122
|
+
- `UnknownServiceRequestedError` - Missing injectable registration
|
|
123
|
+
- `DuplicateServiceRegistrationError` - Same injectable registered twice
|
|
124
|
+
- `DuplicateQualifierForInterfaceError` - Qualifier conflicts
|
|
125
|
+
|
|
126
|
+
## Testing Conventions
|
|
127
|
+
|
|
128
|
+
- Use `Container = Union[SyncContainer, AsyncContainer]` type hint for parameterized tests
|
|
129
|
+
- Service modules for tests use clear hierarchical imports
|
|
130
|
+
- Test both sync and async containers with same test logic via fixtures
|
|
131
|
+
- Mock external dependencies using container overrides, not monkey patching
|
|
132
|
+
|
|
133
|
+
## Container Usage Patterns
|
|
134
|
+
|
|
135
|
+
### Service Discovery
|
|
136
|
+
```python
|
|
137
|
+
# Auto-discover injectables from modules
|
|
138
|
+
container = wireup.create_sync_container(service_modules=[services])
|
|
139
|
+
|
|
140
|
+
# Explicit injectable registration
|
|
141
|
+
container = wireup.create_sync_container(service_modules=[Database, UserService])
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Scoped Containers
|
|
145
|
+
Use scoped containers for request-scoped injectables:
|
|
146
|
+
```python
|
|
147
|
+
with container.request_scope() as scoped:
|
|
148
|
+
# All scoped services share same instance within this block
|
|
149
|
+
service = scoped.get(RequestScopedService)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## File Organization
|
|
153
|
+
|
|
154
|
+
- `z_test_*.py` - Experimental/example files (not actual tests)
|
|
155
|
+
- `test/unit/` - Unit tests with services in subfolders
|
|
156
|
+
- `test/integration/` - Integration tests
|
|
157
|
+
- `wireup/ioc/` - Core DI implementation
|
|
158
|
+
- `docs/pages/` - MkDocs documentation source
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/maldoinc/wireup.git
|
|
7
|
+
cd wireup
|
|
8
|
+
|
|
9
|
+
python -m venv .venv
|
|
10
|
+
source .venv/bin/activate
|
|
11
|
+
make install
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Development Workflow
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
make lint # Run ruff & mypy checks
|
|
18
|
+
make test # Run unit tests
|
|
19
|
+
make format # Format code
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Making Changes
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git checkout -b feature/your-feature-name
|
|
26
|
+
# work on the change
|
|
27
|
+
make lint test
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Project Structure
|
|
32
|
+
|
|
33
|
+
- `wireup/ioc/` - Dependency injection implementation
|
|
34
|
+
- `wireup/integration/` - Framework integrations (FastAPI, Django, etc.)
|
|
35
|
+
- `test/unit/` - Unit tests
|
|
36
|
+
- `test/integration/` - Integration tests
|
|
37
|
+
- `docs/` - Docs
|
|
38
|
+
|
|
39
|
+
## Guidelines
|
|
40
|
+
|
|
41
|
+
- **Python Support**: Target Python 3.8+ compatibility
|
|
42
|
+
- **Dependencies**: No new dependencies without approval
|
|
43
|
+
- **Documentation**: Update docs for user-facing changes
|
|
44
|
+
- **Testing**: Maintain test coverage for new code
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Run tests
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: ["master"]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: ["master"]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v3
|
|
13
|
+
- name: Set up Python
|
|
14
|
+
uses: actions/setup-python@v4
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.8"
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
- name: Install dependencies
|
|
20
|
+
run: make install
|
|
21
|
+
- name: Lint
|
|
22
|
+
run: make check-ruff
|
|
23
|
+
- name: Check formatting
|
|
24
|
+
run: make check-fmt
|
|
25
|
+
- name: Check typing
|
|
26
|
+
run: make check-mypy
|
|
27
|
+
|
|
28
|
+
docs:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v3
|
|
32
|
+
- name: Set up Python
|
|
33
|
+
uses: actions/setup-python@v4
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.14"
|
|
36
|
+
- name: Install uv
|
|
37
|
+
uses: astral-sh/setup-uv@v5
|
|
38
|
+
- name: Install dependencies
|
|
39
|
+
run: make install
|
|
40
|
+
- name: Check documentation
|
|
41
|
+
run: make check-docs
|
|
42
|
+
- name: Build documentation
|
|
43
|
+
run: make build-docs
|
|
44
|
+
|
|
45
|
+
test:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
strategy:
|
|
48
|
+
matrix:
|
|
49
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v3
|
|
52
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
53
|
+
uses: actions/setup-python@v4
|
|
54
|
+
with:
|
|
55
|
+
python-version: ${{ matrix.python-version }}
|
|
56
|
+
- name: Install uv
|
|
57
|
+
uses: astral-sh/setup-uv@v5
|
|
58
|
+
- name: Install dependencies
|
|
59
|
+
run: make install
|
|
60
|
+
- name: Run tests
|
|
61
|
+
run: make test
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Integration tests
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: ["master"]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: ["master"]
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
name: Run Tox
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout code
|
|
13
|
+
uses: actions/checkout@v3
|
|
14
|
+
- name: Set up Python
|
|
15
|
+
uses: actions/setup-python@v4
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.13"
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v5
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: make install
|
|
22
|
+
- name: Run tox
|
|
23
|
+
run: uv run tox
|
wireup-2.5.0/.gitignore
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"name": "Python Debugger: Module",
|
|
9
|
+
"type": "debugpy",
|
|
10
|
+
"request": "launch",
|
|
11
|
+
"module": "wireup_benchmarks.app"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Python Debugger: Django",
|
|
15
|
+
"type": "debugpy",
|
|
16
|
+
"request": "launch",
|
|
17
|
+
"program": "${workspaceFolder}/test/integration/djangoproj/manage.py",
|
|
18
|
+
"args": [
|
|
19
|
+
"runserver",
|
|
20
|
+
"8080"
|
|
21
|
+
],
|
|
22
|
+
"django": true,
|
|
23
|
+
"justMyCode": false
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"python.testing.pytestArgs": [
|
|
3
|
+
"-s",
|
|
4
|
+
"test",
|
|
5
|
+
],
|
|
6
|
+
"python.testing.unittestEnabled": false,
|
|
7
|
+
"python.testing.pytestEnabled": true,
|
|
8
|
+
"python.analysis.autoImportCompletions": true,
|
|
9
|
+
"debugpy.debugJustMyCode": false,
|
|
10
|
+
"python-envs.defaultEnvManager": "ms-python.python:venv",
|
|
11
|
+
"python-envs.pythonProjects": [],
|
|
12
|
+
"cursorpyright.analysis.autoImportCompletions": true,
|
|
13
|
+
"cSpell.words": [
|
|
14
|
+
"asyncio",
|
|
15
|
+
"Codegen",
|
|
16
|
+
"pyrefly"
|
|
17
|
+
],
|
|
18
|
+
}
|
wireup-2.5.0/Makefile
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
.PHONY: install lint check-fmt check-ruff check-mypy test profile fix format docs-deploy publish
|
|
2
|
+
|
|
3
|
+
ifdef GITHUB_ACTIONS
|
|
4
|
+
RUFF_ARGS := --output-format github
|
|
5
|
+
endif
|
|
6
|
+
|
|
7
|
+
install:
|
|
8
|
+
pip install uv
|
|
9
|
+
uv sync --group dev
|
|
10
|
+
|
|
11
|
+
lint: check-fmt check-ruff check-mypy check-docs
|
|
12
|
+
|
|
13
|
+
check-fmt:
|
|
14
|
+
uv run ruff format . --check
|
|
15
|
+
|
|
16
|
+
check-ruff:
|
|
17
|
+
uv run ruff check wireup test $(RUFF_ARGS)
|
|
18
|
+
|
|
19
|
+
check-mypy:
|
|
20
|
+
uv run mypy wireup --strict
|
|
21
|
+
|
|
22
|
+
check-docs:
|
|
23
|
+
find docs -name "*.md" -not -path "docs/pages/class/*" | xargs uv run --python 3.14 mdformat --wrap 120 --check
|
|
24
|
+
|
|
25
|
+
test:
|
|
26
|
+
uv run pytest test/unit
|
|
27
|
+
|
|
28
|
+
profile ./profile_tests $(num_runs):
|
|
29
|
+
uv run python ./profile_tests.py $(num_runs)
|
|
30
|
+
|
|
31
|
+
format: format-docs
|
|
32
|
+
uv run ruff format .
|
|
33
|
+
|
|
34
|
+
fix:
|
|
35
|
+
uv run ruff wireup --fix
|
|
36
|
+
|
|
37
|
+
format-docs:
|
|
38
|
+
find docs -name "*.md" -not -path "docs/pages/class/*" | xargs uv run --python 3.14 mdformat --wrap 120
|
|
39
|
+
find docs -name "*.md" -not -path "docs/pages/class/*" | xargs uv run --python 3.14 blacken-docs -l 80 || true
|
|
40
|
+
|
|
41
|
+
build-docs:
|
|
42
|
+
uv run --python 3.14 mkdocs build --strict -f docs/mkdocs.yml
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# make docs-deploy version=...
|
|
46
|
+
docs-deploy $(version):
|
|
47
|
+
cd docs && uv run mike deploy --push --update-aliases $(version) latest
|
|
48
|
+
|
|
49
|
+
publish:
|
|
50
|
+
uv build
|
|
51
|
+
uv publish
|