Skip to content

Releases: SyntaxArc/ArchiPy

4.12.0

20 Jun 07:32

Choose a tag to compare

Added

Adapters - MinIO

  • Object Existence Check - Added object_exists to MinioPort and MinioAdapter for lightweight presence checks without downloading object content.
    • Returns True when the object key exists and False when it does not.
    • Cached for five minutes via @ttl_cache_decorator to reduce repeated HEAD requests.
  • Batch Object Deletion - Added remove_objects for deleting multiple object keys in a single S3 DeleteObjects call.
    • Clears object-related caches after a successful batch delete.
  • Object Tag Operations - Added tag management methods for per-object metadata used with lifecycle-based expiration.
    • set_object_tags replaces all tags on an existing object.
    • get_object_tags returns the current tag mapping (empty dict when none are set).
    • remove_object_tags clears all tags from an object.
  • Upload-Time Tags - Extended put_object and put_object_stream with an optional tags: dict[str, str] | None parameter so tags can be applied at upload time.
  • Bucket Lifecycle / TTL - Added lifecycle configuration methods for automatic object expiration.
    • set_bucket_lifecycle accepts S3-format lifecycle rule dicts (MinioLifecycleRuleType).
    • get_bucket_lifecycle returns configured rules or an empty list when none are set.
    • delete_bucket_lifecycle removes all lifecycle rules from a bucket.
  • Object Versioning - Added bucket versioning and version-level delete support.
    • set_bucket_versioning enables or suspends versioning on a bucket.
    • get_bucket_versioning returns Enabled, Suspended, or an empty string when never configured.
    • list_object_versions lists version entries and delete markers with normalized metadata (MinioObjectVersionType).
    • remove_object_version permanently deletes a specific version by version_id.

Changed

Adapters - StarRocks

  • Type Ignore Cleanup - Removed redundant # type: ignore[invalid-assignment] comments from StarRocks SQLAlchemy compiler patches, keeping only the ty: ignore directives.

Documentation - MinIO

  • Tutorial Expansion - Extended docs/tutorials/adapters/minio.md with examples for object existence checks, batch deletion, object tags, and versioning workflows.
  • API Reference Clarification - Updated the MinIO adapter API reference to state that the concrete adapter wraps boto3 for S3-compatible storage.

Tests

Tests - MinIO Adapter

  • Tag Scenarios - Added BDD coverage for upload-time tags, setting tags on existing objects, and removing all tags.
  • Lifecycle Scenarios - Added scenarios for setting, verifying, and deleting bucket lifecycle rules.
  • Existence and Batch Delete - Added scenarios for object_exists before and after deletion, and for remove_objects batch cleanup.
  • Versioning Scenarios - Added end-to-end coverage for enabling versioning, uploading multiple versions, listing versions, and permanently deleting the oldest version.

Dependencies

  • Core dependencies - Updated base package pins in pyproject.toml.
    • pydantic-settings: >=2.14.1>=2.14.2
  • Optional extras - Updated optional adapter dependency pins.
    • dependency-injection: dependency-injector>=4.49.0>=4.49.1
    • minio: boto3>=1.43.32>=1.43.34
    • parsian-ipg / parsian-ipg-async: zeep>=4.3.2>=4.3.3
  • Dev group - Updated development tooling pins.
    • boto3-stubs: >=1.43.32>=1.43.34
    • ruff: >=0.15.17>=0.15.18
    • ty: >=0.0.50>=0.0.51
  • Docs group - Updated documentation tooling pins.
    • mkdocstrings-python: >=2.0.4>=2.0.5
  • Lockfile - Regenerated uv.lock to align with the updated pyproject.toml constraints.

Full Changelog: 4.11.1...4.12.0

4.11.1

18 Jun 17:39

Choose a tag to compare

Fixed

Dependencies - FastAPI Compatibility

  • FastAPI Upper Bound — Pinned fastapi to >=0.136,<0.137 to prevent breakage from FastAPI 0.137+
    which introduced incompatible changes with the current codebase.

Refactored

