Conversation
…in-pollensensor Handle missing source in device info
|
/gemini review |
There was a problem hiding this comment.
Code Review
This is a massive and impressive pull request that significantly refactors the integration for improved robustness, maintainability, and adherence to modern Home Assistant practices. The extraction of the API client and coordinator, the move to per-entry runtime data, and the comprehensive enhancements to validation and error handling are all excellent changes. The expansion of the test suite is particularly noteworthy and provides strong confidence in the stability of this major refactoring. I have one suggestion regarding code duplication for a parsing helper, but overall, this is an exemplary contribution.
…er-parsing Codex-generated pull request
…g-and-masking Harden API key validation and mask API key input in config flow
|
/gemini review |
There was a problem hiding this comment.
Code Review
This is an extensive and high-quality pull request that significantly refactors the integration. The changes, including the extraction of the API client and coordinator, the introduction of a runtime data container, and the complete overhaul of the config flow with improved validation and error handling, are excellent. The test suite has been massively expanded, covering migrations, validation, and even translation key discovery, which is impressive. The code is robust, secure, and follows modern Home Assistant best practices. I have reviewed the changes thoroughly and could not find any issues of medium or higher severity. This is an outstanding contribution.
…-forecast_days-parsing Localize D+2 wording in non-English translations
|
Persistent suggestions updated to latest commit 4edfc09 |
…abled-d+1/d+2-sensors Harden dailyInfo validation, coordinator parsing, per-day sensor gating, and improve test isolation
|
/gemini review |
There was a problem hiding this comment.
Code Review
The pull request introduces a significant refactoring of the Pollen Levels integration, moving the API client and data update coordinator into dedicated modules and adopting the modern runtime_data pattern for config entries. The enhanced validation in the config flow and the robust error handling in the HTTP client are excellent improvements. I have identified a minor issue in the test mocks where a synchronous Home Assistant function is mocked as asynchronous, which should be corrected to align with best practices.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
|
/improve |
|
Persistent suggestions updated to latest commit 57796fe |
…ate-behavior Finalize 1.9.3 changelog with Retry-After hardening details
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Update README.md
PR Type
Enhancement, Tests, Bug fix, Documentation
Description
Major refactoring: Extracted
PollenDataUpdateCoordinatorandGooglePollenApiClientinto separate modules (coordinator.py,client.py) with comprehensive HTTP retry logic and error handlingNew runtime data management: Introduced
PollenLevelsRuntimeDatadataclass and migration logic to store coordinator/client instances per config entry instead of inhass.dataEnhanced config flow validation: Refactored with dynamic schema builders, comprehensive input validation (API key, coordinates, intervals, forecast days), and improved error handling distinguishing between auth failures and update failures
Improved error handling: Added
extract_error_message()utility for safe HTTP response parsing, API key redaction in logs, andRetry-Afterheader parsing for rate limit resilienceSetup validation: Implemented coordinate validation (finite values, in-range checks), numeric option sanitization, and config entry setup with initial data refresh
Comprehensive test expansion: Added 30+ new test cases covering migration logic, validation bounds, HTTP error handling, diagnostics privacy, and translation key discovery
Translation updates: Enhanced all 25 language files with new configuration fields (
forecast_days,create_forecast_sensors), error message placeholders, and improved descriptionsDocumentation improvements: Updated README with selector notation clarification, API setup guidance, troubleshooting section, and added CONTRIBUTING.md with code standards
Bug fix: Improved async test detection in pytest configuration using
inspect.iscoroutinefunction()Version bump: Updated to 1.9.2 with detailed changelog documenting all changes
Diagram Walkthrough
File Walkthrough
6 files
test_sensor.py
Refactor tests to use injected client and coordinator modulestests/test_sensor.py
_StubSensorEntitywithunique_idanddevice_infopropertiesto support entity registry testing
_stub_parse_http_date()function to parse HTTP-date formattedretry headers
client_modandcoordinator_modmodules instead of monkeypatchingdailyInfo handling, color channel validation, and deterministic key
ordering
GooglePollenApiClientandPollenDataUpdateCoordinatordirectly with proper client injectionRegistryEntryto useNamedTupleand updatedRegistryStubtosupport
async_entries_for_config_entry()methodauth/forbidden error handling tests
test_translations.py
Enhance translation tests with services and sensor key validationtests/test_translations.py
_extract_services_from_services_yaml()to parse service namesfrom services.yaml without PyYAML
_extract_service_labels_from_services_yaml()to extractname/description labels from services.yaml
_extract_sensor_translation_key_usage()to discover entity anddevice translation keys from sensor.py AST
_extract_schema_key_aliases()to resolve schema key wrapperaliases like
location_field = vol.Required(CONF_LOCATION)_fields_from_schema_call()to return tuple of (fields,sections) and support nested
section()wrappers_extract_helper_error_keys()to discover error keys emitted byhelper functions like
_parse_int_option()_ScopedErrorsVisitorto collect helper-propagated errors inclass scopes
test_config_flow_extractor_includes_helper_error_keys(),test_sensor_translation_keys_present(),test_services_translation_keys_present(),test_services_yaml_labels_match_translations()test_init.py
Comprehensive test infrastructure expansion with migration andvalidation teststests/test_init.py
(sensor, const, aiohttp, helpers, entity_registry, entity, dt, util,
update_coordinator) to support integration testing
_FakeConfigEntriesand_FakeEntryclasses with additionalattributes (
data,options,version,runtime_data) and methods(
async_update_entry,async_entries)_ServiceRegistryclass to mock Home Assistant serviceregistration and calling
(missing API key, invalid/out-of-range coordinates, boundary
conditions, decimal options)
cleanup, and per-day sensor mode normalization across data/options
runtime_datacoordinatorassignment and cleanup
test_config_flow.py
Enhanced test stubs and validation test coverage for config flowtests/test_config_flow.py
_force_module()helper to replacesetdefault()calls,ensuring test stubs override pre-existing modules
NumberSelector,TextSelector,SelectSelectorand their config classes_StubResponsewithjson()andtext()async methods forrealistic HTTP response handling
add_suggested_values_to_schema()method to_StubConfigFlowforform schema manipulation
error code mapping, API key redaction, and error placeholder
management
_parse_int_option()helper validatingnon-finite and decimal value rejection
test_diagnostics.py
New diagnostics test module for privacy and payload validationtests/test_diagnostics.py
payload sizing
value handling
entry data
test_options_flow.py
Options flow validation and schema sanitization teststests/test_options_flow.py
handling
(update interval, forecast days, sensor mode)
during form rendering
8 files
config_flow.py
Refactor config flow with comprehensive validation and UI improvementscustom_components/pollenlevels/config_flow.py
VERSIONfrom 1 to 3 to trigger re-validation of existingentries
_build_step_user_schema()thatdynamically constructs form with all fields (API key, location,
interval, language, forecast days, sensor mode)
_parse_int_option(),_parse_update_interval(),_sanitize_*_for_default()for robust input validation and clamping_async_validate_input()to validate all config options(interval, forecast days, sensor mode compatibility) and extract error
messages from API responses
with invalid key message (auth failed), and 403 forbidden (update
failed)
async_step_init()(options flow) to use the new schemabuilders and validation helpers
NumberSelector,SelectSelector,TextSelectorandrelated config classes
util.py
Add utility functions for error extraction and mode normalizationcustom_components/pollenlevels/util.py
extract_error_message()async function to safely extract andnormalize error messages from HTTP responses
normalize_sensor_mode()function to validate and defaultforecast sensor mode with logging
__all__export list to include new functionsClientResponsetype hint with runtimefallback
coordinator.py
New coordinator module with data update and forecast processingcustom_components/pollenlevels/coordinator.py
PollenDataUpdateCoordinatorclass from sensor.pywith full pollen data fetch and forecast processing logic
(
_normalize_channel,_rgb_from_api,_rgb_to_hex_triplet) and plantcode normalization
(
_process_forecast_attributes) with trend calculation and expectedpeak detection
inSeasonand health recommendationscolor handling
__init__.py
Migration logic, setup validation, and runtime data managementcustom_components/pollenlevels/init.py
async_migrate_entry()function to migrate per-day sensor modefrom data to options and clean up legacy keys
presence, coordinate validation (finite and in-range), numeric option
sanitization
PollenDataUpdateCoordinatorandGooglePollenApiClientinstantiation during setup with initial data refresh
async_setup()service handler to useentry.runtime_dataforcoordinator access and improved error logging with API key redaction
async_unload_entry()to clearruntime_datainstead of managinghass.datadictionaryexecution
client.py
New HTTP client with retry logic and error handlingcustom_components/pollenlevels/client.py
GooglePollenApiClientfor Google Pollen APIHTTP requests with retry logic
and transient failures (timeout, network errors)
ConfigEntryAuthFailed, 403 checks for invalid API key messageRetry-Afterheader parsing and jittered exponential backofffor resilient API calls
logging
diagnostics.py
Runtime data access and defensive numeric handling in diagnosticscustom_components/pollenlevels/diagnostics.py
entry.runtime_datainstead ofhass.datadictionarywith
math.isfinite()checks(MIN/MAX_FORECAST_DAYS) in diagnostics examples
data_keys_totalfield and truncateddata_keyslist to first 50items to limit payload size
rounded coordinates in request examples
const.py
New constants for validation bounds and API configurationcustom_components/pollenlevels/const.py
MIN_UPDATE_INTERVAL_HOURS,MAX_UPDATE_INTERVAL_HOURS,MIN_FORECAST_DAYSPOLLEN_API_TIMEOUT,MAX_RETRIES,POLLEN_API_KEY_URL,RESTRICTING_API_KEYS_URLis_invalid_api_key_message()function to detect invalidAPI key error messages
ATTRIBUTIONconstant for data source attributionFORECAST_SENSORS_CHOICESto explicit list type annotationruntime.py
New runtime data container for config entry statecustom_components/pollenlevels/runtime.py
PollenLevelsRuntimeDatadataclass to holdcoordinator and client instances per config entry
PollenLevelsConfigEntryfor type-hinted config entryaccess to runtime data
1 files
sensor.py
Extract coordinator and runtime data to separate modulescustom_components/pollenlevels/sensor.py
PollenDataUpdateCoordinatorclass (moved to separatecoordinator.pymodule)_normalize_channel(),_rgb_from_api(),_rgb_to_hex_triplet()(moved to coordinator)async_setup_entry()to retrieve coordinator fromconfig_entry.runtime_datainstead of creating it inlineForecastSensorModeenum for type-safe forecast sensor modevalues
PollenLevelsConfigEntryandPollenLevelsRuntimeDatatypes from newruntime.pymoduleaiohttp,random,asynciofrom coordinatorlogic
PollenSensor.extra_state_attributes()to excludecolor_rawfrom public attributes
device_infoproperty to infer group type when missing fromdata
ATTRIBUTIONfrom constmodule
3 files
__init__.py
Mark tests directory as a Python packagetests/init.py
__init__.pyfile to mark tests directory as a packagethird-party
testspackagepyproject.toml
Version bump and pytest configuration updatespyproject.toml
name collisions
manifest.json
Version update in manifestcustom_components/pollenlevels/manifest.json
26 files
services.yaml
Add service metadata for force_update actioncustom_components/pollenlevels/services.yaml
namefield with value "Force Update" to theforce_updateservicedescriptionfield explaining the service purposeCHANGELOG.md
Detailed release notes for versions 1.9.2, 1.9.1, and 1.9.0-rc1CHANGELOG.md
coordinator updates, coordinate validation, and numeric parsing
hardening
redaction, and service improvements
data migration, client extraction, HTTP error handling, and migration
logic
clarity
cs.json
Czech translation updates for new fields and error messagescustom_components/pollenlevels/translations/cs.json
practices link
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed error context
invalid_update_intervalandinvalid_forecast_dayswith localized messagescodes
hu.json
Hungarian translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/hu.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowuk.json
Ukrainian translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/uk.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowpl.json
Polish translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/pl.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowca.json
Catalan translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/ca.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowfi.json
Finnish translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/fi.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowro.json
Romanian translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/ro.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowsv.json
Swedish translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/sv.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowit.json
Italian translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/it.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowfr.json
French translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/fr.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flownb.json
Norwegian Bokmål translation updates for enhanced configuration anderror handlingcustom_components/pollenlevels/translations/nb.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowru.json
Russian translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/ru.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowda.json
Danish translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/da.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowde.json
German translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/de.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowzh-Hant.json
Traditional Chinese translation updates for enhanced configuration anderror handlingcustom_components/pollenlevels/translations/zh-Hant.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flownl.json
Dutch translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/nl.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowes.json
Spanish translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/es.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowpt-PT.json
Portuguese (Portugal) translation updates for enhanced configurationand error handlingcustom_components/pollenlevels/translations/pt-PT.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowpt-BR.json
Portuguese (Brazil) translation updates for enhanced configuration anderror handlingcustom_components/pollenlevels/translations/pt-BR.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowzh-Hans.json
Simplified Chinese translation updates for enhanced configuration anderror handlingcustom_components/pollenlevels/translations/zh-Hans.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowen.json
English translation updates for enhanced configuration and errorhandlingcustom_components/pollenlevels/translations/en.json
and best practices
forecast_daysandcreate_forecast_sensors{error_message}placeholder fordetailed API responses
invalid_update_intervalandinvalid_forecast_daysD+2toD+1+2in options flowREADME.md
Documentation updates for configuration options and API setup guidanceREADME.md
D+1+2notation forcreating both D+1 and D+2 sensors
API setup and security best practices
recommendations
causes
color_rawfrom rich attributes listCONTRIBUTING.md
New contributing guidelines for code standards and translationsCONTRIBUTING.md
en.jsonwith syncrequirements
AGENTS.md
Translation guidance updates for agent instructionsAGENTS.md
en.jsonstrings.json1 files
conftest.py
Improved async test detection in pytest configurationtests/conftest.py
pytest_pyfunc_call()to useinspect.iscoroutinefunction()instead of
asyncio.iscoroutinefunction()for more reliable async testdetection