-
-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor Manufacturer Identification #92
base: develop
Are you sure you want to change the base?
Conversation
Warning Rate limit exceeded@Alexwijn has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 33 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe pull request introduces a comprehensive refactoring of the manufacturer handling system in the SAT component. The primary changes involve simplifying the Changes
Possibly related PRs
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
6dcede0
to
571e110
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (11)
custom_components/sat/manufacturer.py (4)
28-31
: Add a docstring to clarify the identifier’s purpose.While the abstract property is adequate, a short docstring explaining what the identifier represents would help future maintainers.
43-43
: Consider logging unknown manufacturer names.Returning
None
is fine, but logging a warning or error would make it easier to debug issues if a wrong manufacturer name is provided.def resolve_by_name(name: str) -> Optional[Manufacturer]: + import logging + logger = logging.getLogger(__name__) if not (module := MANUFACTURERS.get(name)): + logger.warning(f"Unknown manufacturer name requested: {name}") return None return ManufacturerFactory._import_class(module, name)()
46-46
: Add error handling for module/class import.A try/except block would improve resilience if the module or class doesn’t exist. This can reduce cryptic import tracebacks and highlight configuration issues clearly.
def resolve_by_name(name: str) -> Optional[Manufacturer]: if not (module := MANUFACTURERS.get(name)): return None - return ManufacturerFactory._import_class(module, name)() + try: + manufacturer_class = ManufacturerFactory._import_class(module, name) + return manufacturer_class() + except (ImportError, AttributeError) as e: + import logging + logger = logging.getLogger(__name__) + logger.error(f"Failed to load manufacturer '{name}' from module '{module}': {e}") + return None
60-60
: Wrap dynamic import in a try/except block.A little extra caution can prevent unhandled exceptions if a module or class no longer exists or was renamed.
@staticmethod def _import_class(module_name: str, class_name: str): - return getattr(__import__(f"custom_components.sat.manufacturers.{module_name}", fromlist=[class_name]), class_name) + try: + mod = __import__(f"custom_components.sat.manufacturers.{module_name}", fromlist=[class_name]) + return getattr(mod, class_name) + except (ImportError, AttributeError) as e: + import logging + logger = logging.getLogger(__name__) + logger.error(f"Could not import '{class_name}' from module '{module_name}': {e}") + raisecustom_components/sat/manufacturers/other.py (1)
5-8
: Consider documenting the special identifier valueThe
-1
identifier is appropriate for a catch-all "Other" manufacturer, but it would be helpful to document why this special value was chosen.@property def identifier(self) -> int: + # Using -1 as a special identifier for the catch-all "Other" manufacturer return -1
custom_components/sat/manufacturers/nefit.py (1)
5-8
: Consider improving identifier managementThe current implementation uses magic numbers for manufacturer identifiers. Consider these improvements:
- Create an enum or constants file to centrally define all manufacturer identifiers
- Document the significance of these specific values
- Add validation to ensure uniqueness at runtime
Example implementation:
# custom_components/sat/const.py from enum import IntEnum, unique @unique class ManufacturerID(IntEnum): """Unique identifiers for each manufacturer.""" OTHER = -1 IDEAL = 6 SIME = 27 # Note: Currently conflicts with Immergas NEFIT = 131 # ... add other manufacturersThis approach would:
- Ensure uniqueness through the
@unique
decorator- Make it easier to track and maintain identifiers
- Provide better IDE support and type safety
custom_components/sat/manufacturers/radiant.py (1)
5-8
: LGTM! Consider adding documentationClean implementation with a unique identifier value. Consider adding a docstring to document the purpose of the identifier property and its usage.
@property def identifier(self) -> int: + """Return the unique manufacturer identifier. + + This identifier is used to uniquely identify the manufacturer across the system. + The value 41 is reserved for Radiant manufacturer. + """ return 41custom_components/sat/manufacturers/immergas.py (1)
5-8
: Add documentation for the identifier value.While the implementation is correct, consider adding a docstring to explain the significance of the identifier value
27
and its source/standard if applicable.@property def identifier(self) -> int: + """Return the manufacturer's unique identifier. + + Returns: + int: The unique identifier (27) for Immergas. + """ return 27custom_components/sat/manufacturers/vaillant.py (1)
5-8
: Add documentation for the identifier value.Consider adding a docstring to explain the significance of the identifier value
24
and its source/standard if applicable.@property def identifier(self) -> int: + """Return the manufacturer's unique identifier. + + Returns: + int: The unique identifier (24) for Vaillant. + """ return 24custom_components/sat/manufacturers/viessmann.py (2)
5-8
: Add documentation for the identifier value.Consider adding a docstring to explain the significance of the identifier value
33
and its source/standard if applicable.@property def identifier(self) -> int: + """Return the manufacturer's unique identifier. + + Returns: + int: The unique identifier (33) for Viessmann. + """ return 33
Line range hint
1-1
: Consider enhancing identifier management.To improve maintainability and prevent potential issues:
- Document the identifier scheme in a central location (e.g., in the base
Manufacturer
class)- Consider using an Enum or constants for manufacturer identifiers
- Add runtime validation to ensure identifier uniqueness across all manufacturer implementations
Example implementation:
# custom_components/sat/manufacturer.py from enum import IntEnum class ManufacturerID(IntEnum): VAILLANT = 24 IMMERGAS = 27 VIESSMANN = 33 INTERGAS = 173 # ... other manufacturers class Manufacturer: @property @abstractmethod def identifier(self) -> int: """Return the manufacturer's unique identifier. These identifiers are standardized values used to identify different manufacturers in the SAT protocol. Returns: int: A unique identifier from ManufacturerID enum """ pass
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
custom_components/sat/manufacturer.py
(2 hunks)custom_components/sat/manufacturers/atag.py
(1 hunks)custom_components/sat/manufacturers/baxi.py
(1 hunks)custom_components/sat/manufacturers/brotge.py
(1 hunks)custom_components/sat/manufacturers/dedietrich.py
(1 hunks)custom_components/sat/manufacturers/ferroli.py
(1 hunks)custom_components/sat/manufacturers/geminox.py
(1 hunks)custom_components/sat/manufacturers/ideal.py
(1 hunks)custom_components/sat/manufacturers/immergas.py
(1 hunks)custom_components/sat/manufacturers/intergas.py
(1 hunks)custom_components/sat/manufacturers/itho.py
(1 hunks)custom_components/sat/manufacturers/nefit.py
(1 hunks)custom_components/sat/manufacturers/other.py
(1 hunks)custom_components/sat/manufacturers/radiant.py
(1 hunks)custom_components/sat/manufacturers/remeha.py
(1 hunks)custom_components/sat/manufacturers/sime.py
(1 hunks)custom_components/sat/manufacturers/vaillant.py
(1 hunks)custom_components/sat/manufacturers/viessmann.py
(1 hunks)custom_components/sat/manufacturers/worcester.py
(1 hunks)
🔇 Additional comments (9)
custom_components/sat/manufacturer.py (2)
6-23
: Dictionary mapping appears solid.The simplified dictionary is much cleaner than a nested structure and straightforward to maintain. Ensure that all entries align with the corresponding classes and that any class naming/case matches the dictionary keys to avoid import errors.
52-54
: Instantiation for every entry is acceptable given a small dictionary size.This list comprehension instantiates each manufacturer class to compare identifiers. Since the dictionary is small, performance impact is negligible. If the list grows significantly, consider caching or indexing by identifier.
custom_components/sat/manufacturers/atag.py (1)
5-7
: Ensure the identifier matches ATAG’s actual member ID.Returning 4 fulfills the new contract. Confirm that this value doesn’t collide with another manufacturer’s identifier unless that is intentional.
custom_components/sat/manufacturers/baxi.py (1)
5-7
: Verify that using the same identifier as ATAG is intended.With both ATAG and Baxi returning 4, it’s unclear if this allows proper disambiguation by ID in
resolve_by_member_id()
. If each brand truly needs a unique ID, consider updating one of them.custom_components/sat/manufacturers/ideal.py (1)
5-8
: LGTM!The implementation is correct and follows the established pattern. The identifier value appears to be unique.
custom_components/sat/manufacturers/nefit.py (1)
5-8
: LGTM!The implementation is correct and follows the established pattern. The identifier value appears to be unique.
custom_components/sat/manufacturers/ferroli.py (1)
5-8
: LGTM!Clean implementation with a unique identifier value.
custom_components/sat/manufacturers/itho.py (1)
4-11
: LGTM! Clean implementation of the Itho manufacturerThe implementation follows the established pattern and uses a unique identifier.
custom_components/sat/manufacturers/remeha.py (1)
4-11
: LGTM! Clean implementation of the Remeha manufacturerThe implementation follows the established pattern and uses a unique identifier.
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
custom_components/sat/config_flow.py
(1 hunks)custom_components/sat/manufacturer.py
(1 hunks)custom_components/sat/manufacturers/atag.py
(1 hunks)custom_components/sat/manufacturers/baxi.py
(1 hunks)custom_components/sat/manufacturers/brotge.py
(1 hunks)custom_components/sat/manufacturers/de_dietrich.py
(1 hunks)custom_components/sat/manufacturers/ferroli.py
(1 hunks)custom_components/sat/manufacturers/geminox.py
(1 hunks)custom_components/sat/manufacturers/ideal.py
(1 hunks)custom_components/sat/manufacturers/immergas.py
(1 hunks)custom_components/sat/manufacturers/intergas.py
(1 hunks)custom_components/sat/manufacturers/itho.py
(1 hunks)custom_components/sat/manufacturers/nefit.py
(1 hunks)custom_components/sat/manufacturers/other.py
(1 hunks)custom_components/sat/manufacturers/radiant.py
(1 hunks)custom_components/sat/manufacturers/remeha.py
(1 hunks)custom_components/sat/manufacturers/sime.py
(1 hunks)custom_components/sat/manufacturers/vaillant.py
(1 hunks)custom_components/sat/manufacturers/viessmann.py
(1 hunks)custom_components/sat/manufacturers/worcester.py
(1 hunks)tests/test_manufacturer.py
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
- custom_components/sat/manufacturers/intergas.py
- custom_components/sat/manufacturers/remeha.py
- custom_components/sat/manufacturers/brotge.py
- custom_components/sat/manufacturers/ferroli.py
- custom_components/sat/manufacturers/ideal.py
- custom_components/sat/manufacturers/immergas.py
- custom_components/sat/manufacturers/itho.py
- custom_components/sat/manufacturers/vaillant.py
- custom_components/sat/manufacturers/baxi.py
- custom_components/sat/manufacturers/geminox.py
- custom_components/sat/manufacturers/radiant.py
- custom_components/sat/manufacturers/nefit.py
- custom_components/sat/manufacturers/atag.py
- custom_components/sat/manufacturers/viessmann.py
- custom_components/sat/manufacturers/worcester.py
- custom_components/sat/manufacturers/other.py
- custom_components/sat/manufacturers/sime.py
🧰 Additional context used
🪛 Ruff (0.8.2)
tests/test_manufacturer.py
6-6: Loop control variable module
not used within loop body
Rename unused module
to _module
(B007)
🪛 GitHub Actions: Run PyTest Unit Tests
tests/test_manufacturer.py
[error] 18-18: AttributeError: type object 'ManufacturerFactory' has no attribute 'all'
🔇 Additional comments (7)
custom_components/sat/manufacturers/de_dietrich.py (1)
6-6
: LGTM!The renaming from
name
tofriendly_name
aligns with the abstract base class contract and standardizes the naming convention across manufacturer classes.tests/test_manufacturer.py (1)
Line range hint
55-57
: LGTM!The implementation correctly resolves manufacturers by member ID using the simplified data structure.
🧰 Tools
🪛 Ruff (0.8.2)
6-6: Loop control variable
module
not used within loop bodyRename unused
module
to_module
(B007)
custom_components/sat/config_flow.py (1)
492-492
: LGTM!The change to use
friendly_name
aligns with the manufacturer refactoring.custom_components/sat/manufacturer.py (4)
1-2
: LGTM!Good use of ABC to enforce the contract for manufacturer classes and proper type hints.
7-24
: LGTM!The simplified MANUFACTURERS dictionary is more maintainable and easier to understand.
28-38
: LGTM!Good design choices:
- Making Manufacturer an abstract base class
- Adding proper member_id initialization
- Using @AbstractMethod to enforce friendly_name implementation
46-49
: LGTM!The factory methods have been updated correctly to work with the new data structure and properly handle dynamic imports.
Also applies to: 61-63
✅ Actions performedSummary regeneration triggered. |
Summary by CodeRabbit
New Features
Itho
manufacturer class.Remeha
manufacturer class.Worcester
manufacturer.Refactoring
name
method tofriendly_name
across all manufacturer classes.Manufacturer
base class to be an abstract base class.Bug Fixes
friendly_name
.