Skip to content

Conversation

@albertsola
Copy link
Contributor

@albertsola albertsola commented Feb 2, 2026

Closes MPT-16437

  • Restructures HTTP mixins into a package: replaces monolithic mpt_api_client/http/mixins.py with mpt_api_client/http/mixins/ and individual modules (collection_mixin, create_mixin, delete_mixin, get_mixin, update_mixin, enable_mixin, disable_mixin, create_file_mixin, update_file_mixin, download_file_mixin, file_operations_mixin, queryable_mixin, resource_mixins).
  • Adds init.py to re-export the full public mixin API surface (sync and async variants) to preserve compatibility.
  • Implements pagination, queryable, file upload/download, CRUD, enable/disable, and composite resource mixins as separate modules.
  • Moves and expands unit tests from a single tests/unit/http/test_mixins.py into focused tests under tests/unit/http/mixins/* covering each mixin and async/sync behaviors.
  • Updates pyproject.toml linting ignores to accommodate the new directory layout.

@albertsola albertsola requested a review from a team as a code owner February 2, 2026 11:03
@coderabbitai
Copy link

coderabbitai bot commented Feb 2, 2026

📝 Walkthrough

Walkthrough

Monolithic mpt_api_client/http/mixins.py was removed and replaced by a mpt_api_client/http/mixins/ package containing per-mixin modules and an __init__.py re-export; extensive new unit tests were added and the old consolidated test file removed.

Changes

Cohort / File(s) Summary
Module removed
mpt_api_client/http/mixins.py
Deleted the single-file implementation of many sync/async HTTP mixins (665 lines removed).
Package init / re-exports
mpt_api_client/http/mixins/__init__.py
New package initializer that re-exports all mixin classes (sync and async variants) as the public API.
Collection mixins
mpt_api_client/http/mixins/collection_mixin.py
Added CollectionMixin and AsyncCollectionMixin with fetch_page, fetch_one, iterate, and internal page fetch helpers.
Create mixins
mpt_api_client/http/mixins/create_mixin.py, mpt_api_client/http/mixins/create_file_mixin.py
Added CreateMixin/AsyncCreateMixin and CreateFileMixin/AsyncCreateFileMixin for resource creation, including multipart file upload handling.
Update mixins
mpt_api_client/http/mixins/update_mixin.py, mpt_api_client/http/mixins/update_file_mixin.py
Added UpdateMixin/AsyncUpdateMixin and UpdateFileMixin/AsyncUpdateFileMixin implementing PUT updates and optional file multipart payloads.
Delete mixins
mpt_api_client/http/mixins/delete_mixin.py
Added DeleteMixin and AsyncDeleteMixin implementing resource deletion endpoints.
Get mixins
mpt_api_client/http/mixins/get_mixin.py
Added GetMixin and AsyncGetMixin with optional select normalization (list → comma string).
Enable / Disable mixins
mpt_api_client/http/mixins/enable_mixin.py, mpt_api_client/http/mixins/disable_mixin.py
Added EnableMixin/AsyncEnableMixin and DisableMixin/AsyncDisableMixin delegating to _resource_action for POST actions.
File operations & download
mpt_api_client/http/mixins/file_operations_mixin.py, mpt_api_client/http/mixins/download_file_mixin.py
Added FilesOperationsMixin/AsyncFilesOperationsMixin and DownloadFileMixin/AsyncDownloadFileMixin for multipart create and file download flows.
Queryable mixin
mpt_api_client/http/mixins/queryable_mixin.py
Added QueryableMixin implementing fluent query-state methods: order_by, filter, select, and _create_new_instance.
Resource composition
mpt_api_client/http/mixins/resource_mixins.py
Added composite mixins: ModifiableResourceMixin, AsyncModifiableResourceMixin, ManagedResourceMixin, AsyncManagedResourceMixin.
Build config
pyproject.toml
Updated per-file-ignores to reference tests/unit/http/mixins/* and adjusted linter codes.
Unit tests added
tests/unit/http/mixins/test_collection_mixin.py, tests/unit/http/mixins/test_create_file_mixin.py, tests/unit/http/mixins/test_create_mixin.py, tests/unit/http/mixins/test_delete_mixin.py, tests/unit/http/mixins/test_disable_mixin.py, tests/unit/http/mixins/test_download_file_mixin.py, tests/unit/http/mixins/test_enable_mixin.py, tests/unit/http/mixins/test_file_operations_mixin.py, tests/unit/http/mixins/test_get_mixin.py, tests/unit/http/mixins/test_queryable_mixin.py, tests/unit/http/mixins/test_resource_mixins.py, tests/unit/http/mixins/test_update_file_mixin.py, tests/unit/http/mixins/test_update_mixin.py
Added comprehensive sync/async tests covering create, update, delete, get, file upload/download, enable/disable, collection pagination/iteration, queryable behavior, and composite resource mixins.
Consolidated test removed
tests/unit/http/test_mixins.py
Removed the previous single large test module (1,435 lines); tests redistributed into new modular test files.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Jira Issue Key In Title ✅ Passed The PR title contains exactly one Jira issue key in the correct format (MPT-16437) at the beginning, following the required naming convention.
Test Coverage Required ✅ Passed PR modifies 16 code files and includes 14 test file changes (13 new test modules with ~1,081 lines covering all new mixins), satisfying the requirement of test coverage alongside code modifications.
Single Commit Required ✅ Passed The pull request contains exactly one commit (92149de) with message 'MPT-16437 Update http/mixins file structure' based on git log and commit count verification.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

🤖 Fix all issues with AI agents
In `@mpt_api_client/http/mixins/disable_mixin.py`:
- Around line 18-20: The disable method's docstring contains an extra space
before the period; update the docstring in the disable function (disable) to
remove the double space so it reads "Disable a specific resource." ensuring the
triple-quoted string in disable (in disable_mixin.py) is edited accordingly.

In `@tests/unit/http/mixins/test_disable_mixin.py`:
- Around line 36-97: The tests test_disable_resource_actions and
test_async_disable_resource_actions assert an empty body when input_status is
None, but calling disablable_service.disable / async_disablable_service.disable
with json=None produces a body of b'null'; update both tests to expect b'null'
for the None case (i.e., set request_expected_content =
b'{"id":"OBJ-0000-0001","status":"update"}' if input_status else b'null') so the
assertions match the actual request.content returned by the mocked httpx call.
🧹 Nitpick comments (5)
mpt_api_client/http/mixins/file_operations_mixin.py (2)

17-17: Remove unused noqa directive.

Static analysis indicates # noqa: WPS221 is no longer needed here.

🧹 Proposed fix
-        files: dict[str, FileTypes] | None = None,  # noqa: WPS221
+        files: dict[str, FileTypes] | None = None,

49-49: Remove unused noqa directive.

Same as above - the WPS221 directive is no longer applicable.

🧹 Proposed fix
-        files: dict[str, FileTypes] | None = None,  # noqa: WPS221
+        files: dict[str, FileTypes] | None = None,
tests/unit/http/mixins/test_get_mixin.py (1)

31-60: Consider consolidating async get tests with parametrization.

The two async tests (test_async_get and test_async_get_select_str) could be combined into a single parametrized test similar to test_sync_get_mixin, reducing duplication. However, the current structure is clear and functional.

♻️ Optional consolidation
+@pytest.mark.parametrize(
+    "select_value",
+    [
+        ["id", "name"],
+        "id,name",
+    ],
+)
+async def test_async_get_mixin(
+    async_dummy_service: AsyncDummyService, select_value: str | list[str]
+) -> None:
+    """Test getting a resource asynchronously with different select parameter formats."""
+    resource_data = {"id": "RES-123", "name": "Test Resource"}
+    with respx.mock:
+        mock_route = respx.get(
+            "https://api.example.com/api/v1/test/RES-123", params={"select": "id,name"}
+        ).mock(return_value=httpx.Response(httpx.codes.OK, json=resource_data))
+
+        result = await async_dummy_service.get("RES-123", select=select_value)
+
+    request = mock_route.calls[0].request
+    accept_header = (b"Accept", b"application/json")
+    assert accept_header in request.headers.raw
+    assert result.to_dict() == resource_data
-
-async def test_async_get(async_dummy_service: AsyncDummyService) -> None:
-    """Test getting a resource asynchronously with a list select parameter."""
-    resource_data = {"id": "RES-123", "name": "Test Resource"}
-    with respx.mock:
-        mock_route = respx.get(
-            "https://api.example.com/api/v1/test/RES-123", params={"select": "id,name"}
-        ).mock(return_value=httpx.Response(httpx.codes.OK, json=resource_data))
-
-        result = await async_dummy_service.get("RES-123", select=["id", "name"])
-
-    request = mock_route.calls[0].request
-    accept_header = (b"Accept", b"application/json")
-    assert accept_header in request.headers.raw
-    assert result.to_dict() == resource_data
-
-
-async def test_async_get_select_str(async_dummy_service: AsyncDummyService) -> None:
-    """Test getting a resource asynchronously with a string select parameter."""
-    resource_data = {"id": "RES-123", "name": "Test Resource"}
-    with respx.mock:
-        mock_route = respx.get(
-            "https://api.example.com/api/v1/test/RES-123", params={"select": "id,name"}
-        ).mock(return_value=httpx.Response(httpx.codes.OK, json=resource_data))
-
-        result = await async_dummy_service.get("RES-123", select="id,name")
-
-    request = mock_route.calls[0].request
-    accept_header = (b"Accept", b"application/json")
-    assert accept_header in request.headers.raw
-    assert result.to_dict() == resource_data
mpt_api_client/http/mixins/resource_mixins.py (1)

7-24: Tighten docstring wording.

There’s repeated wording (“resource resources”) in multiple docstrings. Consider tightening for clarity.

✍️ Proposed cleanup
-class ModifiableResourceMixin[Model](GetMixin[Model], UpdateMixin[Model], DeleteMixin):
-    """Editable resource mixin allows to read and update a resource resources."""
+class ModifiableResourceMixin[Model](GetMixin[Model], UpdateMixin[Model], DeleteMixin):
+    """Editable resource mixin allows reading and updating resources."""

@@
-class AsyncModifiableResourceMixin[Model](
+class AsyncModifiableResourceMixin[Model](
     AsyncGetMixin[Model], AsyncUpdateMixin[Model], AsyncDeleteMixin
 ):
-    """Editable resource mixin allows to read and update a resource resources."""
+    """Editable resource mixin allows reading and updating resources."""

@@
-class ManagedResourceMixin[Model](CreateMixin[Model], ModifiableResourceMixin[Model]):
-    """Managed resource mixin allows to read, create, update and delete a resource resources."""
+class ManagedResourceMixin[Model](CreateMixin[Model], ModifiableResourceMixin[Model]):
+    """Managed resource mixin allows reading, creating, updating, and deleting resources."""

@@
-class AsyncManagedResourceMixin[Model](
+class AsyncManagedResourceMixin[Model](
     AsyncCreateMixin[Model], AsyncModifiableResourceMixin[Model]
 ):
-    """Managed resource mixin allows to read, create, update and delete a resource resources."""
+    """Managed resource mixin allows reading, creating, updating, and deleting resources."""
tests/unit/http/mixins/test_resource_mixins.py (1)

36-36: Fix test name typo for clarity.

test_modifieable_resource_mixin is misspelled; consider renaming to test_modifiable_resource_mixin.

✏️ Proposed rename
-def test_modifieable_resource_mixin(method_name: str) -> None:
+def test_modifiable_resource_mixin(method_name: str) -> None:

@albertsola albertsola force-pushed the MPT-16437/Reorganise-mixins branch from fd7377f to 92149de Compare February 2, 2026 11:26
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 2, 2026

@d3rky d3rky merged commit 0d09d83 into main Feb 2, 2026
4 checks passed
@d3rky d3rky deleted the MPT-16437/Reorganise-mixins branch February 2, 2026 13:05
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.

3 participants