fix: add missing Device and Component fields for deserialization#530
Open
bobmatnyc wants to merge 5 commits intopySmartThings:mainfrom
Open
fix: add missing Device and Component fields for deserialization#530bobmatnyc wants to merge 5 commits intopySmartThings:mainfrom
bobmatnyc wants to merge 5 commits intopySmartThings:mainfrom
Conversation
- Exclude AI-generated documentation (CLAUDE.md, ARCHITECTURE.md, PROJECT_VALIDATION.md) - Exclude Claude MPM configuration directories (.claude-mpm/, .claude/) - Consolidate existing Claude-related ignore patterns - Add comprehensive file type exclusions for development tools These files are AI agent-specific and should not be committed to the repository. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Addresses pySmartThings#295 - Documentation request from users Addresses pySmartThings#69 - Lock code example request Changes: - Add examples/ directory with 6 working Python examples - Add examples/README.md with setup and usage instructions - Update README.md with Usage section and quick start - Update .gitignore to exclude temporary docs (docs/bobmatnyc/) - Update .gitignore to exclude .mcp.json (environment-specific) Examples added: - basic_usage.py: Authentication, device listing, status checks - control_devices.py: Control switches, dimmers, colors, thermostats - scenes.py: Scene management and execution - lock_codes.py: Lock code management (SET_CODE, DELETE_CODE) - event_subscription.py: Real-time SSE event handling - async_patterns.py: Production-ready async patterns All examples follow project conventions: - Python 3.12+ async/await syntax - Type hints throughout - Google-style docstrings - Proper error handling - 88-character line length
- Add examples/ to .pre-commit-config.yaml pylint exclude - Add mypy override for examples.* module in pyproject.toml - Add examples to pylint ignore list in pyproject.toml - Examples are demonstration code with intentional patterns - Mashumaro dynamic attributes cause mypy false positives
…martThings#529) Changes: - Added optional field to Component model - Changed relationships type to dict | list | None to handle API variations - Updated Device.__pre_deserialize__ to normalize empty values: * Convert empty relationships list [] to None * Convert empty viper dict {} to None - Fixed test_connection.py to access capabilities via components Fixes pySmartThings#529 Testing: - Verified deserialization of all 184 real devices from SmartThings API - All quality checks passing (ruff, mypy, pylint) 🤖👥 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #529 by adding missing fields to the Device and Component models that were causing deserialization failures.
Changes
optionalfield to Component model - The SmartThings API returnsoptional: falsein component objects, but our Component dataclass was missing this fieldrelationshipstype fromdict | Nonetodict | list | Noneto handle API variations where some devices return empty lists, non-empty lists, or dictsDevice.__pre_deserialize__()to normalize empty values:[]toNone{}toNone(since Viper model has required fields)device.components["main"].capabilitiesTesting
✅ Verified deserialization of all 184 real devices from my SmartThings account
✅ All quality checks passing:
Root Cause
The SmartThings API has inconsistent data structures:
relationships: [](empty list)relationships: [{'deviceId': '...', 'relationshipType': 'COMBINATION', ...}](non-empty list)viper: {}(empty dict, but Viper model expects required fields)optional: false(field was missing from our model)The fix handles all these variations gracefully while maintaining type safety.
Developer's Certificate of Origin
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.