Tooling - Testing Execution Model

  • Removed Parallel Behave Settings — Deleted parallel = 8 and parallel_scheme = "multiprocessing" from
    [tool.behave] in pyproject.toml. Tests now run sequentially by default, aligning with the BDD convention
    of isolated scenarios.
  • Updated AGENTS.md — Refreshed quick commands and dev setup instructions.
  • Documentation Alignment — Brought docs/getting-started/project_structure.md in sync with current layout.

Full Changelog: 4.11.0...4.11.1

4.11.0

18 Jun 10:23

Choose a tag to compare

Added

Adapters - MinIO

  • Stream Upload and Download - Added put_object_stream and get_object_stream to MinioPort and
    MinioAdapter for in-memory and binary-stream object I/O without temporary files.
    • put_object_stream accepts bytes | BinaryIO, optional length, and content_type, and clears the
      list_objects cache after upload.
    • get_object_stream returns the full object body as bytes.

Models - Internet Payment Gateways

  • Parsian and Saman IPG DTOs - Extracted payment gateway request/response models into the domain layer.
    • Added archipy/models/dtos/parsian_ipg_dtos.py with payment, confirm, confirm-with-amount, and reverse DTOs.
    • Added archipy/models/dtos/saman_ipg_dtos.py with payment, verify, and reverse DTOs (including
      PaymentResponseDTO status validation).

Changed

Adapters - Internet Payment Gateways

  • DTO Import Refactor - Parsian and Saman Shaparak ports, adapters, and package __init__ modules now import
    DTOs from archipy.models.dtos instead of defining them inline in ports.py.

Chore - Tooling

  • Ruff Source Paths - Removed unused [tool.pytest.ini_options] from pyproject.toml, narrowed Ruff src to
    archipy and features, and updated per-file ignores for the base/sqlalchemy adapter path.
  • CI Lint Scope - Ruff check and format workflows now include features/steps and scripts alongside archipy.

Tests

Tests - MinIO Adapter

  • Stream Upload Scenarios - Extended features/minio_adapter.feature with outline scenarios for bytes and
    BinaryIO uploads followed by streaming download verification.
  • Flexible Upload Steps - Refactored MinIO step definitions to support stream-based uploads via
    put_object_stream.

Tests - FastAPI MinIO Upload

  • Large File End-to-End Uploads - Added features/fastapi_minio_upload.feature and step implementations covering
    50 MB, 75 MB, and 100 MB multipart uploads through a FastAPI endpoint backed by put_object_stream.

Chore

Test Containers

  • Image Pin Updates - Bumped test container images in .env.test.
    • Temporal: temporalio/temporal:1.5.1temporalio/temporal:1.7.2
    • Redis: redis:8.6.3-alpineredis:8.6.4-alpine
    • Keycloak: keycloak/keycloak:26.6.2keycloak/keycloak:26.6.3
    • ScyllaDB: scylladb/scylla:2026.1.2scylladb/scylla:2026.1.5

Dependencies

  • Optional extras - Updated optional adapter and dev dependencies.
    • fakeredis: fakeredis>=2.36.1fakeredis>=2.36.2
    • fastapi: fastapi[all]>=0.137.0fastapi[all]>=0.137.2
    • minio: boto3>=1.43.29boto3>=1.43.32
    • scylladb: scylla-driver>=3.29.10scylla-driver>=3.29.11
    • sentry: sentry-sdk>=2.62.0sentry-sdk>=2.63.0
    • sqlalchemy / sqlalchemy-async: sqlalchemy>=2.0.50sqlalchemy>=2.0.51
  • Dev group - Updated development tooling pins.
    • boto3-stubs: boto3-stubs>=1.43.14boto3-stubs>=1.43.32
    • ruff: ruff>=0.15.14ruff>=0.15.17
    • ty: ty>=0.0.39ty>=0.0.50
    • types-grpcio: types-grpcio>=1.0.0.20260518types-grpcio>=1.0.0.20260614
    • mkdocstrings-python: mkdocstrings-python>=2.0.3mkdocstrings-python>=2.0.4

Full Changelog: 4.10.2...4.11.0

4.10.2

