Repository navigation
Releases: Baseryn/zcore
Release list
v0.1.0-rc.3 🚀
Welcome to v0.1.0-rc.3 (Release Candidate 3) of the ZCore Framework! 🚀
As we continue advancing through the release candidate evaluation cycle toward the official v1.0.0 Stable GA, v0.1.0-rc.3 delivers significant architectural hardening, strict fail-fast lifecycle enforcement, enterprise database optimizations, and concurrency safety guarantees across the entire framework.
This release introduces native composite primary key support with PostgreSQL partition pruning; dynamic compound keyset pagination and SQLAlchemy Date coercion; a hardened keyword-mapped constructor dependency injection engine supporting Union / Optional type unwrapping; an automatic anti-shadowing hook system for subclassed routers; a dedicated, context-aware GET /_schema introspection endpoint replacing the legacy ?schema=true query parameter; thread-safe background cache eviction using double-checked locking; and strict mutually exclusive pagination validation.
🚀 Core Features & Architectural Advancements
1. 🧩 Native Composite Primary Keys & PostgreSQL Partition Pruning (BaseRepository)
Previously, BaseRepository assumed models possessed a single primary key column (primary_key[0]). In v0.1.0-rc.3, the data layer natively supports composite primary keys and PostgreSQL table partitioning (e.g., Range/List partitioning across (id, operation_date)):
- Tuple-Based Primary Key Reflection: Replaced single-column attributes with
self.pks = tuple(mapper.primary_key)andself.pk_names = tuple(col.name for col in self.pks). Automatically setsself.is_composite_pk = len(self.pks) > 1. - Fail-Fast Guarded Properties: Accessing convenience properties
self.pk,self.pk_name, orself.cursor_fieldon a composite model without an explicit override immediately raises a descriptiveAttributeError, preventing partial or corrupted queries. - PostgreSQL Partition Pruning (
tuple_.in_):_build_ids_condition()dynamically constructstuple_(*self.pks).in_(...)expressions for batch operations. This compiles to native SQL(col1, col2) IN ((val1, val2), ...), enabling the PostgreSQL query planner to perform Partition Pruning and eliminate full table scans across partitions. - Polymorphic Target Resolution (
_build_pk_condition): All CRUD operations (get,exist,update,delete,restore) now accept composite targets as ORM model instances, mapping dictionaries ({"id": 1, "operation_date": d}), or exact-length tuples/lists ((1, d)), enforcing strict key completeness and rejecting invalid scalars. - Batch Operations (
update_multi,delete_multi,restore_multi): Fully refactored to validate and assemble multi-column DBAPI payloads without ORM hydration overhead.
from datetime import date
from sqlalchemy import Date, String
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.ext.asyncio import AsyncSession
from zcore import Base, BaseRepository
# Models with composite primary keys (e.g., Partitioned Tables in SQLAlchemy 2.0)
class AuditLog(Base):
__tablename__ = "audit_logs"
id: Mapped[int] = mapped_column(primary_key=True)
created_date: Mapped[date] = mapped_column(Date, primary_key=True)
message: Mapped[str] = mapped_column(String)
class AuditRepository(BaseRepository[AuditLog]):
def __init__(self, db: AsyncSession):
super().__init__(AuditLog, db)
# Single lookup via composite tuple or dict
log = await repo.get(repo._build_pk_condition((101, date(2026, 10, 20))))
# Partition-pruned batch retrieval: (id, created_date) IN ((101, '2026-10-20'), ...)
logs = await repo.get_by_ids([(101, date(2026, 10, 20)), (102, date(2026, 10, 20))])2. ⚡ Dynamic Keyset Pagination & PostgreSQL Date Type Coercion (CursorPagination)
Resolved sorting conflicts between CursorPagination and SearchRequest, and hardened cursor boundaries for strictly-typed SQL engines:
-
Runtime Sort Overrides: Extended
CursorParamswith optionalcursor_fieldandorderattributes.BaseRouter.search_endpointandBaseRepository.searchnow automatically propagate the primary sort criteria (SearchRequest.sort[0]) directly intoCursorPagination. -
Compound Keyset Ordering: Keyset pagination now supports arbitrary non-PK sorting columns using compound keyset boundary evaluations:
- DESC:
(col < val) OR (col == val AND pk < last_pk) - ASC:
(col > val) OR (col == val AND pk > last_pk)
This completely eliminates data collision, record skipping, and duplication across sequential pages. Existing ordering clauses are reset via
query.order_by(None)before keyset application. - DESC:
-
SQLAlchemy
DateColumn Coercion: In SQLAlchemy,Datedoes not inherit fromDateTime. Drivers likeasyncpgpreviously raisedDatatypeMismatchError: operator does not exist: date < character varying.CursorPaginationnow explicitly detectsisinstance(col.type, Date), strips optional ISO time fragments viaval.split("T")[0], and coerces boundaries usingdatetime.date.fromisoformat(). -
Extended Serialization:
_encode_cursornatively serializesdate,datetime,UUID, andDecimaltypes to strings.
3. 🎯 Keyword-Based Constructor Auto-Wiring & Default Fallbacks (IoCContainer)
Completely overhauled IoCContainer._auto_wire to improve reliability, support optional type signatures, and enforce lifecycle boundaries:
- Unregistered Default Skipping: Constructor parameters defining default values (e.g.,
timeout: int = 30orclient: Any = None) whose types are not explicitly registered in the container are skipped during dependency collection, allowing Python to fall back safely to the declared default. - Registration Precedence: If a dependency type defines a default value but is explicitly registered in the container, the container-managed instance takes precedence and is injected.
- Keyword Auto-Wiring (
**kwargs): Auto-wiring now constructs class instances using keyword arguments (**resolved_kwargs) rather than positional arguments (*args). This eliminates parameter misplacement when optional/default parameters precede registered dependencies or whenKEYWORD_ONLYparameters are used. - Type Unwrapping (
_unwrap_type): Added recursive type normalization forAnnotated,typing.Union, and Python 3.10+types.UnionType(e.g.,IService | None = None). - Cache Compatibility (
_DependencySignature): Implemented a specializedlistsubclass (_DependencySignature) that preserves list-like backward compatibility for test assertions (assert cache[cls] == [...]) while internally mapping parameter names to dependency types (kwargs_map). - Strict Scope Boundaries: Resolving scoped dependencies or
AsyncSessionoutside an active scope context (_current_scope_id is None) now immediately raisesDIException.
4. 🛡️ Subclass Route Auto-Sorting & Anti-Shadowing Hooks (BaseRouter)
Eliminated route shadowing bugs where custom endpoints registered in BaseRouter subclasses were shadowed by dynamic parameterized paths (e.g., /{id:uuid} capturing requests intended for /summary or /reports):
- Dynamic Sorting Hooks (
_bind_router_sorting_hooks): Wrapsself.router.add_api_routeandself.router.add_routeduring initialization. Whenever a subclass registers a route (even inside__init__aftersuper().__init__()), routes are automatically re-sorted based on path specificity. - Subclass Lifecycle Hook (
register_custom_routes): Added a declarative hook method invoked at the tail of_register_routes()allowing clean custom endpoint registration without overriding__init__. - Public Sorting Method: Added
router.sort_routes()exposing on-demand specificity sorting.
5. 🔍 Dedicated Schema Introspection Endpoint (GET /_schema)
Replaced the legacy ?schema=true query parameter with a dedicated, standardized schema introspection endpoint:
- Endpoint Mapping (
RouteKey.SCHEMA): ScaffoldsGET /_schema(customizable viaschema_path, defaults to/_schema) ranked with high specificity to prevent path capture. - Action-Specific & Full Resource Introspection:
GET /_schema— Returns all available schemas for the resource (create,update,view,lookup).GET /_schema?action=create|update|view|lookup— Returns the targeted JSON schema.
- Security & Context Pruning: Dynamically evaluates schemas under active request context, pruning fields defined in
ctx.restricted_fieldsorZchema.__private__. - Cleaned Route Handler: Stripped inline schema generation and reflection logic from
ZCoreAPIRoute, improving HTTP request execution throughput.
# Full resource introspection
curl -X GET "http://localhost:8000/api/v1/products/_schema"
# Action-specific introspection (sensitive fields pruned based on credentials)
curl -X GET "http://localhost:8000/api/v1/products/_schema?action=view" \
-H "Authorization: Bearer <token>"6. 🚦 Fail-Fast Pagination Validation (SearchRequest)
Enforced contract mutual exclusivity between offset pagination and keyset pagination:
- Conflicting Parameter Rejection:
SearchRequestnow validates thatcursorandpage > 1are never submitted simultaneously. - Strict 422 Response: If both are supplied, a
ValueErroris raised at the Pydantic validation boundary, returning a standard 422RequestValidationErrorenvelope. Standard single-page requests (page=1withcursor) remain fully supported.
7. 🔒 Thread-Safe Cache Eviction Loop (_eviction_lock)
Resolved a multi-threaded race condition in zcore.cache.base._ensure_eviction_task:
- Double-Checked Locking: Guarded background memory eviction loop instantiation with
_eviction_lock = threading.Lock(). When multiple threads (e.g...
v0.1.0-rc.2 🚀
Unified Exception Envelope, End-to-End Soft-Delete Lifecycle, Lightweight LOOKUP Projections, Inverted Search Operators, Re-entrant Unit of Work & Polymorphic Identifiers
Welcome to v0.1.0-rc.2 (Release Candidate 2) of the ZCore Framework! 🚀
As we approach the final validation phase before tagging our official v1.0.0 Stable GA, v0.1.0-rc.2 focuses on framework-wide standardization, operational robustness, and developer ergonomic refinements.
This release introduces an automated, normalized exception handling system conforming all HTTP errors to the ResponseWrapper envelope; implements an end-to-end soft-delete, restoration, and forced hard-delete lifecycle; scaffolds a high-performance, schema-projected /lookup endpoint; expands the dynamic AST search engine with negated operators and logical NOT grouping; establishes re-entrant, depth-aware Unit of Work coordination; generalizes user identifiers (int, str, UUID) across all subsystems; and introduces schema-level private field shielding for unauthenticated guests.
🚀 Core Features & Architectural Advancements
1. 🛡️ Unified Exception Handling & Error Normalization (ResponseWrapper)
Previously, standard FastAPI validation failures (422) and Starlette HTTP exceptions bypassed ZCore's standardized response structure. In v0.1.0-rc.2, all exceptions are normalized into a unified, consistent JSON envelope:
- Pydantic Error Sanitization (
_sanitize_error_item,_format_error_location): Converts raw Pydantic error loc tuples into clean, dot-separated field paths (e.g.,body.email,query.limit) and safely serializes context payloads. - Unified Handlers:
request_validation_exception_handler: Formats 422 errors with clean field-level error lists and a human-readable summary.http_exception_handler: Preserves original response headers while wrapping Starlette/FastAPIHTTPExceptioninstances.response_validation_exception_handler: Intercepts internal schema mismatch errors (500) and displays field diagnostics only whensettings.DEBUGis enabled.unhandled_exception_handler: Catch-all fallback for uncaught runtime crashes with debug-gated stack traces.
- Centralized Registration (
register_exception_handlers): A single callregister_exception_handlers(app)binds all handlers to FastAPI with granular feature toggles. - Lazy Module Packaging: Handlers are exported at the root package level via dynamic
__getattr__resolution to avoid circular import issues.
2. 🗑️ End-to-End Soft-Delete Lifecycle & Restoration (restore, force)
Soft deletion is now fully integrated through the Repository, Service, and Web layers:
- Atomic Batch Soft-Delete:
delete_multi()executes atomicUPDATE ... SET deleted_at=now()with SQL dialect-awareRETURNINGsupport and pre-fetch fallbacks. - Single & Batch Restoration: Added
restore(target)andrestore_multi(ids)toWriteRepositoryMixinandWriteServiceMixinto recover soft-deleted records (deleted_at=None). - Forced Physical Hard Deletes: Added
force: bool = Falseacross repository, service execution orchestrators, and lifecycle hooks (pre_delete,post_delete,pre_delete_multi,post_delete_multi). - Web Router Query Flag: Auto-scaffolded DELETE endpoints accept
?force=true(e.g.,DELETE /tasks/{id}?force=true) to permanently purge records when requested.
3. 🔍 Lightweight LOOKUP Endpoint & Schema-Driven Projections (POST /lookup)
For autocomplete selectors, dropdown lists, and relational references where fetching full database entities is wasteful:
- Automatic Schema Projection (
_resolve_lookup_projections): Introspectslookup_schemaagainst SQLAlchemy model metadata to selectively generateload_only(*columns)statements, always including primary keys. - Automatic Eager-Loader Configuration: Detects relationships declared in
lookup_schemaand attaches optimal loader strategies (selectinloadfor collections,joinedloadfor scalar relations). - Strict Whitelist Protection (
allowed_lookup_fields): Client queries attempting to filter or sort on unauthorized fields are immediately rejected with a 400ValidationError. - RBAC Integration: Mapped to
Actions.LOOKUP(model.actions().LOOKUP) for granular permission checks.
4. ⚡ Search Engine Negation & Logical NOT Grouping (SearchEngine)
The dynamic JSON search engine now supports inverted filter operations:
- Inverted Operators: Added
not_like,not_ilike,not_contains,not_startswith,not_endswith,not_in,not_between, andis_not_null. - SQL Expression Wrapping:
_compare_columndetectsnot_prefixes and wraps clauses in SQLAlchemy'snot_()expression. - Logical
NOTBlocks: Evaluates nested filter groups underop="not"asnot_(and_(*sub_exprs))or single-field inversions. - Null Semantics:
is_nullandis_not_nullnow accept boolean flags (True/False) orNonevalues consistently.
5. 🔗 Re-entrant Unit of Work & Deferred Domain Events (UnitOfWork)
To coordinate multi-service business transactions across complex modular monolith architectures:
- Depth-Aware Re-entrancy (
uow_depth): Tracks execution nesting depth insession.info['uow_depth']. NestedUnitOfWorkblocks execute safe intermediatesession.flush()calls, delegating the physicalsession.commit()solely to the outermost root boundary. - Buffered Post-Commit Events: Domain events registered via
uow.register_event()across nested scopes accumulate insession.info['uow_events']and dispatch atomically only after the root transaction commits. - Global Rollback Safeguard: Any unhandled exception resets depth to
0, clears pending events, and executes an immediate session rollback.
6. 🆔 Polymorphic User Identifiers (int, str, UUID)
Removed strict uuid.UUID type enforcement from core identity layers:
- Polymorphic
ZContext&UserProtocol:ZContext.user_idandUserProtocol.idnow acceptAny | None(supporting integer IDs, UUIDs, Auth0/Firebase string IDs, or custom tenant keys). - Real-time Streaming (
StreamManager): Subscriber mapping queues (users_queues) now accept arbitrary user ID types with mixed-type string comparison routing. - Cursor Pagination PK Inspection: Keyset cursor pagination dynamically inspects column types (
mapper.primary_key[0].type.python_type), coercing cursor payload keys tointorUUIDautomatically.
7. 🔒 Optional Authentication & Schema-Level Private Fields (Zchema.__private__)
Enables clean guest-friendly routes and sensitive field filtering:
- Optional Authentication (
BaseAuth(auto_error=False)): Allows endpoints to accept optional authentication without raising401 Unauthorizedon missing or invalid tokens. - Dependency Anchor (
get_optional_user_stub): Exported acrosszcoreandzcore.securityfor optional route parameters. - Private Field Pruning (
__private__): Schemas can declare sensitive fields via__private__: ClassVar[set[str]] = {"cost_price", "notes"}. ZCore automatically prunes these fields from response payloads, input validations, and generated JSON schemas (?schema=true) when no authenticated user is present.
8. ⚙️ Tunable Framework Settings & Request Boundary Clamping
Replaced magic numbers across subsystems with environment-driven settings in Settings:
- Subsystem Tuning: Added
PAGINATION_DEFAULT_SIZE(20),PAGINATION_MAX_SIZE(100),SEARCH_MAX_DEPTH(3),CACHE_LOCAL_MAXSIZE(1000),CACHE_DEFAULT_TTL(3600),CACHE_EVICTION_INTERVAL(60),STREAM_QUEUE_MAXSIZE(100), andAUTH_CACHE_TTL(300). - Dynamic Parameter Validation: Added Pydantic
@model_validatoracrossPageNumberParams,CursorParams, andSearchRequestto clamp requested page sizes within configured minimum and maximum boundaries.
9. 🧪 Advanced Testing Harness & Sandboxing Engine (zcore.testing)
Comprehensive upgrades to make automated testing deterministic and isolated:
- Database Table Lifecycle (
setup_test_database): Drop and recreate test database tables across sync fixtures or running event loops viaThreadPoolExecutorsafely. - Event Sandboxing (
EventDispatcherSandbox): Snapshots and restores registered event subscribers across test runs, eliminating listener pollution. - Multi-Dependency Overrides:
DatabaseRollbackandZTestClientsupport custom engine injections, multiple authentication stub overrides, and strict Pydantic user model validation (user_model).
10. 🪵 Non-Intrusive Logging & Context Isolation
Refined logging signal-to-noise ratio across development and production modes:
- Status-Code-Aware Exception Logging: Application and HTTP exceptions log at
DEBUGfor client errors (< 500) andERRORfor server failures (>= 500). - Independent Slow-Query Interceptor: Slow queries exceeding
slow_query_threshold_msare logged even if generallog_sql_queriesis disabled. - Developer Console Mode: Development mode preserves native Uvicorn console formatting via
passthrough_loggers, switching cleanly toProcessorFormatterJSON rendering in production. - Background Scope Context:
background_scopeisolates Structlog contextvars, bindstask_id=scope_id, and restores parent context on exit.
11. 🖥️ Cascading CLI Server Configuration & Dynamic Scaffolding
Upgraded the zc command-line tool:
- Cascading Precedence (
zc run): Server parameters resolve with the precedence:CLI Arguments > .env File > Defaults. - Transparent Uvicorn Passthrough: Uses
parse_known_args()to forward arbitrary flags (e.g.,--root-path,--proxy-headers) directly to Uvicorn. - Multi-Worker Safety: Automatically d...
v0.1.0-rc.1 🚀
Dynamic Primary Keys, Weighted Route Specificity, Enterprise Logging, Dialect-Aware Fallbacks & Hardened Storage Sandbox
Welcome to v0.1.0-rc.1 (Release Candidate 1) of the ZCore Framework! 🚀
As we officially transition from the Beta phase toward the v1.0.0 Stable GA, v0.1.0-rc.1 marks a major milestone in framework stability, security hardening, and production readiness.
This release delivers dynamic primary key detection across REST endpoints, introduces an anti-shadowing weighted route sorting algorithm, optimizes ORM mutations to accept model instances directly (bypassing duplicate database fetches), adds dialect-aware batch fallbacks for non-RETURNING databases (such as MySQL), integrates a centralized IANA timezone subsystem (ZDateTime), redesigns the structured logging pipeline via ProcessorFormatter, completely hardens the file storage layer with strict sandboxing and active XSS/executable scanning, and achieves complete unit and integration test coverage across all subsystems.
🚀 Core Features & Architectural Advancements
1. 🎯 Dynamic Primary Key Resolution & Generalized Routing (BaseRouter)
Previously, BaseRouter assumed model primary keys were strictly UUIDs. In v0.1.0-rc.1, routing infrastructure dynamically inspects ORM metadata:
- Automatic PK Type Detection (
_resolve_pk_type): Automatically resolves whether the primary key is anint,uuid.UUID, or other scalar type via SQLAlchemy column inspection. - Dynamic Path Mapping (
_get_pk_path): Generates type-safe URL converter paths (e.g.,/{id:int}for integer PKs,/{id:uuid}for UUIDs, or/{id}as a fallback). - Explicit PK Override: Models or routers can explicitly declare
pk_type = intto override dynamic reflection. - Streamlined Endpoint Signatures: Cleaned up internal wrapper signatures by removing unused
**kwargsand enforcing explicit parameter typing.
2. ⚖️ Weighted Route Specificity Sorting (Anti-Path Shadowing)
A notorious issue in REST frameworks is Path Shadowing—where dynamic parameterized routes accidentally capture requests intended for static endpoints (e.g., GET /{id} shadowing POST /search).
- Multi-Tier Weighted Scoring (
_sort_routes): Replaced basic string sorting with an advanced scoring tuple:(has_dynamic, total_dynamic, segment_scores, -len(segments))
- Strict Route Precedence: Guarantees that static segment routes (
/search) are always matched before single dynamic parameters (/{id}) and catch-all path parameters (/{path:path}), regardless of declaration order.
3. ⚡ Optimized Instance-Aware ORM Mutations (update, delete, update_multi)
To eliminate redundant database lookups when an entity is already loaded in memory:
- Direct Model Acceptance:
BaseRepository.update()andBaseRepository.delete()now accepttarget: ModelType | Any. If a model instance is passed directly, the preliminarySELECTquery is completely skipped. - Instance-Keyed Batch Updates:
update_multinow accepts dictionaries keyed by either model instances or primary key scalars (dict[ModelType | Any, BaseModel]), resolving the PK seamlessly viagetattr(key, self.pk_name, key). - Aligned Service Hooks: Updated
pre_update,on_update,pre_delete, andon_deleteinBaseServiceto accepttarget: ModelType | Any.
4. 🔄 Cross-Dialect Batch Compatibility (Dialect-Aware Fallbacks)
Enables seamless database portability across SQL engines that lack native RETURNING support:
- Dialect-Aware
create_multi: Inspects the engine'sinsert_returningcapability. If supported (PostgreSQL, modern SQLite), it executesinsert().returning(). Otherwise (MySQL, older SQLite), it falls back gracefully todb.add_all()anddb.flush(). - Dialect-Aware
delete_multi: Inspectsdelete_returning. If unsupported, it fetches records viaget_by_ids()prior to atomic deletion, guaranteeing deleted instances are returned intact.
5. ⏱️ Centralized Timezone Management & ZDateTime Subsystem
Introduced zcore.utils.timezone for robust, timezone-aware datetime manipulation:
- IANA
ZoneInfoResolution (get_app_timezone): Resolves timezones with LRU caching and falls back safely toUTCif an invalid timezone is provided. ZDateTimeType Alias: Custom type alias utilizing Pydantic'sPlainSerializerto automatically format datetimes as timezone-aware ISO 8601 strings with offsets during JSON serialization.- Timezone-Aware Helpers: Added
now(),utc_now(),to_app_timezone(), andformat_iso_with_app_timezone(). - Soft Delete & JSON Sync:
SoftDeleteMixinandCustomJSONEncodernow natively utilize timezone-aware timestamps. - Windows Support: Added
tzdata>=2024.1for guaranteed IANA timezone database resolution on Windows environments.
6. 🪵 Enterprise Structured Logging (LoggingSettings & ProcessorFormatter)
Redesigned the logging pipeline to seamlessly unify structlog and Python's standard logging library:
ProcessorFormatterIntegration: Eliminates duplicate log emissions and bridges third-party loggers (uvicorn,sqlalchemy.engine) into a unified structlog pipeline.LoggingSettingsModel: Configured viaSettings.LOGGINGwith backward-compatible bidirectional synchronization to legacyLOG_LEVEL.- Slow Query Interceptor: Added
slow_query_threshold_msto silently filter out fast queries and log only statements exceeding latency thresholds. - Built-in File Rotation & DictConfig: Added
RotatingFileHandlersupport (10MB, 5 backups) viafile_pathsetting and support for fulllogging.config.dictConfigoverrides. - Enhanced Telemetry:
RequestLogMiddlewarenow captures real HTTP status codes fromhttp.response.startand client IPs.
7. 📦 Sandboxed Local Storage & Advanced Threat Validation
Expanded zcore.storage into an enterprise-grade, sandboxed asset management subsystem:
- Path Traversal Defense:
LocalStorageProviderincorporates_extract_key,_key_to_path, and_resolve_pathto strictly bound all read/write/delete operations withinbase_path. - URL Resolution & Existence Check: Added
get_url(file_path_or_url)andexists(file_path_or_url)to theStorageProviderbase interface. - Executable & XSS Threat Detection (
SafeMimeTypeValidator):- Increased sample inspection buffer from 2KB to 8KB.
- Rejects binary executable headers (
MZfor.exe/.dll,#!/for shell scripts,\x7fELFfor Linux binaries). - Scans file payloads for Stored XSS and active script injections (
<script>,<?php,javascript:,onload=,onerror=,<iframe>, etc.).
8. 🔍 Search Engine Hardening & Operator Unification
- Consolidated Text Operators: Unified
containsinto theilikeoperator family with automatic SQL wildcard escaping (%,_). - Non-String Column Text Search: Automatically casts non-string database columns (e.g., UUIDs, integers) via
cast(col, String)when text operators (ilike,startswith,endswith,contains) are applied. - Expanded Type Coercion: Supports
setcollections alongsidelistandtupleforinoperators, and provides clear, column-awareValidationErrormessages when coercion fails.
9. 🗄️ Native Engine JSON Serialization & Guaranteed Lifespan Teardown
- Custom JSON Column Serializer:
DatabaseManagerpassesjson_dumpsandjson_loadsdirectly tocreate_async_engine, enabling native persistence ofUUID,Decimal,date, anddatetimetypes in database JSON/JSONB columns. - Guaranteed Shutdown Teardown:
Kernel.lifespanautomatically executesawait close_cache()andawait db_manager.close()in itsfinallyblock, ensuring clean connection pool disposal upon application shutdown. - Event-Loop Safe Cache Eviction: Background cache eviction task in
BaseCachelazily schedules sweeps only when an active event loop is running, preventingRuntimeErrorduring CLI/import time.
⚠️ Breaking Changes & Migration Guide
1. get_list Positional Parameter Ordering
In BaseRepository and BaseService, variadic filter expressions (*criterion) have been moved to the beginning of the parameter list to match standard Python conventions and prevent positional shifting.
Old:
# Ambiguous positional parameter placement
items = await repo.get_list(pagination_params, fields_list, User.is_active == True)New:
# Positional criterion first, optional controls via keyword arguments
items = await repo.get_list(
User.is_active == True,
pagination=pagination_params,
fields=fields_list
)2. Passing Model Instances to update() and delete()
You can now pass either the primary key or the instantiated model directly to service.update() and service.delete().
Old:
user = await user_service.get(id=user_id)
# Required passing ID, triggering an unnecessary second SELECT query
updated = await user_service.update(user.id, user_update_schema)New:
user = await user_service.get(id=user_id)
# Direct instance update (zero redundant SELECT queries)
updated = await user_service.update(user, user_update_schema)3. Structured Database Configuration
db_manager.init_app now accepts structured DatabaseSettings objects directly.
Old:
db_manager.init_app(
db_url=settings.DATABASE_URL,
pool_size=settings.POOL_SIZE,
max_overflow=settings.MAX_OVERFLOW,
echo=settings.DEBUG
)New:
# Pass structured settings directly
db_manager.init_app(config=settings.DATABASE)4. Storage Upload Method Returns Web URL
StorageProvider.upload() and `upload_stream...
v0.1.0-beta.8 🚀
Interactive TUI Engine, Bulk Mutation Optimizations, Isolated Background Tasks & Built-in Soft Delete
Welcome to v0.1.0-beta.8 of the ZCore Framework! 🚀
As we approach our milestone v1.0.0 stable release, v0.1.0-beta.8 delivers major performance breakthroughs in relational data mutations, introduces an enterprise-grade isolated background task execution pipeline with automatic dependency injection, embeds native soft-delete capabilities, significantly expands dynamic search operators, completely redesigns the developer experience with a rich, interactive Terminal User Interface (TUI), and aligns all CLI scaffolding templates with the latest single-generic architecture.
🚀 Core Features & Architectural Advancements
1. ⚡ High-Performance Bulk DBAPI Mutations (create_multi, update_multi, delete_multi)
We completely revamped the bulk data modification pipelines in BaseRepository to bypass individual ORM hydration overhead and leverage native database acceleration:
create_multiviaINSERT ... RETURNING: Batch insertions now execute in a single roundtrip using atomicINSERT ... RETURNINGclauses, eliminating individual entity flushes while returning fully hydrated model instances.update_multivia DBAPIexecutemany: Batch updates now bypass pre-fetching and hydrating ORM entities in memory. Updates are executed directly at the DBAPI level with compiled parameterized payloads, followed by a single consolidated batch query fetch.delete_multiviaDELETE ... RETURNING: Bulk deletions are executed in a single atomic SQL statement without prior entity fetching, returning all deleted records cleanly.
2. ⏱️ Isolated Background Tasks & Scope Management (background_scope, @background_task)
Running background jobs in FastAPI that access request-scoped dependencies or database sessions often triggers RuntimeError: Session is closed. ZCore resolves this at the architectural layer:
background_scopeAsync Context Manager: Provisions an independent IoC scope, allocates a fresh, dedicatedAsyncSessionfromdb_manager, and safely clones the active user context (inherit_context=True) for background execution.@background_taskDecorator: Automatically wraps any async coroutine or synchronous function (executed in a non-blocking threadpool viaanyio.to_thread) insidebackground_scope().- Automatic IoC Auto-Wiring: Any type-annotated parameter omitted during invocation is automatically resolved directly from the IoC container.
3. 🗑️ Built-in Soft Deletion Infrastructure (SoftDeleteMixin)
Soft deletion is now an out-of-the-box framework primitive rather than a manual scoping pattern:
SoftDeleteMixin: Add timestamp-based soft deletion to any model withclass Task(Base, SoftDeleteMixin):.- Automatic Query Scoping: Injects an indexed, timezone-aware
deleted_at: Mapped[datetime | None]column and automatically filters all repository operations (get(),get_list(),count(),exist(),search()) withWHERE deleted_at IS NULL. - Lifecycle Helpers: Provides clean
task.soft_delete(),task.restore(), andtask.is_deletedproperties.
4. 🔍 Advanced Dynamic Search Operators & Configurable Depth (SearchEngine)
The dynamic query engine has been significantly expanded with powerful string-matching and range operators:
contains: Performs substring matching on text columns (with automatic wildcard sanitization) and collection containment.startswith&endswith: String prefix and suffix matching with automated SQL wildcard escaping.between: Range evaluations for numerical, date, and timestamp columns accepting inclusive[min, max]boundaries with automatic type coercion.- Configurable
__max_search_depth__: Filter and relation inclusion (include) depth limits can now be customized per model via the__max_search_depth__attribute (defaulting safely to3to defend against query DoS attacks).
5. 🛡️ Scope-Aware Existence Verifications (exist)
BaseRepository.exist()now strictly evaluates and enforces model-levelscope_queryand soft-delete filters before checking record existence vialimit(1), preventing cross-tenant or deleted entity enumeration.
6. 🖥️ Interactive TUI & Scaffolding Engine (zc)
The zc CLI has been completely rewritten into an interactive Terminal User Interface powered by Rich and Questionary:
- Context-Aware Dashboard: Running
zcautomatically detects whether you are in an active project or a workspace with multiple microservices. - Multi-Database Bootstrapping:
zc initinteractively configures SQLite (aiosqlite), PostgreSQL (asyncpg), or MySQL (aiomysql) with pre-configured.envandrequirements.txtfiles. - Automated Virtual Environment Setup: Automatically initializes isolated
.venvenvironments and installs dependencies using ultra-fastuvor standardpip. - Granular 7-Layer Scaffolding:
zc startappsupports Full Boilerplate, Clean/Blank, or Custom Layer Selection across Models, Schemas, Repositories, Services, Routers, Plugins, and Pytest suites. - Automatic Secret Key Generation:
zc initautomatically provisions fresh 64-character cryptographicSECRET_KEYstrings into.env.
🐛 Bug Fixes & Refinements
7. 🛠️ CLI Scaffolding Template Alignment
- Fixed
BaseRepository&BaseServiceBoilerplate: Corrected scaffolding templates inzcore.cli.templates(REPOSITORY_TEMPLATEandSERVICE_TEMPLATE) to use the streamlined single-generic signature (BaseRepository[Model]andBaseService[Model]) introduced inv0.1.0-beta.7, removing obsolete schema generic parameters and redundant imports. - AST Compilation Test Guard: Added explicit AST compilation testing to the test suite (
test_scaffolded_templates_are_valid_python) to guarantee all generated boilerplates are 100% valid, error-free Python code.
⚠️ Breaking Changes & Migration Guide
1. Simplified Bulk Mutation Return Signatures
Because create_multi, update_multi, and delete_multi now utilize database-level RETURNING clauses and direct DBAPI execution, manual refresh=True loops are no longer needed.
Old:
# Iteratively flushed and refreshed entities in python
created_items = await repo.create_multi(schemas, refresh=True)New:
# Instant atomic database RETURNING execution
created_items = await repo.create_multi(schemas)2. Upgrading Soft Deletion to SoftDeleteMixin
If you previously wrote manual WHERE is_deleted == False clauses in scope_query, you can now inherit directly from SoftDeleteMixin.
Old:
class Task(Base):
__tablename__ = "tasks"
is_deleted: Mapped[bool] = mapped_column(default=False)
@classmethod
def scope_query(cls, query: Select) -> Select:
return query.where(cls.is_deleted.is_(False))New:
from zcore import Base, SoftDeleteMixin
class Task(Base, SoftDeleteMixin):
__tablename__ = "tasks"
# Automatically provides deleted_at, is_deleted, soft_delete(), restore(), and scope_query3. Background Task Execution
Replace manual session allocations inside background routines with @background_task.
Old:
# Fragile: risks closed session errors after request terminates
async def process_task(task_id: uuid.UUID):
session = container.resolve(AsyncSession)
await session.execute(...)New:
from zcore.kernel import background_task
from zcore import Inject
@background_task
async def process_task(task_id: uuid.UUID, service: Inject[TaskService]):
# Automatically runs in an isolated IoC scope & independent AsyncSession
await service.process(task_id)🛠 How to Install / Upgrade
To install or upgrade to v0.1.0-beta.8:
pip install --upgrade fastapi-zcore-framework[all]📖 Interactive Documentation: https://baseryn.github.io/zcore-docs/
v0.1.0-beta.7 🚀
Core Architecture Overhaul, Testing Subsystem & Unified Security
Welcome to v0.1.0-beta.7 of the ZCore Framework! 🚀
This is one of the most substantial and transformative releases in ZCore's history. Guided by our foundational philosophy of Engineered Simplicity (KISS) and Clean Architecture, v0.1.0-beta.7 eliminates generic boilerplate across data layers, introduces a complete asynchronous testing framework with transaction rollback guarantees, unifies request-scoped context state and security primitives, and introduces event-driven subscriber mechanics.
🚀 Core Features & Architectural Advancements
1. 🧪 Comprehensive Async Testing Infrastructure (zcore.testing)
Writing integration and unit tests for database-backed FastAPI services is now effortless and boilerplate-free:
ZTestFixtureEngine: Modular async fixtures includingContainerSandbox(snapshots and restores IoC state),DatabaseRollback(wraps tests in isolated savepoint transactions),UserContext(injects user identities and security scopes), andAppLifespan(manages FastAPI lifecycle hooks).ZTestClient: An asynchronous test client extendinghttpx.AsyncClientthat coordinates test sandboxes with zero manual mock setups.BaseZTest: An abstract class providing clean, class-based test suites using an intuitiveasync with self.run(use_db=True)context manager.- CLI Test Generator: Run
zc startapp <domain> --testto scaffold ready-to-run test files automatically.
2. 🌐 Centralized Request Context & Scopes (ZContext & ctx)
Replaced fragmented context functions with a unified, high-performance, contextvar-isolated ZContext class:
- Global
ctxSingleton: Access context variables anywhere in the request lifecycle via strongly-typed properties (ctx.user_id,ctx.restricted_fields,ctx.action). ctx.scope()Context Manager: Create isolated, temporary context overrides for background tasks, cron jobs, or test sandboxing.- Action-Aware Routing: Route operations (
create,view,update,delete) are automatically detected and injected intoZContext, driving action-scoped field pruning inZchema.
3. 🧹 Streamlined Data Layer Generics & Dynamic Hook Propagation
We eliminated the verbose schema generic clutter from data access layers:
- Single Generic Parameter:
BaseRepository[Model]andBaseService[Model]now only require the database model type. - Dynamic Criterion & Query Filters: Repository
get(),exist(), andget_list()now accept arbitrary positional SQLAlchemy binary expressions (*criterion) and keyword arguments (**filters) consolidated via_apply_filters. - Dynamic Pre-Hook Data Injection: Service
pre_createandpre_updatelifecycle hooks can now return a dictionary (Optional[dict[str, Any]]) that automatically merges context-derived data (e.g.,user_idfromctx) directly into repository database flushes.
4. 🔐 Consolidated Security & Generic Authentication (BaseAuth)
- Unified
SecurityClass: Merged scattered hashing and JWT logic into a centralizedSecuritycoordinator supporting Argon2id password hashing, PyJWT token encoding/decoding, and cryptographic token generation. - Template Method
BaseAuth: A generic authentication dependency that extracts and validates tokens, integrates withBaseCachefor user-lookup caching, and automatically binds the resolved user toZContext. - Dynamic Scope Resolution:
HasScopespermission dependencies now evaluate scopes dynamically fromZContext(ctx.get("scopes")) with automatic type coercion for lists, tuples, and sets.
5. ⚡ Modern Constructor Auto-Wiring (Inject[T])
- Converted
Injectinto a subscriptable type marker (Inject[T]), which seamlessly maps toAnnotated[T, Depends(Injector(T))]. - Allows clean, idiomatic constructor type-hinting in services and routes without importing or declaring raw FastAPI
Depends()chains.
6. 📡 Event-Driven Architecture (@on_event) & SQL Diagnostics
@on_eventDecorator: Mark service methods as event subscribers with automatic container-backed resolution viaEventDispatcher.register_listeners().- SQL Execution Telemetry: Built-in connection interceptors log SQL execution durations in milliseconds and filter out Postgres system catalog query noise.
- Static Route Protection: Added
_sort_routes()to ensure parameterized paths (e.g.,/{id:uuid}) never shadow sibling static endpoints like/search.
🛠️ CLI & Subsystem Enhancements
zc genenv: Introspects registered PydanticSettingsclasses and scaffolds a clean.env.examplefile automatically.SettingsSimplification: RenamedZCoreCoreSettingstoSettingsand replacedENVIRONMENTstrings with booleanDEBUGflags.ZCoreJSONResponse: Replaces standard JSON responses to safely serialize complex types (UUIDs, ISO datetimes, Decimals).- Standalone Documentation Portal: Decoupled documentation from the core repository into the official standalone repository Baseryn/zcore-docs.
⚠️ Breaking Changes & Migration Guide
1. Repository and Service Generic Declarations
You no longer need to pass schema types to BaseRepository or BaseService.
Old:
class TaskRepo(BaseRepository[Task, TaskCreate, TaskUpdate]):
...
class TaskService(BaseService[Task, TaskCreate, TaskUpdate]):
...New:
class TaskRepo(BaseRepository[Task]):
...
class TaskService(BaseService[Task]):
...2. Base Settings & Debug Configuration
The settings class name has been simplified, and ENVIRONMENT is now DEBUG.
Old:
from zcore import ZCoreCoreSettings
class AppSettings(ZCoreCoreSettings):
ENVIRONMENT: str = "development"New:
from zcore import Settings
class AppSettings(Settings):
DEBUG: bool = True3. Dependency Injection Syntax
Update route handlers and constructors to use Inject[T] type annotations.
Old:
@router.post("/tasks")
async def create_task(service: TaskService = Inject(TaskService)):
...New:
from zcore import Inject
@router.post("/tasks")
async def create_task(service: Inject[TaskService]):
...4. Consolidated Security Utilities
Imports from zcore.security.hashing and zcore.security.jwt are merged under Security.
Old:
from zcore.security.hashing import hash_password, verify_password
from zcore.security.jwt import create_access_tokenNew:
from zcore import Security
hashed = Security.hash_password(raw_password)
token = Security.create_jwt({"sub": str(user_id)})🛠 How to Install / Upgrade
To install or upgrade to the latest beta:
pip install --upgrade fastapi-zcore-framework📖 Interactive Documentation: https://baseryn.github.io/zcore-docs/
v0.1.0-beta.6 🚀
Welcome to v0.1.0-beta.6 of the ZCore Framework! 🚀
This release represents a significant step forward in robust data handling, security validation, and comprehensive project governance. Following our core philosophy of Engineered Simplicity (KISS), we have addressed critical edge-cases in timezone serialization, refined schema semantics to align with Domain-Driven Design (DDD), and overhauled our repository's testing and automation pipelines to provide an out-of-the-box, production-ready developer experience (DX).
🚀 Core Architectural Refinements
🌐 Decoupled Presentation Layer Domain (__model__)
In Zchema (zcore/web/projection.py), we have officially deprecated the class attribute __db_name__ in favor of a more semantic and architecturally accurate attribute: __model__.
- The Rationale: Schemas (DTOs) belong purely to the presentation layer and should not be tightly coupled to database nomenclature by name.
- The Alignment: All internal recursion, pruning logics, and CLI code-generation templates have been fully migrated to use
__model__for strict domain binding.
🔌 Lazy-Loaded Root Namespace Imports
Developers can now import highly utilized core framework constructs directly from the root namespace:
from zcore import RouteKey, Plugin- Previously, this forced developers to write long, internal import paths.
- We implemented dynamic, lazy-loaded import resolutions within
src/zcore/__init__.pyusing Python's dynamic__getattr__block, ensuring no performance or startup overhead during initialization.
🐛 Data Integrity & Security Fixes
🔢 Precision-Preserving Decimal Serialization
Changed JSON encoding for Decimal instances from standard floating-point (float) to string (str) inside the CustomJSONEncoder.
- The Fix: Converting Decimals to floats introduces floating-point arithmetic inaccuracies and precision loss right before data is dispatched to clients.
- The Result: Preserves exact decimal precision, establishing the industry standard for financial calculations and highly accurate APIs.
🗺️ Timezone-Aware Pagination Cursors
Refactored the _encode_cursor method inside zcore/db/pagination.py to intercept naive datetime instances.
- Naive datetimes are now explicitly normalized to UTC, and timezone-aware instances are converted safely to UTC before being base64 encoded into cursor payloads.
- Resolves cursor misalignment and timezone-awareness dropouts in geographically distributed deployments.
🛡️ Robust Security Path Normalization
Eliminated overzealous string prefix stripping in path resolutions inside SearchEngine and Zchema.
- Previously,
path.replace("resource.", "")acted globally and would corrupt legitimate nested relation paths (e.g.,project.resource.statusincorrectly mutated toproject.status). - Replaced with a strict, localized prefix-matching resolution to secure nested relationships without false positives during access checks.
⏱️ Native ISO-8601 Datetime Parsing
Simplified UTC datetime coercion in zcore/db/search.py by removing legacy .replace("Z", "+00:00") string manipulation workarounds. The coercion layer now fully relies on native, optimized Python 3.11+ datetime.fromisoformat() UTC suffix parsing out-of-the-box.
⚙️ Automated CI/CD & Project Governance
To prepare ZCore for robust open-source contributions and strict production deployments, we have fully automated our repository workflows:
- GitHub Actions Test Suite (CI): Deployed automated pull-request code quality gates using
ruff checklinting and thehatch testsuite (blocking merges unless all status checks are green). - Standardized Issue Templates: Added customized Bug Report and Feature Request templates to capture environmental diagnostics (DB engines, SQLAlchemy, and Redis versions).
- Automated Semantic Changelogs: Configured
.github/release.ymlto automatically categorize pull requests under semantic sections based on metadata tags. - Community Guidelines: Introduced formal
CONTRIBUTING.mdandSECURITY.mdfiles to clarify local setup steps and private vulnerability reporting workflows.
v0.1.0-Beta.5 🚀
Welcome to v0.1.0-beta.5 of the ZCore Framework! This release represents a significant architectural evolution, centering on Engineered Simplicity (KISS). We have deprecated complex, reflection-based configuration variables and brittle runtime hacks, replacing them with standard Object-Oriented patterns, native Pydantic V2 integrations, and cleaner dependency structures.
🚀 Core Features & Enhancements
🛡️ Unified Schema Security (Zchema)
We have completely overhaulled our data pruning and shielding mechanisms. Previously, data masking was handled globally in the web layer via a generic resource.* prefix, which was prone to namespace collisions.
- The
ZchemaClass: All schemas now inherit fromZchema(extendingBaseModel). - Domain-Specific Namespacing: You now define a class-level
__db_name__attribute (e.g.,__db_name__ = "user"). - 3-Tier Protection:
Zchemahandles security natively within Pydantic boundaries:- Dynamic Schemas (
?schema=true): Automatically prunes restricted fields from the exposed JSON Schema. - Input Filtering: Automatically strips restricted fields from incoming payloads, defending against Mass Assignment.
- Response Pruning: Automatically masks fields during serialization.
- Dynamic Schemas (
🚦 Template Method Service Hooks
To guarantee that business-critical pre_ and post_ lifecycle hooks and transaction boundaries are never skipped, we separated orchestration from execution.
- Custom Database Operations: Developers now override dedicated
on_create,on_update, andon_deletecallback hooks instead of overriding the publiccreate()orchestrator. - The orchestrator guarantees that validation, hooks, and transaction commits (
_safe_commit) are executed in the exact correct order.
🔗 FastAPI-Native Route Dependencies
We have conceptually renamed the routing security layer from "Permissions" to "Dependencies", matching FastAPI's design.
- Removed 8 static class variables (
DEFAULT_PERMISSIONS,POST_PERMISSIONS, etc.). - Introduced a single, elegant factory method:
get_route_dependencies(self, route_key: RouteKey, action: str) -> list[Any]. - Developers can now use standard Python inheritance and
super()to customize specific endpoints while maintaining default scopes for others.
📦 Robust Modular Monolith Imports
Resolved ModuleNotFoundError across nested modules (such as importing from shared/ within modules/identity/) using a 3-layer approach:
- CLI: Auto-injects the root into
PYTHONPATHduringzc run. - Runtime: Bootstraps
sys.pathdynamically at the top ofmain.py. - IDE: Generates
PYTHONPATH=.in.envto eliminate warning lines in VSCode/PyCharm.
⚠️ Breaking Changes & Migration Guide
1. Schema Base Class Update
You must replace BaseModel with Zchema and define __db_name__ on your schemas.
- Old:
from pydantic import BaseModel class UserResponse(BaseModel): email: str
- New:
from zcore import Zchema class UserResponse(Zchema): __db_name__ = "user" email: str
2. Router Security Configuration
Static permission variables have been deprecated. Move your custom security logic to the new factory method.
- Old:
class ProductRouter(BaseRouter): DEFAULT_PERMISSIONS = "AUTO" DELETE_PERMISSIONS = [AdminOnly()]
- New:
class ProductRouter(BaseRouter): def get_route_dependencies(self, route_key: RouteKey, action: str): if route_key == RouteKey.DELETE: return [AdminOnly()] return super().get_route_dependencies(route_key, action)
3. Service Overrides
If you previously overrode create, update, or delete directly, move that database logic to the corresponding on_ hook.
- Old:
async def create(self, schema: ProductCreate): return await self.repository.create(schema)
- New:
async def on_create(self, schema: ProductCreate) -> Product: return await self.repository.create(schema)
🐛 Bug Fixes & Refactoring
v0.1.0-beta.4 - DI Overhaul and Architecture Refinement
ZCore Framework — v0.1.0-beta.4
We are pleased to announce the release of v0.1.0-beta.4. This version introduces critical architectural refinements, improves ASGI/Async performance by eliminating thread-pool bottlenecks, and simplifies the developer experience (DX) for database-backed microservices.
🚀 Key Improvements & Features
1. Complete DI Overhaul & Web-Decoupled Scoping
The dependency injection (DI) layer has been restructured to strictly adhere to Clean Architecture:
- ASGI Middleware Session Scoping: The lifetime of the
AsyncSessiondatabase connection is now managed at the ASGI middleware level (ScopedDependencyMiddleware). This guarantees that a request-scoped database session is initialized and registered in the DI container before FastAPI resolves any routing dependency graphs, preventing race conditions. - Annotated Type Unpacking: The custom DI container (
_auto_wire) now supports python's nativetyping.Annotatedpatterns, gracefully extracting the core class definition (e.g., resolvingAsyncSessionfromAnnotated[AsyncSession, ...]). - High-Performance Async Injector: Modified
Injector.__call__to be asynchronous (async def). This allows FastAPI to evaluate dependencies directly on the main event loop, bypassing costlyanyio.to_thread.run_synccontext switches.
2. Base Query Hook & Extension Layer
Introduced structured hook methods in the base repository layer to allow granular control over queries:
_get_base_query(): A reusable hook returning the defaultSelectstatement (defaults toselect(self.model)). Custom repositories can override this to pre-select columns or include defaults._extend_query(): Enables developers to dynamically extend queries (e.g., chaining default criteria or global filters).- Integrated base query pipeline seamlessly with the
SearchEnginedynamic filter compiler.
3. One-Command Database Bootstrapping
- Running
zc init <project_name>through the ZCore CLI now automatically touches and creates the default SQLite database file (zcore_dev.db) on the filesystem, ensuring a zero-configuration developer onboarding experience.
4. Dependency Management
- Added
uvicornas a primary core dependency insidepyproject.tomlto guarantee the ZCore orchestration server commands (zc run) function correctly out of the box in all environments.
⚠️ Breaking Changes & Migration Guide
If you are migrating your test projects or showcase apps from beta.3 to beta.4, please review the following changes:
1. Clean Constructor Parameters (Decoupling Web Defaults)
You no longer need to write = Inject(...) default values or rely on SessionDep in repository/service constructors.
Before (v0.1.0-beta.3):
class UsersRepository(BaseRepository):
def __init__(self, db: SessionDep):
super().__init__(model=Users, db=db)
class UsersService(BaseService):
def __init__(self, repository: UsersRepository = Inject(UsersRepository)):
super().__init__(model=Users, repository=repository)After (v0.1.0-beta.4):
class UsersRepository(BaseRepository):
def __init__(self, db: AsyncSession): # Standard AsyncSession
super().__init__(model=Users, db=db)
class UsersService(BaseService):
def __init__(self, repository: UsersRepository): # Pure Python, no defaults
super().__init__(model=Users, repository=repository)2. Using Inject over Depends in Custom Web Deps
When writing custom FastAPI dependencies (e.g., get_current_user), ensure you use Inject(YourService) instead of Depends(YourService) so that the container handles recursive resolution:
async def get_current_user(
token: str = Depends(oauth2_scheme),
service: UsersService = Inject(UsersService) # Bypasses FastAPI default-resolver errors
) -> Users:
...🛠 How to Install / Upgrade
To fetch the latest beta package:
pip install --upgrade fastapi-zcore-framework