Skip to content

Conversation

@KaQuMiQ
Copy link
Collaborator

@KaQuMiQ KaQuMiQ commented Dec 4, 2025

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Walkthrough

Version bumped 0.94.1 → 0.95.0 and dependency haiway updated to ~=0.40.0 in pyproject.toml; added an optional rabbitmq extra. Added src/draive/rabbitmq/init.py re-exporting haiway.rabbitmq symbols. Introduced SQS support: AWSSQSMixin (publish/consume/ack, queue URL resolution, receive/ack flows, error translation), AWSSQS State with typed queue accessor, and AWSSQSQueueAccessing protocol. Integrated SQS into AWSAPI and AWS client (new _sqs_client, _prepare_sqs_client, AWS inherits AWSSQSMixin and returns a list of feature states). Added S3 metadata sanitizers and minor test string literal changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files/areas requiring extra attention:
    • src/draive/aws/sqs.py — async generator semantics, long-polling/receive logic, attribute formatting, error translation mapping and edge cases.
    • src/draive/aws/state.py and src/draive/aws/types.py — overloads, protocol correctness, and typing/runtime_checkable behavior.
    • src/draive/aws/api.py and src/draive/aws/client.py — new slot/attribute, SQS client initialization, and changed aenter return shape (composed feature states).
    • src/draive/aws/s3.py — metadata sanitization, UTF‑8-safe truncation, and correctness against S3 limits.
    • pyproject.toml and src/draive/rabbitmq/init.py — dependency/optional-dependency changes and public API surface.