15 Jun 12:24

Choose a tag to compare

Changed

Adapters - Internet Payment Gateways

  • HTTP Client Migration to httpx2 - Parsian and Saman async/sync adapters now use httpx2 for client construction
    and httpx2.RequestError handling in place of httpx.
    • AsyncParsianShaparakPaymentAdapter builds its Zeep async transport with httpx2.AsyncClient.
    • SamanShaparakPaymentAdapter, SamanNeoPgShaparakPaymentAdapter, AsyncSamanShaparakPaymentAdapter, and
      AsyncSamanNeoPgShaparakPaymentAdapter use httpx2.Client / httpx2.AsyncClient and catch
      httpx2.RequestError for token, verify, and reverse flows.

Adapters - StarRocks

  • Type-Hint Cleanup in Session Managers - StarRocks SQLAlchemy patch helpers in session_managers.py now type
    **kw: Any (with ANN401 noqa) instead of object, and monkeypatch assignments use combined
    # type: ignore[invalid-assignment] # ty: ignore[invalid-assignment] comments.

Fixed

Helpers - gRPC Interceptors

  • Optional Handler Return Types - BaseAsyncGrpcServerInterceptor.intercept_service and
    AsyncGrpcServerTraceInterceptor.intercept_service now declare grpc.RpcMethodHandler | None return and
    continuation types and early-return None when the continuation yields no handler, removing the prior
    cast(..., None) workaround.

Helpers - App Utils

  • Defensive Route Tag Access - FastAPIUtils.generate_unique_id_function reads route.tags via
    getattr(route, "tags", []) to tolerate routes without a tags attribute.

Tests

Tests - Metric Interceptor

  • httpx2 in Steps - features/steps/metric_interceptor_steps.py updated to use httpx2 to match the adapter
    migration.

Chore

Type Checking

  • changed ty Rule - Removed conflicting-argument-forms = "error" from the [tool.ty.rules] section in
    pyproject.toml.

Dependencies

  • Optional extras - Updated optional adapter extras.
    • elasticsearch / elasticsearch-async: elasticsearch>=9.4.0elasticsearch>=9.4.1
    • fakeredis: fakeredis>=2.35.1fakeredis>=2.36.1
    • fastapi: fastapi[all]>=0.136.3fastapi[all]>=0.137.0
    • grpc: grpcio>=1.80.0grpcio>=1.81.1, grpcio-health-checking>=1.80.0grpcio-health-checking>=1.81.1
    • kafka: confluent-kafka>=2.14.0confluent-kafka>=2.14.2
    • minio: boto3>=1.43.14boto3>=1.43.29
    • parsian-ipg: requests[socks]>=2.34.0requests[socks]>=2.34.2
    • parsian-ipg-async: httpx[socks]>=0.28.1httpx2[socks]>=2.4.0
    • redis: redis[hiredis]>=7.4.0redis[hiredis]>=8.0.0
    • saman-ipg: httpx[socks]>=0.28.1httpx2[socks]>=2.4.0
    • sentry: sentry-sdk>=2.60.0sentry-sdk>=2.62.0

Full Changelog: 4.10.1...4.10.2

4.10.1

31 May 17:10

Choose a tag to compare

Fixed

Helpers - App Utils

  • FastAPI APM Middleware Ordering - Reordered FastAPI app setup so setup_metric_interceptor runs before
    setup_elastic_apm.
    • Elastic APM must be the outermost middleware to capture incoming FastAPI requests; the previous order placed the
      metrics interceptor outside APM, causing handler spans to be missed.

Adapters - Redis

  • Async Cluster Node Import - AsyncRedisAdapter._create_cluster_client now imports ClusterNode from
    redis.asyncio.cluster instead of the synchronous redis.cluster, matching the async cluster client's expected node
    type.

Changed

