core/.github/copilot-instructions.md

4.1 KiB

Instructions for GitHub Copilot

This repository holds the core of Home Assistant, a Python 3 based home automation application.

  • Python code must be compatible with Python 3.13
  • Use the newest Python language features if possible:
    • Pattern matching
    • Type hints
    • f-strings for string formatting over % or .format()
    • Dataclasses
    • Walrus operator
  • Code quality tools:
    • Formatting: Ruff
    • Linting: PyLint and Ruff
    • Type checking: MyPy
    • Testing: pytest with plain functions and fixtures
  • Inline code documentation:
    • File headers should be short and concise:
      """Integration for Peblar EV chargers."""
      
    • Every method and function needs a docstring:
      async def async_setup_entry(hass: HomeAssistant, entry: PeblarConfigEntry) -> bool:
          """Set up Peblar from a config entry."""
          ...
      
  • All code and comments and other text are written in American English
  • Follow existing code style patterns as much as possible
  • Core locations:
    • Shared constants: homeassistant/const.py, use them instead of hardcoding strings or creating duplicate integration constants.
    • Integration files:
      • Constants: homeassistant/components/{domain}/const.py
      • Models: homeassistant/components/{domain}/models.py
      • Coordinator: homeassistant/components/{domain}/coordinator.py
      • Config flow: homeassistant/components/{domain}/config_flow.py
      • Platform code: homeassistant/components/{domain}/{platform}.py
  • All external I/O operations must be async
  • Async patterns:
    • Avoid sleeping in loops
    • Avoid awaiting in loops, gather instead
    • No blocking calls
  • Polling:
    • Follow update coordinator pattern, when possible
    • Polling interval may not be configurable by the user
    • For local network polling, the minimum interval is 5 seconds
    • For cloud polling, the minimum interval is 60 seconds
  • Error handling:
    • Use specific exceptions from homeassistant.exceptions
    • Setup failures:
      • Temporary: Raise ConfigEntryNotReady
      • Permanent: Use ConfigEntryError
  • Logging:
    • Message format:
      • No periods at end
      • No integration names or domains (added automatically)
      • No sensitive data (keys, tokens, passwords), even when those are incorrect.
    • Be very restrictive on the use of logging info messages, use debug for anything which is not targeting the user.
    • Use lazy logging (no f-strings):
      _LOGGER.debug("This is a log message with %s", variable)
      
  • Entities:
    • Ensure unique IDs for state persistence:
      • Unique IDs should not contain values that are subject to user or network change.
      • An ID needs to be unique per platform, not per integration.
      • The ID does not have to contain the integration domain or platform.
      • Acceptable examples:
        • Serial number of a device
        • MAC address of a device formatted using homeassistant.helpers.device_registry.format_mac Do not obtain the MAC address through arp cache of local network access, only use the MAC address provided by discovery or the device itself.
        • Unique identifier that is physically printed on the device or burned into an EEPROM
      • Not acceptable examples:
        • IP Address
        • Device name
        • Hostname
        • URL
        • Email address
        • Username
      • For entities that are setup by a config entry, the config entry ID can be used as a last resort if no other Unique ID is available. For example: f"{entry.entry_id}-battery"
    • If the state value is unknown, use None
    • Do not use the unavailable string as a state value, implement the available() property method instead
    • Do not use the unknown string as a state value, use None instead
  • Extra entity state attributes:
    • The keys of all state attributes should always be present
    • If the value is unknown, use None
    • Provide descriptive state attributes
  • Testing:
    • Test location: tests/components/{domain}/
    • Use pytest fixtures from tests.common
    • Mock external dependencies
    • Use snapshots for complex data
    • Follow existing test patterns