Skip to content

Conversation

@albertsola
Copy link
Contributor

@albertsola albertsola commented Dec 10, 2025

Summary by CodeRabbit

  • Refactor

    • Enhanced type consistency across account and module service classes for improved type safety and better IDE support.
    • Aligned generic type parameters in service mixins to accurately match their specific resource types.
  • Chores

    • Added type annotations to improve static code analysis in seed utilities.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link

github-actions bot commented Dec 10, 2025

Warnings
⚠️

This PR modifies code (7 file(s)) but does not include any changes in the tests/ folder.

Please consider adding or updating tests to cover your changes.

✅ Found Jira issue key in the title: MPT-16304

Generated by 🚫 dangerJS against 5f5a229

@coderabbitai
Copy link

coderabbitai bot commented Dec 10, 2025

Walkthrough

This pull request updates generic type parameters across multiple service classes in the mpt_api_client library, replacing the generic Model placeholder with specific resource types (Account, Buyer, Licensee, Module) in file-related and functionality mixins. Additionally, type-ignore annotations are added to seed files to suppress static analysis warnings.

Changes

Cohort / File(s) Change Summary
Service type parameter corrections
mpt_api_client/resources/accounts/account.py, mpt_api_client/resources/accounts/buyers.py, mpt_api_client/resources/accounts/licensees.py, mpt_api_client/resources/accounts/modules.py
Updated AccountsService, AsyncAccountsService, BuyersService, AsyncBuyersService, LicenseesService, and AsyncLicenseesService class signatures to replace Model type parameter with resource-specific types (Account, Buyer, Licensee, Module) across CreateFileMixin, UpdateFileMixin, ActivatableMixin, EnablableMixin, ValidateMixin, and AsyncCollectionMixin.
Type-ignore annotations
seed/accounts/buyer.py, seed/accounts/licensee.py, seed/accounts/module.py
Added type: ignore[unreachable] annotations to suppress static type checker warnings on unreachable code paths in initialization failure branches.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • The changes follow a consistent, homogeneous pattern of replacing a single type parameter across multiple files
  • Type parameter replacements are straightforward generic type updates with no control-flow modifications
  • Type-ignore annotations are trivial additions
  • Areas to verify: compatibility of resource-specific types with their respective mixins and absence of downstream typing side effects

Possibly related PRs

Suggested reviewers

  • d3rky
  • svazquezco
  • alephsur
  • ruben-sebrango
  • jentyk

Poem

🐰 A rabbit hops through types so true,
From Model's mist to Account's view,
Each service now knows what it holds,
Generic constraints break their molds,
Type safety shines, so clean and bright!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing generic Model type parameters with specific resource types (Account, Buyer, Licensee, Module) in service class mixins across multiple files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ 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 MPT-16304-Ensure-the-correct-model-is-uses-on-Resource-Services

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.

@albertsola albertsola self-assigned this Dec 10, 2025
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

🧹 Nitpick comments (3)
seed/accounts/module.py (1)

47-55: Unreachable warning suppression is reasonable; consider structural alternative

Using # type: ignore[unreachable] on the warning is consistent with the static type that modules[0] is always Module, while still keeping a runtime safeguard if something goes wrong at runtime. If you want to avoid ignores, an alternative would be to replace the if isinstance(first_module, Module): ... else: pattern with an assert isinstance(first_module, Module) before using it, which most type checkers accept without raising unreachable warnings.

seed/accounts/licensee.py (1)

81-94: Type-ignore for unreachable warning path is acceptable

Given that mpt_client.accounts.licensees.create is now generically parameterized with Licensee, the isinstance(created, Licensee) guard is statically redundant and the warning branch is considered unreachable by type checkers. The # type: ignore[unreachable] keeps the defensive log + exception without fighting the type checker, which is fine here. As a minor alternative, an assert isinstance(created, Licensee) would both satisfy the type checker and still fail loudly if the API ever returned an unexpected type.

seed/accounts/buyer.py (1)

71-83: Consistent unreachable warning suppression with other seed modules

Here as well, the created value is statically a Buyer, so the failure branch is unreachable to the type checker. Adding # type: ignore[unreachable] on the warning keeps runtime safety and aligns this file with licensee.py and module.py. Same optional refinement: an assert isinstance(created, Buyer) could remove the need for the ignore entirely.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d927ac4 and 5f5a229.

📒 Files selected for processing (7)
  • mpt_api_client/resources/accounts/account.py (2 hunks)
  • mpt_api_client/resources/accounts/buyers.py (2 hunks)
  • mpt_api_client/resources/accounts/licensees.py (2 hunks)
  • mpt_api_client/resources/accounts/modules.py (1 hunks)
  • seed/accounts/buyer.py (1 hunks)
  • seed/accounts/licensee.py (1 hunks)
  • seed/accounts/module.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
seed/accounts/licensee.py (1)
tests/e2e/conftest.py (1)
  • logger (63-64)
mpt_api_client/resources/accounts/modules.py (2)
mpt_api_client/http/mixins.py (2)
  • AsyncGetMixin (380-395)
  • AsyncCollectionMixin (538-605)
mpt_api_client/http/async_service.py (1)
  • AsyncService (12-80)
seed/accounts/module.py (1)
tests/e2e/conftest.py (1)
  • logger (63-64)
mpt_api_client/resources/accounts/buyers.py (1)
mpt_api_client/resources/accounts/mixins.py (6)
  • ActivatableMixin (4-27)
  • EnablableMixin (30-53)
  • ValidateMixin (56-68)
  • AsyncActivatableMixin (134-159)
  • AsyncEnablableMixin (162-185)
  • AsyncValidateMixin (188-200)
mpt_api_client/resources/accounts/licensees.py (2)
mpt_api_client/http/mixins.py (2)
  • CreateFileMixin (115-144)
  • UpdateFileMixin (147-184)
mpt_api_client/resources/accounts/mixins.py (2)
  • EnablableMixin (30-53)
  • AsyncEnablableMixin (162-185)
⏰ 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: build
🔇 Additional comments (4)
mpt_api_client/resources/accounts/modules.py (1)

29-31: AsyncModulesService now correctly parameterized with Module

Switching AsyncCollectionMixin from Model to Module brings the async service in line with the sync ModulesService and ensures that iterate, fetch_page, etc. are typed as handling Module objects. This directly supports the PR goal of using the correct model type in services.

mpt_api_client/resources/accounts/licensees.py (1)

35-44: Licensees services now fully specialized on Licensee instead of base Model

Updating CreateFileMixin, UpdateFileMixin, and EnablableMixin (and their async counterparts) to use Licensee tightens typing so all operations in these services consistently return Licensee. This matches the config’s _model_class = Licensee and avoids generic Model leakage in public APIs.

Also applies to: 48-57

mpt_api_client/resources/accounts/account.py (1)

41-51: Accounts services correctly use Account for all mixin generics

Changing CreateFileMixin, UpdateFileMixin, ActivatableMixin, EnablableMixin, and ValidateMixin (and their async variants) to [...] [Account] removes the last uses of the generic Model in these service signatures. This makes the API surface more precise (everything is typed as Account) without affecting runtime behavior.

Also applies to: 61-71

mpt_api_client/resources/accounts/buyers.py (1)

40-51: Buyers services now consistently parameterized with Buyer

Using Buyer as the type argument for all (async) file and status/validation mixins aligns with _model_class = Buyer and with the explicit Buyer return types of synchronize and transfer. This improves type safety for callers relying on these service classes.

Also applies to: 73-84

@sonarqubecloud
Copy link

@d3rky d3rky merged commit ee74fde into main Dec 10, 2025
6 checks passed
@d3rky d3rky deleted the MPT-16304-Ensure-the-correct-model-is-uses-on-Resource-Services branch December 10, 2025 11:25
context.set_resource("accounts.module", first_module)
return first_module
logger.warning("First module is not a Module instance.")
logger.warning("First module is not a Module instance.") # type: ignore[unreachable]
Copy link
Contributor

Choose a reason for hiding this comment

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

Be careful with this kind of errors, we shouldn't ignore it since it mens the code after this point will never run. Did you check that the typing is correct? did you try using cast method?

I'd be great to improve a bit this logic using guard clauses or early returns, that way we avoid the spaguetti code and it's simpler to read and understand

Something like ->

    """Refresh module in context (always fetch)."""
    module = await get_module(context=context, mpt_operations=mpt_operations)
    if module:
        return module

    filtered_modules = mpt_operations.accounts.modules.filter(
        RQLQuery(name="Access Management")
    )
    modules = [mod async for mod in filtered_modules.iterate()]
    if not modules:
        logger.warning("Module 'Access Management' not found.")
        return None

    first_module = modules[0]
    if not isinstance(first_module, Module):
        logger.warning("First module is not a Module instance.")  # type: ignore[unreachable]
        return None
    
    context["accounts.module.id"] = first_module.id
    context.set_resource("accounts.module", first_module)
    return first_module

logger.info("Licensee created: %s", created.id)
return created
logger.warning("Licensee creation failed")
logger.warning("Licensee creation failed") # type: ignore[unreachable]
Copy link
Contributor

Choose a reason for hiding this comment

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

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