Adapters - Redis

  • Concrete Type Hints in Place of Generic Aliases - Replaced the generic RedisResponseType, RedisKeyType,
    RedisExpiryType, RedisAbsExpiryType, RedisIntegerResponseType, RedisListResponseType, RedisSetResponseType,
    RedisPatternType, and RedisSetType aliases with concrete return and parameter types across RedisAdapter,
    AsyncRedisAdapter, RedisPort, and AsyncRedisPort.
    • Cluster methods now declare specific shapes (e.g., cluster_info() -> dict[str, str] | None,
      cluster_slots() -> list[Any] | None, cluster_get_keys_in_slot(...) -> list[bytes | str] | None).
    • TTL and counter methods now return int directly (e.g., pttl, incrby).
    • Expiry parameters use int | timedelta and int | datetime for relative and absolute forms respectively.
    • Added from __future__ import annotations to archipy/adapters/redis/adapters.py and
      archipy/adapters/redis/ports.py and imported datetime / timedelta for the new typing.
    • RedisScoreCastType is retained; all other aliases are removed from archipy.adapters.redis.ports.

Adapters - Redis Mocks

  • Drop Removed Type Alias - AsyncRedisMock._create_async_wrapper now types the wrapped method as
    Callable[..., Awaitable[Any]] after RedisResponseType was removed from archipy.adapters.redis.ports.

Helpers - Rate Limit

  • Concrete Return Type for _check - FastAPIRestRateLimitHandler._check now returns int instead of the removed
    RedisResponseType alias and the TYPE_CHECKING import is dropped.

Tests

Tests - Keycloak

  • Audience Mapper for Token Introspection - Replaced the brittle realm-management:token-introspection role
    assignment in _step_create_client_and_update_adapter with a new _ensure_introspection_audience_mapper helper that
    installs an oidc-audience-mapper on freshly created clients.
    • Uses add_mapper_to_client / a_add_mapper_to_client to ensure the introspecting client appears in the access
      token aud claim, which Keycloak 26.6.2+ requires for successful introspection.
    • Re-initializes the admin adapter against the target realm before mutating the client and skips creation when a
      mapper with the same name already exists.

Chore

Test Containers

  • Image Bumps - Updated the test container images used by BDD scenarios in .env.test.
    • REDIS__IMAGE: redis:8.6.2-alpineredis:8.6.3-alpine
    • POSTGRES__IMAGE: postgres:18.3-alpinepostgres:18.4-alpine
    • KEYCLOAK__IMAGE: keycloak/keycloak:26.6.1keycloak/keycloak:26.6.2
    • KAFKA__IMAGE: apache/kafka:4.2.0apache/kafka:4.3.0

Dependencies

  • Runtime dependencies - Updated version pins for production dependencies.
    • requests: >=2.34.0>=2.34.2
    • jdatetime: >=5.2.0>=5.3.0
  • Optional extras - Updated optional adapter extras.
    • cache: cachetools>=7.1.1cachetools>=7.1.4
    • elastic-apm: elastic-apm>=6.25.0elastic-apm>=6.26.1
    • fastapi: fastapi[all]>=0.136.1fastapi[all]>=0.136.3
    • jwt: pyjwt>=2.12.1pyjwt>=2.13.0
    • keycloak: cachetools>=7.1.1cachetools>=7.1.4
    • minio: boto3>=1.43.6boto3>=1.43.14, cachetools>=7.1.1cachetools>=7.1.4
    • scylladb: cachetools>=7.1.1cachetools>=7.1.4
    • sqlalchemy / sqlalchemy-async: sqlalchemy>=2.0.49sqlalchemy>=2.0.50
    • starrocks: pymysql>=1.1.3pymysql>=1.2.0
  • Dev dependencies - Updated development tooling and typing stubs.
    • boto3-stubs: >=1.43.6>=1.43.14
    • ruff: >=0.15.12>=0.15.14
    • ty: >=0.0.35>=0.0.39
    • types-cachetools: >=7.0.0.20260503>=7.0.0.20260518
    • types-grpcio: >=1.0.0.20260508>=1.0.0.20260518
    • types-protobuf: >=7.34.1.20260508>=7.34.1.20260518
    • types-pymysql: >=1.1.0.20260508>=1.1.0.20260518
    • types-regex: >=2026.5.9.20260510>=2026.5.9.20260518
    • types-requests: >=2.33.0.20260513>=2.33.0.20260518