Possibly related PRs

  • Add AWS S3 ResourcesRepository #475 — Prior AWS integration changes touching api.py, client.py, s3.py, and types.py that relate directly to the AWS/SQS and S3 modifications in this PR.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.89% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess relatedness to the changeset. Add a description explaining the MessageQueue feature, its purpose, integration points, and any relevant context or design decisions.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add MessageQueue feature' accurately summarizes the main change: integrating MessageQueue/SQS support into the draive library via new modules and mixins.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/mq

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68e696f and 6b57814.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • pyproject.toml (3 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • src/draive/rabbitmq/__init__.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/rabbitmq/__init__.py
🧠 Learnings (2)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test (macos-latest, 3.13)
🔇 Additional comments (3)
pyproject.toml (3)

8-8: Version bump to 0.95.0 matches scope of added feature

Aligning the version with the new RabbitMQ integration and dependency updates makes sense; no issues from a packaging/semver perspective.


27-27: Confirm compatibility with haiway~=0.40.0

Bumping haiway to ~0.40.0 is appropriate for exposing haiway.rabbitmq, but it’s worth double‑checking the 0.40.0 changelog for any breaking changes affecting existing integrations in draive.

Please verify against the haiway 0.40.0 release notes and ensure the test suite passes with this version, especially around existing haiway-based integrations (e.g., httpx, postgres).


55-55: rabbitmq extra group matches existing integration patterns; verify haiway[rabbitmq] extra

Defining rabbitmq = ["haiway[rabbitmq]", "pika"] is consistent with other extras (e.g., haiway[httpx], haiway[postgres]) and cleanly gates MQ support behind an optional group.

Please confirm that:

  • haiway indeed exposes a rabbitmq extra with the expected dependencies, and
  • pika is the correct client lib and version range for haiway.rabbitmq usage in this project.
    If needed, consult the haiway documentation for the recommended extra and client library versions.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
src/draive/rabbitmq/__init__.py (1)

1-7: Clean re-export pattern for optional RabbitMQ integration.

The thin wrapper correctly re-exports the haiway.rabbitmq symbols with an explicit __all__ tuple. This aligns well with the new rabbitmq optional dependency group in pyproject.toml.

The past review comment about wiring these exports through src/draive/__init__.py remains relevant if these symbols should be part of the top-level public API.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b57814 and 0d38a44.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (3 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • src/draive/aws/api.py
  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/client.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/api.py
  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/client.py
🧠 Learnings (2)
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
🧬 Code graph analysis (3)
src/draive/aws/sqs.py (2)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
src/draive/aws/client.py (3)
src/draive/aws/sqs.py (2)
  • AWSSQSMixin (28-140)
  • _queue_access (29-62)
src/draive/aws/state.py (1)
  • AWSSQS (12-86)
src/draive/aws/api.py (1)
  • _prepare_sqs_client (65-68)
🔇 Additional comments (10)
src/draive/aws/types.py (1)

85-93: Protocol definition is well-structured.

The AWSSQSQueueAccessing protocol correctly uses:

  • @runtime_checkable for structural typing at boundaries
  • PEP 695 generic method syntax [Content] (appropriate for Python 3.13+)
  • **extra: Any at the protocol boundary (acceptable per guidelines)

The async callable returning AbstractAsyncContextManager[MQQueue[Content]] aligns with the implementation in AWSSQSMixin._queue_access.

pyproject.toml (2)

55-55: RabbitMQ optional dependency group looks correct.

The group includes both haiway[rabbitmq] for the RabbitMQ integration and pika as the underlying AMQP client. This follows the same pattern as other optional groups (e.g., postgres, httpx).


27-27: Verify that haiway 0.40.0 exports MQQueue, MQMessage, and BasicObject.

The version bump to haiway~=0.40.0 is necessary for MQQueue, MQMessage, and BasicObject exports used in the AWS SQS and RabbitMQ integrations. These symbols are imported directly from haiway in src/draive/aws/sqs.py, src/draive/aws/types.py, and src/draive/aws/state.py, and RabbitMQ-specific exports are imported from haiway.rabbitmq in src/draive/rabbitmq/__init__.py. Confirm this version introduces these message queue abstractions.

src/draive/aws/api.py (1)

64-68: SQS client preparer follows the established pattern.

The @asynchronous decorator correctly offloads the blocking boto3 client creation to a thread pool, consistent with _prepare_s3_client.

src/draive/aws/sqs.py (1)

96-103: Closure correctly captures receipt_handle via default argument.

The default argument pattern receipt_handle: str = receipt_handle properly binds the current iteration's value, avoiding the classic late-binding closure pitfall in loops.

src/draive/aws/state.py (3)

1-9: LGTM!

Imports are clean and follow the coding guideline to import from draive directly where applicable. The __all__ export is properly declared.


13-32: LGTM!

The overloaded signatures correctly support both classmethod and instance method invocation patterns with proper generic type parameters.


79-86: LGTM!

The implementation correctly delegates to the injected queue_accessing callable, and the attribute declaration follows the State pattern for required dependencies.

src/draive/aws/client.py (2)

9-10: LGTM!

The import additions and mixin inheritance are correctly structured. The MRO order places the mixins before the base AWSAPI class, which is the proper pattern for mixin composition.

Also applies to: 17-20


47-60: LGTM!

The typing correctly uses Collection (abstract) over concrete types, and the empty tuple default maintains immutability. The union type properly expresses the supported feature types.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (6)
src/draive/rabbitmq/__init__.py (1)

1-7: Clean re-export shim for RabbitMQ integration.

The pattern correctly re-exports haiway.rabbitmq symbols under the draive.rabbitmq namespace, consistent with other optional integration modules. The __all__ tuple properly constrains the public surface.

Note: The suggestion to wire these symbols through src/draive/__init__.py was already raised in a previous review.

src/draive/aws/sqs.py (3)

25-62: Add a NumPy-style docstring to AWSSQSMixin and clarify queue semantics.

AWSSQSMixin is exported via __all__ and forms part of the public AWS surface, but it has no class-level docstring. Per project guidelines, it should have a NumPy-style docstring describing:

  • Purpose: SQS-backed MQ queue access helpers built on AWSAPI.
  • Parameters / expectations: that it is intended to be mixed into an AWSAPI subclass, and what queue represents (SQS queue URL vs logical name).
  • High-level behavior of _queue_access / the returned MQQueue (publish uses content_encoder, consume uses content_decoder, acknowledgements delete messages, rejects rely on retries).

Also, _queue_access accepts **extra but currently ignores it entirely. Either thread these options through to publish_message/consume_messages or drop **extra here and from the protocol to avoid misleading callers.


117-128: Optional: Make long‑polling parameters configurable or document the fixed defaults.

MaxNumberOfMessages=1 and WaitTimeSeconds=20 are hardcoded. That’s reasonable as a default, but some consumers may need different batch sizes or wait times. Consider accepting these as optional parameters (threaded from queue(..., **extra)) or explicitly documenting the fixed behavior in the public AWSSQS docs.


143-154: Attribute formatting is correct; consider explicit bool handling.

_format_attribute_value correctly maps strings to "String" and numbers to "Number" per SQS semantics, and raises on unsupported types. Because bool is a subclass of int, it will currently be treated as a "Number" with StringValue "True"/"False", which is odd for numeric attributes. If you expect boolean attributes, consider adding an explicit case bool() as value: branch before the numeric case (or explicitly rejecting bools) to avoid surprising behavior.

src/draive/aws/client.py (1)

62-83: Feature binding in __aenter__ is correct; consider expanding the docstring.

The new __aenter__ correctly:

  • Lazily prepares the S3 client when ResourcesRepository is requested.
  • Lazily prepares the SQS client when AWSSQS is requested.
  • Returns a list of State instances for requested features.

To better guide callers, the docstring could briefly explain that the returned Iterable[State] is meant to be bound into a context (e.g., via ctx.scope(features)) and that the list may contain ResourcesRepository, AWSSQS, or both, in an unspecified order.

src/draive/aws/state.py (1)

43-78: Fix content_encoder docstring type and align queue description with SQS usage.

The queue method signature uses content_encoder: Callable[[Content], str], but the docstring still documents it as Callable[[Content], BasicObject], which is misleading.

Apply the following adjustment (as previously suggested) so docs match the actual type:

-        content_encoder : Callable[[Content], BasicObject]
-            Callable that transforms typed payloads into broker-serializable objects before publish.
+        content_encoder : Callable[[Content], str]
+            Callable that transforms typed payloads into strings before publish.

Also, the parameter doc currently says:

queue : str — Name of the queue to access on the broker.

Given that the underlying implementation in AWSSQSMixin passes queue straight into QueueUrl=... for boto3, either:

  • Clarify here that queue must be the full SQS QueueUrl, or
  • Change the impl to resolve a logical queue name into a URL before calling SQS.

Right now the example (AWSSQS.queue("events", ...)) suggests a logical name, which will not work with the current boto3 usage.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d38a44 and a33eaa7.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (3 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • src/draive/aws/api.py
  • src/draive/aws/types.py
  • src/draive/aws/state.py
  • tests/test_tags_replacement.py
  • src/draive/aws/sqs.py
  • tests/test_tags_extraction.py
  • src/draive/aws/client.py
  • src/draive/rabbitmq/__init__.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/api.py
  • src/draive/aws/types.py
  • src/draive/aws/state.py
  • src/draive/aws/sqs.py
  • src/draive/aws/client.py
  • src/draive/rabbitmq/__init__.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_replacement.py
  • tests/test_tags_extraction.py
🧠 Learnings (3)
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/sqs.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
🧬 Code graph analysis (6)
src/draive/aws/types.py (1)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/sqs.py (2)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
tests/test_tags_extraction.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/client.py (3)
src/draive/aws/sqs.py (2)
  • AWSSQSMixin (28-140)
  • _queue_access (29-62)
src/draive/aws/state.py (1)
  • AWSSQS (12-86)
src/draive/aws/api.py (2)
  • _prepare_s3_client (59-62)
  • _prepare_sqs_client (65-68)
🔇 Additional comments (10)
tests/test_tags_extraction.py (1)

465-476: LGTM!

Minor string quote style normalization. The test logic remains correct and continues to verify that malformed self-closing tags (missing quotes around attribute values) are properly skipped.

tests/test_tags_replacement.py (1)

678-681: LGTM!

Minor string quote style normalization consistent with the rest of the test suite.

pyproject.toml (3)

8-8: LGTM!

Version bump to 0.95.0 is appropriate for the new MessageQueue feature additions (AWS SQS and RabbitMQ support).


55-55: LGTM!

The new rabbitmq optional dependency group correctly bundles haiway[rabbitmq] (for the RabbitMQ integration) and pika (the underlying AMQP client library).


27-27: haiway 0.40.0 is available on PyPI.

The version is published and stable. The dependency specification haiway~=0.40.0 correctly allows patch version updates within the 0.40.x series. No issues found.

src/draive/aws/types.py (2)

1-5: LGTM!

Imports are appropriate for the new protocol definition. Uses Protocol and runtime_checkable for structural typing at async boundaries, consistent with coding guidelines.


85-93: Well-defined protocol for SQS queue access.

The AWSSQSQueueAccessing protocol correctly:

  • Uses @runtime_checkable for async client boundaries
  • Employs PEP 695 generic syntax ([Content]) on the method, appropriate for Python 3.13+
  • Returns AbstractAsyncContextManager[MQQueue[Content]] for structured async resource management
  • Accepts **extra: Any for forwarding provider-specific options (acceptable at third-party boundaries)

The signature aligns with the usage in src/draive/aws/state.py where queue_accessing delegates to this callable.

src/draive/aws/api.py (1)

16-20: SQS client wiring looks consistent and type-safe at the boundary.

Adding _sqs_client to __slots__, annotating it as Any, and introducing _prepare_sqs_client() mirrors the existing S3 setup and keeps the boto3 interaction confined to a clearly typed boundary. No issues from a typing or async-usage perspective.

Also applies to: 55-57, 58-68

src/draive/aws/sqs.py (1)

83-115: Consumption loop and message decoding behavior look correct.

The consume loop respects cancellation via ctx.check_cancellation(), uses long-polling via _receive, and yields MQMessage instances with proper acknowledge callbacks. Passing message["Body"] into decoder aligns with the Callable[[BasicObject], Content] contract and avoids the earlier “full envelope” issue. The no-op reject relying on SQS retry semantics is an acceptable default for now.

src/draive/aws/client.py (1)

7-21: SQS feature integration into AWS looks structurally sound.

Importing AWSSQSMixin/AWSSQS, extending AWS with the mixin, and widening the features type to Collection[type[ResourcesRepository | AWSSQS]] align with the new SQS state. Using an empty tuple as the default feature set avoids implicit S3/SQS initialization and keeps typing strict. No functional or typing issues here.

Also applies to: 42-61

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (4)
src/draive/rabbitmq/__init__.py (1)

1-7: Thin RabbitMQ shim looks good; ensure central top-level export stays in sync.

The re-export and __all__ are clean and match other integration shims. If these are intended public symbols, also re-export them from src/draive/__init__.py (e.g. from .rabbitmq import RabbitMQ, RabbitMQClient, RabbitMQException) so users can rely on draive.RabbitMQ* as the single public entrypoint.

src/draive/aws/client.py (1)

62-82: Document how callers should use the returned feature states from __aenter__.

__aenter__ correctly prepares S3/SQS clients and returns a list of State instances (e.g. ResourcesRepository, AWSSQS), but the docstring doesn’t explain how that iterable is meant to be used with context scoping (e.g. ctx.scope(features)).

Consider expanding the docstring with a brief usage note:

-    async def __aenter__(self) -> Iterable[State]:
-        """Prepare the AWS client and bind selected features to context."""
+    async def __aenter__(self) -> Iterable[State]:
+        """
+        Prepare the AWS client and bind selected features to context.
+
+        Returns
+        -------
+        Iterable[State]
+            Feature state instances (for example ``ResourcesRepository``,
+            ``AWSSQS``) ready to be passed into a context scope, e.g.
+            ``async with AWS(..., features={ResourcesRepository, AWSSQS}) as features:``
+            ``    async with ctx.scope(features): ...``
+        """
src/draive/aws/state.py (2)

12-12: Add a class‑level NumPy‑style docstring for AWSSQS.

AWSSQS is exported via __all__ and is the primary public state wrapper for SQS queues, but the class itself has no docstring. Per the project guidelines, it should describe its role (binding SQS access into state), its main API (queue and injected queue_accessing), and high‑level usage.

For example:

-class AWSSQS(State):
+class AWSSQS(State):
+    """
+    State wrapper providing typed access to AWS SQS queues.
+
+    Parameters
+    ----------
+    queue_accessing : AWSSQSQueueAccessing
+        Callable used internally to acquire queue‑scoped async context
+        managers. This is typically injected by the AWS client.
+
+    Notes
+    -----
+    The primary public API is :meth:`queue`, which returns an async context
+    manager yielding an :class:`MQQueue` bound to a specific SQS queue and
+    content encoder/decoder.
+    """

Also applies to: 86-86


35-42: Fix content_encoder docstring type and clarify queue/**extra semantics.

The implementation and overloads use content_encoder: Callable[[Content], str], but the docstring still documents Callable[[Content], BasicObject], which is misleading. Also, the doc says queue is the “Name of the queue”, and that **extra is forwarded to the underlying accessor, but in the current SQS mixin, queue is passed straight as QueueUrl and **extra is effectively ignored.

I’d recommend:

  1. Align the encoder docs with the actual type:
-        content_encoder : Callable[[Content], BasicObject]
-            Callable that transforms typed payloads into broker-serializable objects before publish.
+        content_encoder : Callable[[Content], str]
+            Callable that transforms typed payloads into the message body string
+            sent to SQS.
  1. Clarify the meaning of queue and behaviour of **extra to match the implementation you want:
  • If queue is intended to be a logical name (as in the "events" example), the SQS layer should resolve it via get_queue_url before calling send_message / receive_message / delete_message.
  • If you prefer to treat queue as the full SQS QueueUrl, update this docstring (and the example) to say so explicitly and mention that passing a bare name will not work.
  1. Either:
  • Plumb **extra through to AWSSQSMixin._queue_access / _publish / _receive so callers can influence SQS options, or
  • Remove/undocument it here if you intentionally do not support extra options yet.

Right now the contract promises more than the implementation delivers, which will surprise callers.

Also applies to: 46-56

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a33eaa7 and 6e47eaa.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (3 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • tests/test_tags_replacement.py
  • src/draive/aws/types.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/client.py
  • src/draive/aws/state.py
  • src/draive/aws/sqs.py
  • src/draive/aws/api.py
  • tests/test_tags_extraction.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_replacement.py
  • tests/test_tags_extraction.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/types.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/client.py
  • src/draive/aws/state.py
  • src/draive/aws/sqs.py
  • src/draive/aws/api.py
🧠 Learnings (3)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/state.py
  • src/draive/aws/sqs.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
🧬 Code graph analysis (6)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/types.py (1)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/client.py (3)
src/draive/aws/sqs.py (2)
  • AWSSQSMixin (28-140)
  • _queue_access (29-62)
src/draive/aws/state.py (1)
  • AWSSQS (12-86)
src/draive/aws/api.py (2)
  • _prepare_s3_client (59-62)
  • _prepare_sqs_client (65-68)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
src/draive/aws/sqs.py (2)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
tests/test_tags_extraction.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
🔇 Additional comments (3)
tests/test_tags_extraction.py (1)

466-476: LGTM!

String literal delimiter standardization from single to double quotes. No functional changes.

tests/test_tags_replacement.py (1)

679-681: LGTM!

String literal delimiter standardization consistent with changes in test_tags_extraction.py. No functional impact.

pyproject.toml (1)

8-8: Version/dependency bump and rabbitmq extra wiring are consistent; no action required.

The move to haiway~=0.40.0 and the rabbitmq = ["haiway[rabbitmq]", "pika"] extra are correctly wired. The symbols MQQueue, MQMessage, BasicObject, and asynchronous are actively used throughout the codebase (e.g., in src/draive/aws/sqs.py, src/draive/aws/state.py), and RabbitMQ imports are present in src/draive/rabbitmq/__init__.py, confirming the dependency is compatible with the new AWS/RabbitMQ features.

@KaQuMiQ KaQuMiQ force-pushed the feature/mq branch 2 times, most recently from 3f200d4 to 1bf16bb Compare December 5, 2025 13:23
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/draive/aws/s3.py (1)

229-245: Centralized S3 metadata sanitization is solid; consider tightening value typing

Moving metadata normalization into _sanitize_metadata_value / _sanitize_metadata and wiring _upload through them makes the S3 boundary much clearer and safer (ASCII-only, whitespace/control stripping, byte-length guard).

Given the current usages, you could narrow

def _sanitize_metadata_value(value: Any) -> str:

to something like

def _sanitize_metadata_value(value: str | BasicValue) -> str:

to keep Any reserved for true third‑party boundaries while preserving behavior.

Also applies to: 255-299

♻️ Duplicate comments (6)
src/draive/rabbitmq/__init__.py (1)

1-7: Thin RabbitMQ re-export looks good; consider wiring through draive.__init__ as well

The direct re-export of RabbitMQ, RabbitMQClient, and RabbitMQException from haiway.rabbitmq with an explicit __all__ matches the existing integration-shim style and is clear.

If these are intended as part of the public surface, consider also re-exporting them from src/draive/__init__.py (e.g., from .rabbitmq import RabbitMQ, RabbitMQClient, RabbitMQException) so users can rely on draive.RabbitMQ* alongside the other top-level integrations.

src/draive/aws/types.py (1)

1-6: Public AWSSQSQueueAccessing protocol looks correct; add a NumPy-style docstring

The protocol shape (__call__ async, returning an AbstractAsyncContextManager[MQQueue[Content]] with encoder/decoder callables) matches how AWSSQS.queue and the SQS mixin use it, so the typing boundary looks good.

Since AWSSQSQueueAccessing is exported via __all__ and is a public boundary, it should carry a short NumPy-style docstring documenting the queue, content_encoder, and content_decoder parameters and the returned async context manager (an MQQueue[Content] accessor), similar in spirit to the AWSSQS.queue docstring.

Adding that docstring will keep the public API self-describing and consistent with other exported protocols.

Also applies to: 11-12, 85-93

src/draive/aws/state.py (1)

12-86: Align AWSSQS documentation with its types (class docstring + content_encoder type)

The AWSSQS state wrapper and its generic queue statemethod are well-typed and delegate cleanly to queue_accessing, but there are two documentation gaps:

  1. Missing class-level docstring for AWSSQS

    Since AWSSQS is exported via __all__ and is a public state surface, add a short NumPy-style class docstring describing it as a stateful accessor for AWS SQS queues, noting that:

    • The main entrypoint is the queue statemethod.
    • queue_accessing: AWSSQSQueueAccessing is injected by the AWS client and performs the actual access/teardown.
    • Typical usage mirrors the example already shown in the queue method docstring.
  2. Docstring type mismatch for content_encoder

    The queue docstring currently documents:

    content_encoder : Callable[[Content], BasicObject]
        Callable that transforms typed payloads into broker-serializable objects before publish.
    

    but the actual parameter type is Callable[[Content], str]. To avoid confusion, update the docstring to match the signature, e.g.:

  •    content_encoder : Callable[[Content], BasicObject]
    
  •        Callable that transforms typed payloads into broker-serializable objects before publish.
    
  •    content_encoder : Callable[[Content], str]
    
  •        Callable that transforms typed payloads into strings before publish.
    
    
    

These tweaks bring the public docs back in sync with the types and the underlying AWSSQSQueueAccessing protocol.

src/draive/aws/sqs.py (3)

30-64: Missing docstring and **extra parameters not forwarded.

Per past review comments that remain unaddressed: AWSSQSMixin lacks the required NumPy-style docstring, and **extra parameters are accepted but silently dropped throughout the call chain (publish_message, consume_messages, _publish). This violates the API contract documented in AWSSQS.queue.


216-227: bool values incorrectly handled as numbers.

As noted in a prior review, bool is a subclass of int in Python, so True/False match the int() | float() case and produce {"DataType": "Number", "StringValue": "True"}. Add an explicit case bool() before the numeric case.


98-131: Type mismatch: decoder expects BasicObject but receives str.

Line 126 passes message["Body"] (a str) to decoder, but the type annotation on line 103 declares Callable[[BasicObject], Content]. This inconsistency will cause type checkers to report errors and confuses consumers about the expected decoder signature.

Either parse the JSON body before passing to the decoder:

+from json import loads
 ...
                 yield MQMessage(
-                    content=decoder(message["Body"]),
+                    content=decoder(loads(message["Body"])),

Or update the type annotations across AWSSQSQueueAccessing, AWSSQS.queue, and _queue_access to use Callable[[str], Content] if consumers are expected to handle raw string bodies.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f200d4 and 1bf16bb.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (4 hunks)
  • src/draive/aws/s3.py (1 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • tests/test_tags_replacement.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/aws/s3.py
  • src/draive/rabbitmq/__init__.py
  • tests/test_tags_extraction.py
  • src/draive/aws/sqs.py
  • src/draive/aws/client.py
  • src/draive/aws/api.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_replacement.py
  • tests/test_tags_extraction.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/aws/s3.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/sqs.py
  • src/draive/aws/client.py
  • src/draive/aws/api.py
🧠 Learnings (4)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/state.py
  • src/draive/aws/sqs.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to **/*.py : Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like `HTTPRequesting` to keep boundaries explicit

Applied to files:

  • src/draive/aws/types.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
🧬 Code graph analysis (5)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
src/draive/aws/types.py (1)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/sqs.py (3)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/types.py (3)
  • AWSAccessDenied (51-65)
  • AWSError (15-48)
  • AWSResourceNotFound (68-82)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/client.py (3)
src/draive/aws/sqs.py (2)
  • AWSSQSMixin (30-213)
  • _queue_access (31-64)
src/draive/aws/state.py (1)
  • AWSSQS (12-86)
src/draive/aws/api.py (1)
  • _prepare_sqs_client (65-68)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test (macos-latest, 3.13)
🔇 Additional comments (13)
tests/test_tags_extraction.py (1)

465-477: String-literal style change only

The updated HTML snippets are a pure quoting/style tweak and do not affect test behavior; this segment looks good as-is.

tests/test_tags_replacement.py (1)

678-682: No behavioral change in malformed self-closing tag test

The updated string literal keeps the test scenario identical (malformed img tag is still ignored); no further changes needed here.

src/draive/aws/api.py (1)

12-20: SQS client wiring mirrors S3 cleanly; no action needed

The added _sqs_client slot and _prepare_sqs_client follow the existing S3 pattern correctly and keep boto3 behind @asynchronous. All call sites in client.py properly await both methods. The rename from _prepare_client to _prepare_s3_client is complete with no stale references remaining.

Likely an incorrect or invalid review comment.

src/draive/aws/sqs.py (6)

1-27: Imports and module setup look correct.

The imports are appropriate for the functionality: asynccontextmanager for async context management, ClientError for boto3 error handling, and haiway types for message queue abstractions. The __all__ export is properly restricted to the public mixin.


66-96: _publish implementation is well-structured.

Queue URL resolution, error translation, and message attribute formatting follow established patterns. The @asynchronous decorator ensures boto3's synchronous calls don't block the event loop.


132-156: _receive correctly implements long-polling with error translation.

The implementation properly uses long-polling (WaitTimeSeconds=20) and handles boto3 errors. The hardcoded polling parameters were noted in a prior review as a potential enhancement.


158-181: _ack_message implementation is correct.

Properly resolves queue URL and translates errors consistently with other operations.


230-287: Error translation logic is comprehensive and well-structured.

The mapping covers common SQS error codes (NonExistentQueue, access denied variants) and HTTP status codes. The contextual error messages include provider, operation, and queue identifiers for debugging.


290-297: LGTM!

Clean helper for consistent error message formatting with contextual metadata.

src/draive/aws/client.py (4)

9-10: LGTM!

Imports for AWSSQSMixin and AWSSQS are correctly added to support the new SQS feature.


16-21: Mixin composition is correctly ordered.

The MRO AWS -> AWSS3Mixin -> AWSSQSMixin -> AWSAPI ensures both mixins share a single AWSAPI instance. Placing AWSAPI last is the canonical pattern for diamond inheritance with mixins.


56-61: Breaking change: default features is now empty.

Previously, omitting features defaulted to (ResourcesRepository,). Now it defaults to (), so existing code like async with AWS() as features will get an empty list and ResourcesRepository won't be activated without explicit request.

If this is intentional (explicit-is-better), consider documenting the change in release notes. Otherwise, restore the previous default:

         else:
-            self._features = ()
+            self._features = (ResourcesRepository,)

63-83: Feature binding implementation is correct.

The conditional client preparation and state instantiation properly handle multiple feature types. The returned list[State] matches the Iterable[State] return type and integrates well with ctx.scope(...).

@KaQuMiQ KaQuMiQ force-pushed the feature/mq branch 2 times, most recently from b19c55a to d345469 Compare December 5, 2025 13:54
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (7)
pyproject.toml (1)

8-8: Version bump and dependency updates are consistent with the new MessageQueue feature.

The version bump to 0.95.0, the haiway~=0.40.0 update, and the new rabbitmq optional dependency group align with the PR's objective to add MessageQueue support. The pika dependency lacking a version constraint was already noted in a previous review.

Also applies to: 27-27, 55-55

src/draive/rabbitmq/__init__.py (1)

1-7: Clean re-export shim for RabbitMQ integration.

The direct re-export from haiway.rabbitmq with explicit __all__ follows the established pattern for integration modules. The suggestion to also export these symbols from src/draive/__init__.py for central API consistency was already raised in a previous review.

src/draive/aws/types.py (1)

85-93: Well-defined protocol with precise typing; docstring suggestion already noted.

The AWSSQSQueueAccessing protocol correctly uses structural typing with @runtime_checkable, and the __call__ signature aligns with the AWSSQS.queue implementation in src/draive/aws/state.py. The PEP 695 generic syntax (def __call__[Content]) is appropriate for Python 3.13+.

The suggestion to add a NumPy-style docstring for this public protocol was already raised in a previous review.

src/draive/aws/state.py (2)

12-13: Add a class-level NumPy-style docstring for AWSSQS.

Per coding guidelines, public symbols require NumPy-style docstrings. AWSSQS is exported via __all__ but lacks class-level documentation describing its purpose, main public API (queue statemethod and queue_accessing attribute), and usage pattern.


50-51: Docstring type mismatch for content_encoder.

The docstring states Callable[[Content], BasicObject] but the actual parameter type is Callable[[Content], str]. This inconsistency could mislead API consumers.

-        content_encoder : Callable[[Content], BasicObject]
-            Callable that transforms typed payloads into broker-serializable objects before publish.
+        content_encoder : Callable[[Content], str]
+            Callable that transforms typed payloads into strings before publish.
src/draive/aws/sqs.py (2)

31-40: AWSSQSMixin is missing a NumPy-style docstring and silently drops **extra parameters.

Per coding guidelines, public symbols require NumPy-style docstrings. Additionally, _queue_access receives **extra at line 39 but never forwards it to _publish (line 48-52) or through consume_messages (line 54-60). The AWSSQS.queue docstring promises these are "forwarded to the underlying queue accessor."

Either forward **extra through the stack or update the API contract to clarify that extra options are not supported for SQS.


226-237: bool values are incorrectly serialized as SQS Number type.

Since bool is a subclass of int in Python, True/False match the int() | float() case (line 233) and are serialized as {"DataType": "Number", "StringValue": "True"}. SQS expects numeric strings for Number types, so this will likely cause validation errors or unexpected behavior.

Add an explicit bool case before the numeric case:

 def _format_attribute_value(
     value: RawValue,
 ) -> dict[str, Any]:
     match value:
         case str() as value:
             return {"DataType": "String", "StringValue": value}
 
+        case bool() as value:
+            return {"DataType": "String", "StringValue": "true" if value else "false"}
+
         case int() | float() as value:
             return {"DataType": "Number", "StringValue": str(value)}
 
         case value:
-            raise ValueError(f"Unsupported value {type(value)}")
+            raise ValueError(f"Unsupported SQS attribute value type: {type(value)}")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bf16bb and b19c55a.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (4 hunks)
  • src/draive/aws/s3.py (1 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • tests/test_tags_replacement.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/types.py
  • src/draive/aws/sqs.py
  • src/draive/aws/api.py
  • src/draive/aws/state.py
  • src/draive/aws/s3.py
  • tests/test_tags_extraction.py
  • src/draive/aws/client.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_replacement.py
  • tests/test_tags_extraction.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/types.py
  • src/draive/aws/sqs.py
  • src/draive/aws/api.py
  • src/draive/aws/state.py
  • src/draive/aws/s3.py
  • src/draive/aws/client.py
🧠 Learnings (4)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to **/*.py : Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like `HTTPRequesting` to keep boundaries explicit

Applied to files:

  • src/draive/aws/types.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
🧬 Code graph analysis (4)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/types.py (1)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/sqs.py (3)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/types.py (3)
  • AWSAccessDenied (51-65)
  • AWSError (15-48)
  • AWSResourceNotFound (68-82)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
🔇 Additional comments (10)
tests/test_tags_extraction.py (1)

466-476: Cosmetic quote style change; test logic remains correct.

The change from single to double quotes for the test input strings is a formatting adjustment with no semantic impact. The test correctly validates that self-closing tags with malformed attributes (missing quotes around attribute values) are ignored while valid tags are still parsed.

tests/test_tags_replacement.py (1)

678-681: Cosmetic quote style change; test correctly validates malformed tag handling.

The quote style adjustment has no semantic impact. The test appropriately verifies that replacing_tag leaves content unchanged when encountering a malformed self-closing tag with an unquoted attribute value.

src/draive/aws/types.py (1)

1-5: Imports are appropriate for the new protocol definition.

All imports are used: Callable, AbstractAsyncContextManager, Protocol, runtime_checkable from the standard library, and BasicObject, MQQueue from haiway for the protocol's type signature.

src/draive/aws/s3.py (1)

281-295: LGTM!

The metadata sanitization correctly handles both keys and values, defensively skips empty entries, and returns the proper dict[str, str] type for S3 Metadata.

src/draive/aws/api.py (1)

64-68: LGTM!

The _prepare_sqs_client method correctly mirrors the _prepare_s3_client pattern, maintaining consistency in the boto3 client initialization approach.

src/draive/aws/state.py (1)

79-84: LGTM!

The queue method correctly delegates to queue_accessing with all parameters including **extra, matching the documented behavior.

src/draive/aws/sqs.py (2)

101-133: LGTM!

The consume implementation correctly:

  • Passes message["Body"] to the decoder (not the full envelope)
  • Uses default argument capture for receipt_handle in the closure
  • Checks cancellation between polling iterations

240-297: LGTM!

The error translation follows the established S3 pattern, correctly maps SQS-specific error codes to typed exceptions, and includes contextual information (provider, operation, queue) for debugging.

src/draive/aws/client.py (2)

56-61: Default features changed from (ResourcesRepository,) to ()—potential breaking change.

Previously, if features was None, ResourcesRepository was activated by default. Now it defaults to an empty tuple, meaning no features are activated unless explicitly requested. This could break existing code that relies on the implicit default.

If this is intentional, consider documenting the change. If backward compatibility is desired:

         else:
-            self._features = ()
+            self._features = (ResourcesRepository,)

63-83: LGTM!

The __aenter__ implementation correctly:

  • Lazily prepares only the requested AWS service clients
  • Constructs feature states with appropriate callbacks
  • Returns an Iterable[State] for context binding

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/draive/aws/client.py (1)

22-39: Update class docstring to mention SQS capability.

The class now supports SQS features via AWSSQSMixin, but the docstring at line 22 only mentions "S3 and repository integrations." Update to reflect the broader capability:

-    """AWS service facade bundling S3 and repository integrations.
+    """AWS service facade bundling S3, SQS, and repository integrations.
♻️ Duplicate comments (7)
pyproject.toml (1)

8-8: Version and MQ dependency updates look aligned; consider constraining pika

The 0.95.0 version bump and haiway~=0.40.0 upgrade match the new MQ/SQS/RabbitMQ features and Python 3.13 tooling.

For the new rabbitmq extra, you currently install the latest pika without bounds. Unless you explicitly want “latest available” behavior, consider adding a compatible version range (e.g., pika~=X.Y) to avoid unexpected upstream breaking changes, and verify that haiway~=0.40.0 plus your chosen pika range passes the test suite.

Also applies to: 27-27, 55-55

src/draive/rabbitmq/__init__.py (1)

1-7: RabbitMQ shim looks good; consider adding top‑level draive re‑exports

This is a clean, minimal re‑export of the haiway RabbitMQ types. If these are part of the intended public surface, consider also re‑exporting them from src/draive/__init__.py so users can access draive.RabbitMQ, draive.RabbitMQClient, and draive.RabbitMQException, keeping the central public API index consistent. Based on learnings, public exports are typically centralized there.

src/draive/aws/types.py (1)

1-3: Add a NumPy‑style docstring for public AWSSQSQueueAccessing

The protocol shape and generics look good and line up with the AWSSQS.queue overloads, but since AWSSQSQueueAccessing is exported via __all__, it should carry a short NumPy‑style docstring describing the async __call__ contract (Parameters/Returns, noting it returns an AbstractAsyncContextManager[MQQueue[Content]] for a given queue/encoder/decoder), to keep the public boundary self‑describing. As per coding guidelines for src/draive/**/*.py, public symbols should have NumPy‑style docstrings.

Also applies to: 5-5, 11-12, 85-93

src/draive/aws/api.py (1)

12-20: SQS client wiring is fine; fix minor grammar in the class docstring

The added _sqs_client slot and _prepare_sqs_client mirror the existing S3 path and keep boto3 calls behind @asynchronous, which is consistent with the rest of the AWS mixins.

The class docstring sentence

“Provides an asynchronous S3 and SQS client initializers…”

is grammatically off. Consider e.g.:

  • “Provides asynchronous S3 and SQS client initializers that other mixins can rely on …”, or
  • “Provides an asynchronous initializer for S3 and SQS clients that other mixins can rely on …”.

Also applies to: 56-68

src/draive/aws/state.py (1)

12-86: Add class‑level docs for AWSSQS and fix content_encoder docstring type

The AWSSQS.queue overloads and implementation look consistent with AWSSQSQueueAccessing and the @statemethod pattern, but there are two doc issues:

  1. AWSSQS is exported via __all__ yet has no class‑level NumPy‑style docstring, contrary to the src/draive/**/*.py guidelines for public symbols.
  2. In the queue method docstring, content_encoder is documented as Callable[[Content], BasicObject] while the actual type is Callable[[Content], str], which can confuse consumers.

You can address both with something like:

 class AWSSQS(State):
+    """
+    AWS SQS state providing typed queue access bound to the current state.
+
+    Parameters
+    ----------
+    queue_accessing : AWSSQSQueueAccessing
+        Callable responsible for creating typed SQS queue accessors. It is
+        typically injected by the AWS client layer and used internally by
+        :meth:`queue`.
+
+    Notes
+    -----
+    The primary entry point is :meth:`queue`, which returns an async context
+    manager yielding an :class:`MQQueue` configured with the provided
+    encoder/decoder pair.
+    """
@@
-        content_encoder : Callable[[Content], BasicObject]
-            Callable that transforms typed payloads into broker-serializable objects before publish.
+        content_encoder : Callable[[Content], str]
+            Callable that transforms typed payloads into strings before publish.

As per coding guidelines and prior feedback, this keeps the public state type self‑describing and aligns the documentation with the actual signature.

src/draive/aws/sqs.py (2)

46-79: **extra parameters are accepted but never forwarded, violating the API contract.

AWSSQS.queue (state.py:43-49) documents that **extra are "Additional options forwarded to the underlying queue accessor," but:

  • publish_message (line 58) accepts **extra but doesn't pass it to _publish (line 60)
  • consume_messages (line 67) accepts **extra but doesn't pass it to _consume (line 69)

Either thread **extra through the full call chain (publish_message_publish, consume_messages_consume) or remove **extra from all signatures and update AWSSQS.queue's docstring to clarify extra options are unsupported.


238-249: bool values incorrectly serialize as Number type, causing SQS API errors.

Since bool is a subclass of int in Python, boolean values match the int() | float() case at line 245, resulting in attributes like {"DataType": "Number", "StringValue": "True"}. AWS SQS rejects numeric attributes with non-numeric strings.

Add an explicit bool case before the numeric pattern:

 def _format_attribute_value(
     value: RawValue,
 ) -> dict[str, Any]:
     match value:
         case str() as value:
             return {"DataType": "String", "StringValue": value}
 
+        case bool() as value:
+            return {"DataType": "String", "StringValue": "true" if value else "false"}
+
         case int() | float() as value:
             return {"DataType": "Number", "StringValue": str(value)}
 
         case value:
-            raise ValueError(f"Unsupported value {type(value)}")
+            raise ValueError(f"Unsupported SQS attribute value type: {type(value)}")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b19c55a and d345469.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (4 hunks)
  • src/draive/aws/s3.py (1 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • src/draive/aws/api.py
  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • tests/test_tags_replacement.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/s3.py
  • tests/test_tags_extraction.py
  • src/draive/aws/client.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/api.py
  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/s3.py
  • src/draive/aws/client.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_replacement.py
  • tests/test_tags_extraction.py
🧠 Learnings (4)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to **/*.py : Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like `HTTPRequesting` to keep boundaries explicit

Applied to files:

  • src/draive/aws/types.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
🧬 Code graph analysis (6)
src/draive/aws/sqs.py (3)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/types.py (3)
  • AWSAccessDenied (51-65)
  • AWSError (15-48)
  • AWSResourceNotFound (68-82)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
src/draive/aws/types.py (1)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
tests/test_tags_extraction.py (2)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/resources/types.py (4)
  • of (77-94)
  • of (103-120)
  • of (131-138)
  • of (142-149)
src/draive/aws/client.py (4)
src/draive/aws/sqs.py (2)
  • AWSSQSMixin (31-235)
  • _queue_access (46-79)
src/draive/aws/state.py (1)
  • AWSSQS (12-86)
src/draive/resources/state.py (1)
  • ResourcesRepository (27-190)
src/draive/aws/api.py (2)
  • _prepare_s3_client (59-62)
  • _prepare_sqs_client (65-68)
🔇 Additional comments (11)
tests/test_tags_extraction.py (1)

466-477: Malformed self‑closing <img> test still valid after quoting change

Only the string literal quoting changed here; the test still correctly verifies that a malformed <img src=hero/> is skipped while a following well‑formed tag is parsed. No behavioral impact.

tests/test_tags_replacement.py (1)

678-686: Quote style tweak only; malformed <img> replacement behavior unchanged

Switching the HTML snippet to double quotes doesn’t affect the test’s intent: replacing_tag still ignores the malformed <img src=logo/> and returns the original content.

src/draive/aws/s3.py (1)

252-295: S3 metadata sanitization helpers look correct and safely bounded

The new _sanitize_metadata_value / _sanitize_metadata pair produce a clean dict[str, str] for S3 metadata: values are stringified, non‑ASCII and control characters are stripped, whitespace is normalized, and values are truncated with an ellipsis to stay within the 1,024‑byte limit. Using these helpers from _upload via Metadata=_sanitize_metadata(meta) keeps the boto3 boundary safe without leaking arbitrary user metadata into headers.

src/draive/aws/sqs.py (5)

81-111: LGTM!

Proper queue URL resolution, error handling, and attribute formatting. The implementation correctly translates queue names to URLs and handles boto3 ClientError exceptions with contextual information.


147-171: LGTM!

Proper queue URL resolution, long-polling configuration, and error handling. The fixed polling parameters (MaxNumberOfMessages=1, WaitTimeSeconds=20) are reasonable defaults for typical SQS consumption patterns.


173-196: LGTM!

Correct message acknowledgment via SQS delete operation with proper error handling.


198-235: LGTM!

Robust queue URL resolution with proper caching, error handling, and response validation. The instance-level cache correctly avoids cross-region/cross-account conflicts.


252-318: LGTM!

Comprehensive error translation following the established pattern from s3.py. Proper normalization of error codes, status code fallbacks, and contextual error messages with provider/operation/queue information.

src/draive/aws/client.py (3)

9-21: LGTM!

Proper import structure and multiple inheritance setup. The MRO (Method Resolution Order) is safe since both AWSS3Mixin and AWSSQSMixin properly call super().__init__() and inherit from AWSAPI.


56-61: Default features changed from (ResourcesRepository,) to () - breaking change.

The default value for features changed from (ResourcesRepository,) to an empty tuple at line 61. This means existing code that relied on ResourcesRepository being enabled by default will break.

If this is intentional (to make features opt-in), ensure:

  1. Migration guide documents this breaking change
  2. Version bump reflects the breaking change (already 0.94.1→0.95.0 per PR summary)

If unintentional, restore the previous default.


63-83: LGTM!

Clean feature initialization logic with proper client preparation for each feature type. The method correctly prepares S3 for ResourcesRepository and SQS for AWSSQS, returning a composite list of bound feature states.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

♻️ Duplicate comments (5)
src/draive/rabbitmq/__init__.py (1)

1-7: RabbitMQ shim looks good; double‑check central draive.__init__ exports.

This re‑export is fine. If RabbitMQ, RabbitMQClient, and RabbitMQException are intended as public APIs, ensure they’re also exported from src/draive/__init__.py to keep the central public surface consistent. Based on learnings, this repo centralizes exports there.

pyproject.toml (1)

55-55: Consider bounding pika version for the rabbitmq extra.

rabbitmq = ["haiway[rabbitmq]", "pika"] leaves pika completely unpinned, which risks unexpected breakage from upstream releases. Consider constraining it (for example, pika~=X.Y) to match a known‑good range for your stack.

src/draive/aws/api.py (1)

12-13: Fix grammar in AWSAPI class docstring.

The phrase "Provides an asynchronous S3 and SQS client initializers" is ungrammatical. Suggest:

-    Provides an asynchronous S3 and SQS client initializers that other mixins
+    Provides asynchronous S3 and SQS client initializers that other mixins
src/draive/aws/sqs.py (2)

31-45: Add a NumPy‑style docstring for public AWSSQSMixin.

AWSSQSMixin is exported via __all__ and forms part of the public AWS façade, but it has no class docstring. Per project guidelines, it should briefly describe its purpose (SQS helpers on top of AWSAPI), expected usage (mixed into AWS), and the main public surface (_queue_access and the higher‑level methods built on it).

Consider adding a short NumPy‑style docstring documenting Parameters (inherits AWSAPI constructor) and a high‑level description of what the mixin provides.


238-249: Handle bool message attribute values explicitly to satisfy SQS constraints.

Because bool is a subclass of int, the case int() | float() branch will match True/False and encode them as:

{"DataType": "Number", "StringValue": "True"}  # or "False"

AWS SQS requires that attributes with DataType="Number" have StringValue set to a numeric string representing a number. "True"/"False" are invalid and will cause send_message to fail.

You should treat booleans separately, before the numeric case, and either encode them as strings or reject them explicitly. For example:

def _format_attribute_value(
    value: RawValue,
) -> dict[str, Any]:
    match value:
+        case bool() as value:
+            # Represent booleans as strings; SQS has no native boolean type.
+            return {"DataType": "String", "StringValue": "true" if value else "false"}
         case str() as value:
             return {"DataType": "String", "StringValue": value}
@@
-        case int() | float() as value:
-            return {"DataType": "Number", "StringValue": str(value)}
+        case int() | float() as value:
+            return {"DataType": "Number", "StringValue": str(value)}
@@
-        case value:
-            raise ValueError(f"Unsupported value {type(value)}")
+        case value:
+            raise ValueError(f"Unsupported SQS attribute value type: {type(value)}")

This preserves correct handling for numeric types while avoiding invalid Number payloads for booleans.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d345469 and a78b5fb.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (4 hunks)
  • src/draive/aws/s3.py (1 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • tests/test_tags_replacement.py
  • src/draive/aws/sqs.py
  • src/draive/aws/api.py
  • tests/test_tags_extraction.py
  • src/draive/aws/s3.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/aws/client.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_replacement.py
  • tests/test_tags_extraction.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/sqs.py
  • src/draive/aws/api.py
  • src/draive/aws/s3.py
  • src/draive/rabbitmq/__init__.py
  • src/draive/aws/state.py
  • src/draive/aws/types.py
  • src/draive/aws/client.py
🧠 Learnings (4)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/sqs.py
  • src/draive/aws/state.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to **/*.py : Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like `HTTPRequesting` to keep boundaries explicit

Applied to files:

  • src/draive/aws/types.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
🧬 Code graph analysis (6)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/sqs.py (3)
src/draive/aws/api.py (1)
  • AWSAPI (9-74)
src/draive/aws/types.py (3)
  • AWSAccessDenied (51-65)
  • AWSError (15-48)
  • AWSResourceNotFound (68-82)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
tests/test_tags_extraction.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
src/draive/aws/types.py (1)
src/draive/aws/state.py (3)
  • queue (15-22)
  • queue (25-32)
  • queue (35-84)
src/draive/aws/client.py (5)
src/draive/aws/sqs.py (2)
  • AWSSQSMixin (31-235)
  • _queue_access (46-79)
src/draive/aws/state.py (1)
  • AWSSQS (12-86)
src/draive/aws/api.py (3)
  • AWSAPI (9-74)
  • _prepare_s3_client (59-62)
  • _prepare_sqs_client (65-68)
src/draive/resources/state.py (1)
  • ResourcesRepository (27-190)
src/draive/aws/s3.py (2)
  • fetch (20-70)
  • upload (178-224)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (10)
tests/test_tags_extraction.py (1)

466-476: Cosmetic quote style changes appear unrelated to the PR objective.

These changes convert string literals from single to double quotes but don't relate to the MessageQueue feature. The file uses mixed quote styles elsewhere.

This was previously flagged. Consider reverting if accidental, or normalizing quote style across all test files if intentional.

tests/test_tags_replacement.py (1)

679-679: Cosmetic quote style change appears unrelated to the PR objective.

Same observation as in the extraction tests - this quote style change seems unrelated to the MessageQueue feature.

This was previously flagged. Consider reverting or standardizing quote usage across all test files.

src/draive/rabbitmq/__init__.py (1)

1-7: Re-export shim looks good; consider centralizing in draive.__init__ as well.

The re-export from haiway.rabbitmq with explicit __all__ is clean. If these symbols are meant to be part of the public API, they should also be re-exported from src/draive/__init__.py for consistency.

Based on learnings, this repo centralizes public exports in src/draive/__init__.py.

pyproject.toml (1)

55-55: Consider pinning pika to a version range for consistency.

Other dependencies in this file use version constraints (e.g., ~=X.Y). Leaving pika unpinned may lead to unexpected breaking changes from upstream.

This was previously flagged. Consider adding a version constraint like pika~=1.3 or similar.

src/draive/aws/types.py (1)

85-93: Add a NumPy-style docstring for the public AWSSQSQueueAccessing protocol.

This protocol is exported via __all__ and represents a public boundary. Per coding guidelines, it should carry a NumPy-style docstring with Parameters/Returns sections.

The type signature now correctly uses Callable[[str], Content] for the decoder, which aligns with the actual SQS implementation.

src/draive/aws/api.py (1)

12-12: Grammar issue in docstring.

The docstring has a subject-verb agreement error: "Provides an asynchronous S3 and SQS client initializers" should be "Provides asynchronous S3 and SQS client initializers" (remove "an").

This was previously flagged but appears to still be present in the code.

src/draive/aws/s3.py (1)

278-292: Consider narrowing types and separating key handling.

The value: Any parameter type is loose per coding guidelines. Also, S3 metadata keys behave like HTTP header names (stricter charset than values). Using the same sanitization for both keys and values may not fully enforce key constraints.

Consider:

  1. Narrowing value type to BasicValue | str
  2. Adding a dedicated _sanitize_metadata_key helper that enforces ASCII for header-name compatibility
src/draive/aws/state.py (2)

12-12: Add a class-level NumPy-style docstring for AWSSQS.

AWSSQS is exported via __all__ and is a public State subclass, but lacks a class-level docstring. Per coding guidelines, public symbols should have NumPy-style docstrings describing purpose and usage.

This was previously flagged. Add a brief docstring describing AWSSQS as a stateful accessor for AWS SQS queues.


50-51: Minor docstring clarification.

The docstring says "broker-serializable objects" but the actual type is str. Consider updating to "strings" for precision:

-        content_encoder : Callable[[Content], str]
-            Callable that transforms typed payloads into broker-serializable objects before publish.
+        content_encoder : Callable[[Content], str]
+            Callable that transforms typed payloads into strings before publish.

This was previously flagged.

src/draive/aws/sqs.py (1)

30-43: Add a NumPy-style docstring for public AWSSQSMixin.

AWSSQSMixin is exported via __all__ but has no class-level docstring. Per the guidelines for src/draive/**/*.py, public symbols should have NumPy-style docstrings with Parameters, Returns, and Raises sections that describe the mixin’s purpose and its main entry point (_queue_access).

Consider adding a concise class docstring explaining that this mixin provides SQS-backed MQQueue access for AWSAPI subclasses, outlines how queue, content_encoder, and content_decoder are used, and summarizes which AWS errors can be raised during publish/consume flows. Based on learnings.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a78b5fb and 27d5bf7.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • pyproject.toml (3 hunks)
  • src/draive/aws/api.py (2 hunks)
  • src/draive/aws/client.py (4 hunks)
  • src/draive/aws/s3.py (1 hunks)
  • src/draive/aws/sqs.py (1 hunks)
  • src/draive/aws/state.py (1 hunks)
  • src/draive/aws/types.py (2 hunks)
  • src/draive/rabbitmq/__init__.py (1 hunks)
  • tests/test_tags_extraction.py (1 hunks)
  • tests/test_tags_replacement.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Ensure latest, most strict typing syntax available from Python 3.13+; use no untyped public APIs and no loose Any unless required by third-party boundaries
Prefer explicit attribute access with static types; avoid dynamic getattr except at narrow boundaries
In public types, prefer abstract immutable protocols like Mapping, Sequence, Iterable over concrete dict, list, set
Use final where applicable; avoid inheritance and prefer type composition
Use precise unions (|) and narrow with match/isinstance; avoid cast unless provably safe and localized
Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like HTTPRequesting to keep boundaries explicit
Guard immutability with assertions when crossing context boundaries; failure messages should aid debugging but never leak secrets
All I/O is async; keep boundaries async and use ctx.spawn for detached tasks, avoiding custom threading
Ensure structured concurrency concepts and valid coroutine usage; rely on haiway and asyncio packages
Await long-running operations directly; never block the event loop with sync calls
Translate provider/SDK errors into appropriate typed exceptions; wrap third-party exceptions at the boundary with actionable context (provider, operation, identifiers) while redacting sensitive payloads
Don't raise bare Exception; preserve contextual information in exception construction
Use observability hooks (ctx.log_*, ctx.record) from ctx helper instead of print/logging; tests assert on emitted events

Files:

  • src/draive/aws/client.py
  • src/draive/aws/state.py
  • tests/test_tags_extraction.py
  • tests/test_tags_replacement.py
  • src/draive/aws/api.py
  • src/draive/aws/sqs.py
  • src/draive/aws/types.py
  • src/draive/aws/s3.py
  • src/draive/rabbitmq/__init__.py
src/draive/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/draive/**/*.py: Import symbols from draive directly (e.g., from draive import State, ctx) rather than internal module paths
Use context scoping (ctx.scope(...)) to bind scoped Disposables, active State instances, and avoid global state
Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale
Avoid docstrings for internal and private helpers; keep names self-explanatory
Skip module-level docstrings

Files:

  • src/draive/aws/client.py
  • src/draive/aws/state.py
  • src/draive/aws/api.py
  • src/draive/aws/sqs.py
  • src/draive/aws/types.py
  • src/draive/aws/s3.py
  • src/draive/rabbitmq/__init__.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.py: No network in unit tests; mock providers and HTTP requests
Keep tests fast and specific to the code you change; start with unit tests around new types, functions, and adapters
Mirror package layout in tests/; colocate new tests alongside features and prefer pytest parametrization over loops
Test async flows with pytest.mark.asyncio; use ctx.scope in tests to isolate state and avoid leaking globals

Files:

  • tests/test_tags_extraction.py
  • tests/test_tags_replacement.py
🧠 Learnings (4)
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/**/*.py : Add NumPy-style docstrings to public symbols; include Parameters, Returns, and Raises sections with rationale

Applied to files:

  • src/draive/aws/state.py
  • src/draive/aws/sqs.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to **/*.py : Favor structural typing (Protocols) for async clients and adapters; use runtime-checkable protocols like `HTTPRequesting` to keep boundaries explicit

Applied to files:

  • src/draive/aws/types.py
📚 Learning: 2025-12-02T14:30:08.757Z
Learnt from: CR
Repo: miquido/draive PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-02T14:30:08.757Z
Learning: Applies to src/draive/__init__.py : Centralize public exports in `src/draive/__init__.py`; update this file when adding or modifying public APIs

Applied to files:

  • src/draive/rabbitmq/__init__.py
📚 Learning: 2025-06-16T10:28:07.434Z
Learnt from: KaQuMiQ
Repo: miquido/draive PR: 338
File: src/draive/lmm/__init__.py:1-2
Timestamp: 2025-06-16T10:28:07.434Z
Learning: The draive project requires Python 3.12+ as specified in pyproject.toml with "requires-python = ">=3.12"" and uses Python 3.12+ specific features like PEP 695 type aliases and generic syntax extensively throughout the codebase.

Applied to files:

  • pyproject.toml
🧬 Code graph analysis (2)
src/draive/aws/state.py (1)
src/draive/aws/types.py (1)
  • AWSSQSQueueAccessing (86-93)
tests/test_tags_replacement.py (1)
src/draive/multimodal/content.py (3)
  • MultimodalContent (25-592)
  • of (42-66)
  • of (619-647)
🔇 Additional comments (4)
src/draive/aws/api.py (1)

64-68: LGTM!

The _prepare_sqs_client method correctly mirrors the S3 client initialization pattern with proper @asynchronous decoration.

src/draive/aws/s3.py (1)

252-275: Metadata sanitization logic is sound.

The implementation correctly handles UTF-8 truncation by encoding, truncating at byte level, and decoding with "ignore" to handle partial multi-byte characters at the boundary.

src/draive/aws/state.py (1)

34-84: Implementation looks correct and well-structured.

The @statemethod pattern with overloads for both class-level and instance-level usage is appropriate. The delegation to queue_accessing is clean, and the comprehensive docstring with usage example is helpful.

src/draive/aws/client.py (1)

16-82: SQS feature wiring in AWS looks coherent; confirm callers rely on explicit features.

The integration of AWSSQSMixin and AWSSQS into AWS is clean: __aenter__ now prepares S3 and SQS clients only when their respective state classes are present in self._features, and returns a concrete list[State] as declared.

One behavioral change is that _features now defaults to () when features is None, so async with AWS(...) as features: will yield an empty list unless callers explicitly pass something like {ResourcesRepository, AWSSQS}. If previous usage relied on an implicit default (e.g., always getting ResourcesRepository), please double-check and update call sites / docs accordingly.

@KaQuMiQ KaQuMiQ merged commit c5ead6c into main Dec 5, 2025
3 checks passed
@KaQuMiQ KaQuMiQ deleted the feature/mq branch December 5, 2025 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants