Skip to content

Conversation

@rogelioLpz
Copy link
Member

@rogelioLpz rogelioLpz commented Sep 8, 2025

Permite definir el metodo to_dict en un EmbeddedDocument y usarlo en la construcción del dict base.

@coderabbitai
Copy link

coderabbitai bot commented Sep 8, 2025

Walkthrough

  • In mongoengine_plus/models/helpers.py, mongo_to_dict now checks for a callable to_dict on EmbeddedDocumentField values and uses it when available; otherwise, it falls back to mongo_to_dict without an explicit exclude list.
  • mongoengine_plus/version.py updates version from 1.2.0 to 1.2.1.
  • tests/models/test_base.py adds File (EmbeddedDocument) and Address (EmbeddedDocument, BaseModel) types, augments TestModel with embedded fields (address, document), sets id as primary_key, and adds tests asserting nested to_dict behavior including exclusion and masking.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
		  - name: "Undocumented Breaking Changes"
			  mode: "warning"
			  instructions: |
				  Flag potential breaking changes that are not documented:
				  1. Identify changes to public APIs/exports, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints (including removed/renamed items and changes to types, required params, return values, defaults, or behavior).
				  2. Ignore purely internal/private changes (e.g., code not exported from package entry points or marked internal).
				  3. Verify documentation exists: a "Breaking Change" section in the PR description and updates to CHANGELOG.md.

Pre-merge checks (1 passed, 2 warnings)

❌ Failed Checks (2 warnings)
Check Name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is currently empty, providing no context, rationale, or summary of the changes, which leaves reviewers without the necessary information to evaluate the update. Please add a detailed pull request description outlining the motivation, implementation details, and expected impact of the changes, and consider adding a PR template to the repository to ensure all future PRs include essential information.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed Checks (1 passed)
Check Name Status Explanation
Title Check ✅ Passed The title succinctly and clearly describes the primary change—enabling use of an EmbeddedDocumentField’s custom to_dict method—which aligns closely with the pull request’s implementation of preferring data.to_dict() when available.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-embed-doc

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

@codecov
Copy link