Full Changelog: 4.10.0...4.10.1

4.10.0

18 May 11:50

Choose a tag to compare

Added

Adapters - Keycloak

  • Batch UMA Permission Checks - Added check_permissions_batch to KeycloakPort and AsyncKeycloakPort (and their
    adapter implementations) for evaluating multiple (resource, scope) pairs in a single UMA call.
    • Returns a frozenset[tuple[str, str]] containing only the granted pairs from the requested set.
    • Sync implementation wraps KeycloakOpenID.uma_permissions; async implementation wraps a_uma_permissions.
    • Cached with ttl_cache_decorator(ttl_seconds=30, maxsize=200) (sync) and alru_cache(ttl=30, maxsize=200) (
      async) to avoid redundant Keycloak round-trips.
    • Existing check_permissions now documents check_permissions_batch as the preferred entry point when multiple
      pairs must be checked per request.

Changed

Adapters - Keycloak

  • get_userinfo Trusts UserInfo Endpoint - Removed the local validate_token precheck from both sync and async
    get_userinfo implementations.
    • The Keycloak UserInfo endpoint already validates the token server-side, so the extra local validation was
      redundant and an unnecessary network round-trip.
    • Dropped the now-unused InvalidTokenError import from archipy/adapters/keycloak/adapters.py.
    • Docstrings updated to call out that UserInfo handles validation.

Helpers - Keycloak Utils

  • Shared Adapter Instances - KeycloakUtils._get_keycloak_adapter and _get_async_keycloak_adapter now delegate to
    process-wide @cached factories (_shared_sync_adapter, _shared_async_adapter) instead of constructing a new
    adapter per decorator invocation.
  • Authorization Pipeline Consolidation - Extracted the gRPC auth-decorator authorization flow into reusable helpers
    and used the new batch permission API throughout.
    • Added _authorize_sync / _authorize_async helpers that validate the token, fetch token info, retrieve UserInfo,
      perform optional resource-ownership checks, enforce role requirements, and run batch permission checks.
    • Added _extract_roles, _check_resource_access, and _build_auth_context helpers to centralize role
      aggregation (realm + client), ownership/admin checks, and AuthContext construction.
    • Role enforcement now uses local set operations against UserInfo claims (issuperset / isdisjoint) rather than
      issuing separate has_all_roles / has_any_of_roles calls.
    • Permission enforcement uses check_permissions_batch and surfaces missing pairs via the missing_permissions
      field in PermissionDeniedError.additional_data.
    • BaseError instances raised inside async wrappers are re-raised after the optional gRPC abort, preventing them
      from being wrapped into InternalError.

Helpers - Decorators

  • Sharper Tracing Decorator Generics - capture_transaction, capture_span, async_capture_transaction, and
    async_capture_span now bind their generic F to local _Function / _AsyncFunction Protocol classes that
    require a __name__ attribute, replacing the looser Callable[..., Any] bound and giving callers better type
    narrowing on decorated functions.

Full Changelog: 4.9.3...4.10.0

4.9.3

13 May 13:52

Choose a tag to compare

Changed

Helpers - Rate Limit

  • Lazy Redis client initialization - The FastAPIRestRateLimitHandler now lazily initializes its Redis client to avoid import cycles and enable TYPE_CHECKING imports.
    • Added _create_redis_client() static method that imports AsyncRedisAdapter at call time with # noqa: PLC0415.
    • Changed from eager self.redis_client = AsyncRedisAdapter() in __init__ to lazy self._redis_client assignment.
    • Renamed redis_client to _redis_client to indicate private API.

