Skip to content

Commit a581862

Browse files
committed
feat: version bump to 0.2.0-M11, CI fix for missing mongo test ignores
1 parent 5e2831f commit a581862

14 files changed

Lines changed: 54 additions & 23 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ jobs:
6565
--ignore=tests/data/test_mongo_filter.py
6666
--ignore=tests/data/test_mongo_post_processor.py
6767
--ignore=tests/data/test_mongo_query_decorator.py
68+
--ignore=tests/data/test_mongo_projection_query.py
69+
--ignore=tests/data/test_mongo_query_compiler.py
6870
--ignore=tests/data/test_mongo_repository.py
6971
--ignore=tests/data/test_mongo_specification.py
7072
--ignore=tests/data/test_mongo_wiring.py

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

77
---
88

9+
## v0.2.0-M11 (2026-03-01)
10+
11+
### Fixed
12+
- **Thread-safe singleton initialization**: DI container now uses RLock with double-check pattern to prevent duplicate singleton creation under concurrent access
13+
- **Condition list inheritance**: `@conditional_on_*` decorators now copy conditions via `cls.__dict__` instead of `getattr()` to prevent cross-class mutation through MRO
14+
- **`@transactional` rollback_for semantics**: Replaced `session.begin()` context manager with explicit `begin()`/`commit()`/`rollback()` to support selective rollback matching Spring's `@Transactional`
15+
- **SecurityException status code**: Base `SecurityException` now maps to 403 (Forbidden) instead of 401; `UnauthorizedException` subclass retains 401
16+
- **`@secure` decorator**: Authorization failures now raise `ForbiddenException` (403) instead of base `SecurityException`
17+
- **Security context bridge**: `SecurityMiddleware` now sets `security_context` on both `request.state` and `RequestContext` for `@pre_authorize`/`@post_authorize`
18+
- **Lazy controller race condition**: Added `asyncio.Lock` with double-check to prevent duplicate bean resolution on concurrent first requests
19+
- **Parameter coercion errors**: `_coerce()` now raises `InvalidRequestException` (HTTP 400) instead of unhandled `ValueError`/`TypeError`
20+
- **Bulkhead TOCTOU**: Replaced `semaphore.locked()` check with `_active >= _max_concurrent` for consistent capacity tracking
21+
- **`asyncio.get_event_loop()`**: Replaced 3 occurrences with `get_running_loop()` to avoid deprecation warnings and ensure correct loop in nested contexts
22+
23+
### Changed
24+
- **Resilience sync/async support**: All 4 resilience decorators (`@fallback`, `@rate_limiter`, `@time_limiter`, `@bulkhead`) now detect sync functions via `inspect.iscoroutinefunction` and wrap accordingly
25+
- **Event bus optimization**: Listeners are pre-sorted at subscribe time instead of on every `publish()` call
26+
- **Repository dynamic PK**: `find_all_by_ids()` and `delete_all()` use `_pk_column` property (via `sa_inspect`) instead of hardcoded `.id`
27+
- **Nested repository patching**: `_patch_repositories()` now patches repositories one level deep into nested services
28+
- **Kahn's algorithm**: `_sort_bean_methods` uses `collections.deque` instead of `list.pop(0)` for O(1) popleft
29+
- **Auto-config logging**: `ImportError` during entry point discovery now logged at DEBUG level instead of silently swallowed
30+
- **Exception handling**: `_inject_autowired_fields` catches `NameError` specifically (not bare `Exception`) and logs a warning
31+
- **Filter chain**: Fast path bypasses response buffering when no filters are registered; 100MB body size guard prevents OOM
32+
33+
---
34+
935
## v0.2.0-M10 (2026-02-28)
1036

1137
### Changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<a href="https://github.com/fireflyframework"><img src="https://img.shields.io/badge/Firefly_Framework-official-ff6600?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0xMiAyQzYuNDggMiAyIDYuNDggMiAxMnM0LjQ4IDEwIDEwIDEwIDEwLTQuNDggMTAtMTBTMTcuNTIgMiAxMiAyeiIvPjwvc3ZnPg==" alt="Firefly Framework"></a>
1212
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white" alt="Python 3.12+"></a>
1313
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-green" alt="License: Apache 2.0"></a>
14-
<a href="#"><img src="https://img.shields.io/badge/version-0.2.0--M9-yellow" alt="Version: 0.2.0-M10"></a>
14+
<a href="#"><img src="https://img.shields.io/badge/version-0.2.0--M11-yellow" alt="Version: 0.2.0-M11"></a>
1515
<a href="#"><img src="https://img.shields.io/badge/type--checked-mypy%20strict-blue?logo=python&logoColor=white" alt="Type Checked: mypy strict"></a>
1616
<a href="#"><img src="https://img.shields.io/badge/code%20style-ruff-purple?logo=ruff&logoColor=white" alt="Code Style: Ruff"></a>
1717
<a href="#"><img src="https://img.shields.io/badge/async-first-brightgreen" alt="Async First"></a>
@@ -304,13 +304,13 @@ my-addon = "my_package.auto_configuration:MyAutoConfiguration"
304304