codecov bot commented Sep 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (108945e) to head (411dd9c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main       #95   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           15        15           
  Lines          252       254    +2     
  Branches        22        23    +1     
=========================================
+ Hits           252       254    +2     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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: 0

Caution

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

⚠️ Outside diff range comments (2)
mongoengine_plus/models/helpers.py (2)

98-101: Apply the same to_dict() preference for EmbeddedDocument items inside ListField.

Currently list items always go through mongo_to_dict(), which skips BaseModel masking/exclusions and may leak hidden fields. Mirror the EmbeddedDocumentField logic here.

Apply this diff:

-        if isinstance(item, EmbeddedDocument):
-            return_data.append(mongo_to_dict(item))
+        if isinstance(item, EmbeddedDocument):
+            if callable(getattr(item, "to_dict", None)):
+                return_data.append(item.to_dict())
+            else:
+                return_data.append(mongo_to_dict(item))

120-121: Fix FloatField branch condition (typo causes it to never match).

Using rv is FloatField is incorrect; should compare field_type.

Apply this diff:

-    elif rv is FloatField:  # pragma: no cover
+    elif field_type is FloatField:  # pragma: no cover
         rv = float(data)
🧹 Nitpick comments (7)
mongoengine_plus/models/helpers.py (1)

45-51: Avoid mutating the caller-provided exclude_fields list in place.

Copying prevents subtle side effects if the same list is reused across calls.

Apply this diff:

-    if exclude_fields is None:
-        exclude_fields = []
+    if exclude_fields is None:
+        exclude_fields = []
+    else:
+        exclude_fields = list(exclude_fields)
 
     # remove _cls from heritage embedded fields
     exclude_fields.append('_cls')
tests/models/test_base.py (6)

16-22: Annotate class-level lists as ClassVar to satisfy static analysis and avoid shared-mutable warnings.

This matches the BaseModel convention and silences RUF012.

Apply this diff:

-class Address(EmbeddedDocument, BaseModel):
+class Address(EmbeddedDocument, BaseModel):
     # Inheritance from BaseModel, to use _excluded and _hidden
-    _excluded = ['reference']
-    _hidden = ['secret_code']
+    _excluded: ClassVar[list[str]] = ['reference']
+    _hidden: ClassVar[list[str]] = ['secret_code']

And ensure ClassVar is imported (see import suggestion).


1-6: Import ClassVar for the annotations above.

Apply this diff:

 from mongoengine import (
     Document,
     EmbeddedDocument,
     EmbeddedDocumentField,
     StringField,
 )
+from typing import ClassVar

32-32: Annotate TestModel _hidden as ClassVar for consistency with Address.

Apply this diff:

-    _hidden = ['secret_field']
+    _hidden: ClassVar[list[str]] = ['secret_field']

39-45: Silence S106 in tests or configure tooling to ignore it for test files.

These are harmless literals in tests; add # noqa: S106 if needed.

Apply this diff:

-        secret_code='898612',
+        secret_code='898612',  # noqa: S106
 ...
-        secret_field='secret',
+        secret_field='secret',  # noqa: S106

61-61: Optional: silence S101 or configure ruff to allow asserts in tests.

Either keep as-is (common in tests) or append # noqa: S101.

Apply this diff:

-    assert model_dict == expected
+    assert model_dict == expected  # noqa: S101

35-62: Add coverage for ListField[EmbeddedDocument] to ensure masking/exclusions apply within lists.

Complements the helpers.py change proposed for list items.

I can add a test like:

def test_embedded_list_respects_to_dict():
    class Tag(EmbeddedDocument, BaseModel):
        _hidden: ClassVar[list[str]] = ['secret']
        name = StringField()
        secret = StringField()

    class WithTags(BaseModel, Document):
        __test__ = False
        tags = ListField(EmbeddedDocumentField(Tag))

    doc = WithTags(tags=[Tag(name='t1', secret='s1')])
    assert doc.to_dict()['tags'] == [{'name': 't1', 'secret': '********'}]
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 108945e and 411dd9c.

📒 Files selected for processing (3)
  • mongoengine_plus/models/helpers.py (1 hunks)
  • mongoengine_plus/version.py (1 hunks)
  • tests/models/test_base.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit configuration file

**/*.py: Enforce Relative Imports for Internal Modules

Ensure that any imports referencing internal modules use relative paths. However, if modules reside in the main module directories (for example /src or /library_or_app_name) —and relative imports are not feasible—absolute imports are acceptable. Additionally, if a module is located outside the main module structure (for example, in /tests or /scripts at a similar level), absolute imports are also valid.

Examples and Guidelines:

  1. If a module is in the same folder or a subfolder of the current file, use relative imports. For instance: from .some_module import SomeClass
  2. If the module is located under /src or /library_or_app_name and cannot be imported relatively, absolute imports are allowed (e.g., from library_or_app_name.utilities import helper_method).
  3. If a module is outside the main module directories (for example, in /tests, /scripts, or any similarly placed directory), absolute imports are valid.
  4. External (third-party) libraries should be imported absolutely (e.g., import requests).

**/*.py:
Rule: Enforce Snake Case in Python Backend

  1. New or Modified Code: Use snake_case for all variables, functions, methods, and class attributes.
  2. Exceptions (Pydantic models for API responses):
    • Primary fields must be snake_case.
    • If older clients expect camelCase, create a computed or alias field that references the snake_case field.
    • Mark any camelCase fields as deprecated or transitional.

Examples

Invalid:

class CardConfiguration(BaseModel):
    title: str
    subTitle: str  # ❌ Modified or new field in camelCase

Valid:

class CardConfiguration(BaseModel):
    title: str
    subtitle: str  # ✅ snake_case for new/modified field

    @computed_field
    def subTitle(self) -> str:  # camelCase allowed only for compatibility
        return self.subtitle

Any direct use of camelCase in new or updated code outside of these exceptions should be flagged.

`*...

Files:

  • mongoengine_plus/models/helpers.py
  • mongoengine_plus/version.py
  • tests/models/test_base.py
🧬 Code graph analysis (2)
mongoengine_plus/models/helpers.py (1)
mongoengine_plus/models/base.py (1)
  • to_dict (13-20)
tests/models/test_base.py (1)
mongoengine_plus/models/base.py (2)
  • BaseModel (6-23)
  • to_dict (13-20)
🪛 Ruff (0.12.2)
tests/models/test_base.py

18-18: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


19-19: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


32-32: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


39-39: Possible hardcoded password assigned to argument: "secret_code"

(S106)


44-44: Possible hardcoded password assigned to argument: "secret_field"

(S106)


61-61: Use of assert detected

(S101)

🔇 Additional comments (5)
mongoengine_plus/version.py (1)

1-1: Patch version bump is appropriate for this bugfix.

No issues spotted.

mongoengine_plus/models/helpers.py (1)

69-72: Prefer embedded to_dict() when available — good fix.

This honors BaseModel masking/exclusions on embedded docs and aligns behavior with expectations.

tests/models/test_base.py (3)

11-14: Embedded File doc for fallback path — looks good.

Covers the non-BaseModel embedded case.


26-29: Primary key and embedded fields on TestModel — LGTM.

This exercises both custom to_dict() (Address) and fallback (File).


49-61: Expected structure and masking assertions — LGTM.

Covers id, masking, exclusion, and embedded serialization paths.

@rogelioLpz rogelioLpz changed the title Fix to_dict for EmbeddedDocumentField Permite usar el to_dict de un EmbeddedDocumentField Sep 8, 2025
@rogelioLpz rogelioLpz merged commit 8a57a6e into main Sep 8, 2025
12 checks passed
@rogelioLpz rogelioLpz deleted the fix-embed-doc branch September 8, 2025 23:26
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.

4 participants