Dependencies

  • Core dependencies - Updated version pins for several production dependencies.
    • pydantic: >=2.13.3>=2.13.4
    • pydantic-settings: >=2.14.0>=2.14.1
    • requests: >=2.33.1>=2.34.0
    • elasticsearch: >=9.3.0>=9.4.0
    • boto3 (minio group): >=1.43.2>=1.43.6
    • scylla-driver: >=3.29.9>=3.29.10
    • sentry-sdk: >=2.58.0>=2.60.0
  • Dev dependencies - Updated development and typing stubs.
    • boto3-stubs: >=1.43.2>=1.43.6
    • ty: >=0.0.34>=0.0.35
    • types-grpcio: >=1.0.0.20260408>=1.0.0.20260508
    • types-protobuf: >=7.34.1.20260503>=7.34.1.20260508
    • types-pymysql: >=1.1.0.20260408>=1.1.0.20260508
    • types-regex: >=2026.4.4.20260408>=2026.5.9.20260510
    • types-requests: >=2.33.0.20260503>=2.33.0.20260513
    • pymdown-extensions (docs group): >=10.21.2>=10.21.3

Tests

Test Configuration

  • Elasticsearch test container version - Updated ELASTIC__IMAGE from elastic/elasticsearch:9.4.0 to elastic/elasticsearch:9.4.1 in .env.test.

Full Changelog: 4.9.2...4.9.3

4.9.2

12 May 13:30

Choose a tag to compare

Changed

Configs - GrpcConfig

  • Thread worker count resolution - When THREAD_WORKER_COUNT is omitted, it is now assigned during model validation by the after-model resolve_thread_worker_count validator to THREAD_PER_CPU_CORE * (os.cpu_count() or 1).
    • Removed the unused resolved_thread_worker_count property.
    • gRPC server helpers now pass a concrete max_workers into ThreadPoolExecutor instead of None.
  • Default server and stub channel options - Refreshed SERVER_OPTIONS_CONFIG_LIST and STUB_OPTIONS_CONFIG_LIST defaults for clearer limits, keepalive alignment, and client resilience.
    • grpc.max_metadata_size default 16KB on both server and stub presets.
    • Server keepalive and HTTP/2 ping intervals aligned with client expectations to reduce ENHANCE_YOUR_CALM / GOAWAY issues; connection idle (10m) and max age (30m) with a short grace drain.
    • Stub keepalive at 5 minutes with a 20s timeout; grpc.service_config default timeout 10s, wait-for-ready, retry policy, and a retryThrottling block.

Fixed

Adapters - Saman Shaparak Payment

  • Missing TransactionDetail Handling - Fixed graceful handling of missing TransactionDetail in Saman payment adapters.
    • Changed from .get("TransactionDetail", {}) to .get("TransactionDetail") or {}
    • Prevents TypeError when API returns null instead of missing key

Full Changelog: 4.9.1...4.9.2

4.9.1

12 May 12:32

Choose a tag to compare

Fixed

Adapters - ScyllaDB

  • Async Callback Fix - Fixed async error handling in ScyllaDB adapter by replacing run_in_executor with callback-based approach.
    • Uses add_callbacks to bridge cassandra-driver's ResponseFuture to asyncio.Future
    • Avoids ThreadPoolExecutor bottleneck under high concurrency
    • Properly constructs ResultSet from raw rows in the success callback

Dependencies

Adapters - ScyllaDB

  • ScyllaDB and Driver Upgrades - Updated ScyllaDB test container and Python driver to latest versions.
    • Upgraded ScyllaDB Docker image to 2026.1.2
    • Updated scylla-driver to 3.29.10

Chore - Dependencies

  • Dependency Updates - Upgraded multiple Python packages for improved compatibility and security.
    • Updated idna to 3.14
    • Updated python-multipart to 0.0.28
    • Updated requests to 2.34.0

Helpers - Tracing

  • Elastic APM Initialization - Enhanced Elastic APM client initialization by excluding IS_ENABLED from model dump.
    • Prevents potential configuration leaks in APM agent initialization

Full Changelog: 4.9.0...4.9.1

4.9.0

09 May 16:43

Choose a tag to compare

Added

Adapters - Kafka

  • Null Commit and Batch Consume Support - Added support for null commits and batch consume operations in Kafka adapters.
    • Implemented batch consume capability for processing multiple messages in a single operation
    • Added null commit support for manual offset management scenarios
    • Comprehensive BDD test coverage for the new functionality

Full Changelog: 4.8.1...4.9.0