From 0a0a96fb3b05df0b030e9748ff3de437c9be8914 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 19 Feb 2025 21:52:20 +0100 Subject: [PATCH] Add initial basic GitHub Copilot instructions (#137754) Co-authored-by: Martin Hjelmare Co-authored-by: Joost Lekkerkerker --- .github/copilot-instructions.md | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000000..06499d62b9e --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,100 @@ +# 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: + ```python + """Integration for Peblar EV chargers.""" + ``` + - Every method and function needs a docstring: + ```python + 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): + ```python + _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