305305
```bash
306306
# Install the latest release (uv)
307-
uv add "pyfly @ https://github.com/fireflyframework/pyfly/releases/latest/download/pyfly-0.2.0a10-py3-none-any.whl"
307+
uv add "pyfly @ https://github.com/fireflyframework/pyfly/releases/latest/download/pyfly-0.2.0a11-py3-none-any.whl"
308308
309309
# Install with specific extras
310-
uv add "pyfly[web,data-relational,cache] @ https://github.com/fireflyframework/pyfly/releases/latest/download/pyfly-0.2.0a10-py3-none-any.whl"
310+
uv add "pyfly[web,data-relational,cache] @ https://github.com/fireflyframework/pyfly/releases/latest/download/pyfly-0.2.0a11-py3-none-any.whl"
311311
312312
# Or with pip
313-
pip install "pyfly @ https://github.com/fireflyframework/pyfly/releases/latest/download/pyfly-0.2.0a10-py3-none-any.whl"
313+
pip install "pyfly @ https://github.com/fireflyframework/pyfly/releases/latest/download/pyfly-0.2.0a11-py3-none-any.whl"
314314
```
315315

316316
### One-Line Install (CLI + Framework)
@@ -595,21 +595,21 @@ PyFly follows the same versioning system as Spring Boot, based on **Semantic Ver
595595
| Stage | Format | Description |
596596
|-------|--------|-------------|
597597
| **SNAPSHOT** | `0.2.0-SNAPSHOT` | Active development build. Unstable, changes daily. |
598-
| **Milestone** | `0.2.0-M10` | Pre-release feature preview. New functionality available for early feedback. |
598+
| **Milestone** | `0.2.0-M11` | Pre-release feature preview. New functionality available for early feedback. |
599599
| **Release Candidate** | `0.2.0-RC1` | Feature-complete. Only bug fixes from this point. |
600600
| **GA** | `0.2.0` | General Availability. Production-ready, fully tested and stable. |
601601
602602
**Release lifecycle:** `SNAPSHOT` → `M1` → `M2` → ... → `RC1` → `RC2` → ... → `GA`
603603
604-
For Python packaging (PEP 440), milestone versions map to alpha pre-releases (`0.2.0a10`), release candidates map to `rc` (`0.2.0rc1`), and GA is the final release (`0.2.0`). See [docs/versioning.md](docs/versioning.md) for full details.
604+
For Python packaging (PEP 440), milestone versions map to alpha pre-releases (`0.2.0a11`), release candidates map to `rc` (`0.2.0rc1`), and GA is the final release (`0.2.0`). See [docs/versioning.md](docs/versioning.md) for full details.
605605
606606
---
607607
608608
## Changelog
609609
610610
See **[CHANGELOG.md](CHANGELOG.md)** for detailed release notes.
611611
612-
**Current:** 0.2.0-M10 (2026-02-28) — uv-first tooling: PEP 735 dependency-groups, uv-native CI/templates/installer, tool-neutral error messages.
612+
**Current:** 0.2.0-M11 (2026-03-01) — Thread-safety, correctness, and robustness audit: 18 fixes across DI container, web layer, resilience, security, and data modules.
613613
614614
---
615615

ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ PyFly's roadmap is driven by achieving feature parity with the full [Firefly Fra
44

55
---
66

7-
## Current State (v0.2.0-M10)
7+
## Current State (v0.2.0-M11)
88

99
PyFly ships with **27 modules** covering the foundation, application, infrastructure, and cross-cutting layers. See the [Changelog](CHANGELOG.md) for full details on what's included.
1010

docs/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ Missing optional tools are shown with a `-` dash indicator (dimmed), while missi
645645
Verifies that PyFly itself is importable and displays the installed version:
646646

647647
```
648-
✓ pyfly v0.2.0-M10
648+
✓ pyfly v0.2.0-M11
649649
```
650650

651651
### Summary

docs/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ ______ ___.__._/ ____\ | ___.__.
470470
| __// ____| |__| |____/ ____|
471471
|__| \/ \/
472472
473-
PyFly v0.2.0-M10 | Python 3.12.0
473+
PyFly v0.2.0-M11 | Python 3.12.0
474474
475475
2026-01-15T10:30:00Z [info] starting_application app=my-service version=0.1.0
476476
2026-01-15T10:30:00Z [info] no_active_profiles message=No active profiles set, falling back to default

docs/installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ PyFly Doctor
509509
✓ mypy — Type checker
510510
511511
PyFly packages:
512-
✓ pyfly v0.2.0-M10
512+
✓ pyfly v0.2.0-M11
513513
514514
All checks passed!
515515
```

docs/modules/core.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ class BannerMode(enum.Enum):
560560
| Mode | Behavior |
561561
|---|---|
562562
| `TEXT` | Full ASCII art banner (default) with a framework version line. |
563-
| `MINIMAL` | Single line: `:: PyFly :: (v0.2.0-M10)` |
563+
| `MINIMAL` | Single line: `:: PyFly :: (v0.2.0-M11)` |
564564
| `OFF` | No banner output at all. |
565565

566566
### BannerPrinter Class
@@ -601,7 +601,7 @@ ______ ___.__._/ ____\ | ___.__.
601601
| __// ____| |__| |____/ ____|
602602
|__| \/ \/
603603
604-
:: PyFly Framework :: (v0.2.0-M10)
604+
:: PyFly Framework :: (v0.2.0-M11)
605605
```
606606

607607
### Custom Banner Files

docs/versioning.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ All PyFly versions follow the `MAJOR.MINOR.PATCH` scheme:
1212
- **MINOR** — New functionality in a backward-compatible manner
1313
- **PATCH** — Backward-compatible bug fixes
1414

15-
Pre-release versions append a stage suffix: `0.2.0-M10`, `0.2.0-RC1`.
15+
Pre-release versions append a stage suffix: `0.2.0-M11`, `0.2.0-RC1`.
1616

1717
---
1818

@@ -40,7 +40,7 @@ SNAPSHOT versions represent the bleeding edge of development. They are rebuilt f
4040

4141
| | |
4242
|-|-|
43-
| **Format** | `X.Y.Z-MN` (e.g., `0.1.0-M1`, `0.2.0-M10`) |
43+
| **Format** | `X.Y.Z-MN` (e.g., `0.1.0-M1`, `0.2.0-M11`) |
4444
| **Stability** | Pre-release — APIs may still change |
4545
| **Purpose** | Feature previews and early feedback |
4646
| **Audience** | Developers evaluating upcoming features |
@@ -78,18 +78,19 @@ Python packaging standards ([PEP 440](https://peps.python.org/pep-0440/)) use a
7878
| PyFly (Spring Boot Style) | PEP 440 (`pyproject.toml`) | Example |
7979
|---------------------------|---------------------------|---------|
8080
| `0.2.0-SNAPSHOT` | `0.2.0.dev1` | Development |
81-
| `0.2.0-M10` | `0.2.0a10` | Milestone 10 |
81+
| `0.2.0-M11` | `0.2.0a11` | Milestone 11 |
8282
| `0.2.0-RC1` | `0.2.0rc1` | Release Candidate 1 |
8383
| `0.2.0` (GA) | `0.2.0` | General Availability |
8484

85-
The display version (`__version__` in `pyfly/__init__.py`) uses the Spring Boot format (`0.2.0-M10`), which is what you see in the startup banner, CLI output, and admin dashboard. The `pyproject.toml` version uses PEP 440 format for compatibility with Python packaging tools (pip, uv, hatchling).
85+
The display version (`__version__` in `pyfly/__init__.py`) uses the Spring Boot format (`0.2.0-M11`), which is what you see in the startup banner, CLI output, and admin dashboard. The `pyproject.toml` version uses PEP 440 format for compatibility with Python packaging tools (pip, uv, hatchling).
8686

8787
---
8888

8989
## Version History
9090

9191
| Version | Date | Stage | Highlights |
9292
|---------|------|-------|------------|
93+
| `0.2.0-M11` | 2026-03-01 | Milestone | Thread-safety, correctness, and robustness audit: 18 fixes across DI, web, resilience, security, data |
9394
| `0.2.0-M10` | 2026-02-28 | Milestone | uv-first tooling: PEP 735 dependency-groups, uv-native CI/templates/installer, tool-neutral error messages |
9495
| `0.2.0-M9` | 2026-02-20 | Milestone | Method security, @transactional, K8s probes, Pydantic config, soft delete/versioning |
9596
| `0.2.0-M8` | 2026-02-20 | Milestone | HttpSecurity DSL, OAuth2 login flow, data auditing, @query for MongoDB, SSE |
@@ -116,7 +117,7 @@ See **[CHANGELOG.md](../CHANGELOG.md)** for detailed release notes.
116117

117118
```python
118119
import pyfly
119-
print(pyfly.__version__) # e.g., "0.2.0-M10"
120+
print(pyfly.__version__) # e.g., "0.2.0-M11"
120121
```
121122

122123
**CLI:**
@@ -135,7 +136,7 @@ ______ ___.__._/ ____\ | ___.__.
135136
| __// ____| |__| |____/ ____|
136137
|__| \/ \/
137138
138-
:: PyFly Framework :: (v0.2.0-M10) (Python 3.13.9)
139+
:: PyFly Framework :: (v0.2.0-M11) (Python 3.13.9)
139140
Copyright 2026 Firefly Software Solutions Inc. | Apache License 2.0
140141
```
141142

install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ set -euo pipefail
2626

2727
# ── Constants ──────────────────────────────────────────────────────────────────
2828

29-
PYFLY_VERSION="0.2.0-M10"
29+
PYFLY_VERSION="0.2.0-M11"
3030
PYFLY_REPO="https://github.com/fireflyframework/pyfly.git"
3131
DEFAULT_INSTALL_DIR="$HOME/.pyfly"
3232
MIN_PYTHON_MAJOR=3

0 commit comments

Comments
 (0)