Skip to content

Commit 706add4

Browse files
akxfrenck
andauthored
Switch formatting from black to ruff-format (home-assistant#102893)
Co-authored-by: Franck Nijhof <[email protected]>
1 parent cf9b0e8 commit 706add4

File tree

161 files changed

+531
-608
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

161 files changed

+531
-608
lines changed

.devcontainer/devcontainer.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"customizations": {
1111
"vscode": {
1212
"extensions": [
13-
"ms-python.black-formatter",
13+
"charliermarsh.ruff",
1414
"ms-python.pylint",
1515
"ms-python.vscode-pylance",
1616
"visualstudioexptteam.vscodeintellicode",
@@ -39,7 +39,10 @@
3939
"!include_dir_list scalar",
4040
"!include_dir_merge_list scalar",
4141
"!include_dir_merge_named scalar"
42-
]
42+
],
43+
"[python]": {
44+
"editor.defaultFormatter": "charliermarsh.ruff"
45+
}
4346
}
4447
}
4548
}

.github/PULL_REQUEST_TEMPLATE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
- [ ] There is no commented out code in this PR.
6161
- [ ] I have followed the [development checklist][dev-checklist]
6262
- [ ] I have followed the [perfect PR recommendations][perfect-pr]
63-
- [ ] The code has been formatted using Black (`black --fast homeassistant tests`)
63+
- [ ] The code has been formatted using Ruff (`ruff format homeassistant tests`)
6464
- [ ] Tests have been added to verify that the new code works.
6565

6666
If user exposed functionality or configuration variables are added/changed:

.github/workflows/ci.yaml

+6-31
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ env:
3636
CACHE_VERSION: 5
3737
PIP_CACHE_VERSION: 4
3838
MYPY_CACHE_VERSION: 6
39-
BLACK_CACHE_VERSION: 1
4039
HA_SHORT_VERSION: "2023.12"
4140
DEFAULT_PYTHON: "3.11"
4241
ALL_PYTHON_VERSIONS: "['3.11', '3.12']"
@@ -58,7 +57,6 @@ env:
5857
POSTGRESQL_VERSIONS: "['postgres:12.14','postgres:15.2']"
5958
PRE_COMMIT_CACHE: ~/.cache/pre-commit
6059
PIP_CACHE: /tmp/pip-cache
61-
BLACK_CACHE: /tmp/black-cache
6260
SQLALCHEMY_WARN_20: 1
6361
PYTHONASYNCIODEBUG: 1
6462
HASS_CI: 1
@@ -261,8 +259,8 @@ jobs:
261259
. venv/bin/activate
262260
pre-commit install-hooks
263261
264-
lint-black:
265-
name: Check black
262+
lint-ruff-format:
263+
name: Check ruff-format
266264
runs-on: ubuntu-22.04
267265
needs:
268266
- info
@@ -276,13 +274,6 @@ jobs:
276274
with:
277275
python-version: ${{ env.DEFAULT_PYTHON }}
278276
check-latest: true
279-
- name: Generate partial black restore key
280-
id: generate-black-key
281-
run: |
282-
black_version=$(cat requirements_test_pre_commit.txt | grep black | cut -d '=' -f 3)
283-
echo "version=$black_version" >> $GITHUB_OUTPUT
284-
echo "key=black-${{ env.BLACK_CACHE_VERSION }}-$black_version-${{
285-
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
286277
- name: Restore base Python virtual environment
287278
id: cache-venv
288279
uses: actions/cache/[email protected]
@@ -301,33 +292,17 @@ jobs:
301292
key: >-
302293
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
303294
needs.info.outputs.pre-commit_cache_key }}
304-
- name: Restore black cache
305-
uses: actions/[email protected]
306-
with:
307-
path: ${{ env.BLACK_CACHE }}
308-
key: >-
309-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
310-
steps.generate-black-key.outputs.key }}
311-
restore-keys: |
312-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-black-${{
313-
env.BLACK_CACHE_VERSION }}-${{ steps.generate-black-key.outputs.version }}-${{
314-
env.HA_SHORT_VERSION }}-
315-
- name: Run black (fully)
316-
if: needs.info.outputs.test_full_suite == 'true'
317-
env:
318-
BLACK_CACHE_DIR: ${{ env.BLACK_CACHE }}
295+
- name: Run ruff-format (fully)
319296
run: |
320297
. venv/bin/activate
321-
pre-commit run --hook-stage manual black --all-files --show-diff-on-failure
322-
- name: Run black (partially)
298+
pre-commit run --hook-stage manual ruff-format --all-files --show-diff-on-failure
299+
- name: Run ruff-format (partially)
323300
if: needs.info.outputs.test_full_suite == 'false'
324301
shell: bash
325-
env:
326-
BLACK_CACHE_DIR: ${{ env.BLACK_CACHE }}
327302
run: |
328303
. venv/bin/activate
329304
shopt -s globstar
330-
pre-commit run --hook-stage manual black --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*} --show-diff-on-failure
305+
pre-commit run --hook-stage manual ruff-format --files {homeassistant,tests}/components/${{ needs.info.outputs.integrations_glob }}/{*,**/*} --show-diff-on-failure
331306
332307
lint-ruff:
333308
name: Check ruff

.pre-commit-config.yaml

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.1.1
3+
rev: v0.1.6
44
hooks:
55
- id: ruff
66
args:
77
- --fix
8-
- repo: https://github.com/psf/black-pre-commit-mirror
9-
rev: 23.11.0
10-
hooks:
11-
- id: black
12-
args:
13-
- --quiet
8+
- id: ruff-format
149
files: ^((homeassistant|pylint|script|tests)/.+)?[^/]+\.py$
1510
- repo: https://github.com/codespell-project/codespell
1611
rev: v2.2.2

.vscode/extensions.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
{
2-
"recommendations": ["esbenp.prettier-vscode", "ms-python.python"]
2+
"recommendations": [
3+
"charliermarsh.ruff",
4+
"esbenp.prettier-vscode",
5+
"ms-python.python"
6+
]
37
}

Dockerfile.dev

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
55
# Uninstall pre-installed formatting and linting tools
66
# They would conflict with our pinned versions
77
RUN \
8-
pipx uninstall black \
9-
&& pipx uninstall pydocstyle \
8+
pipx uninstall pydocstyle \
109
&& pipx uninstall pycodestyle \
1110
&& pipx uninstall mypy \
1211
&& pipx uninstall pylint

homeassistant/auth/permissions/types.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55

66
ValueType = (
77
# Example: entities.all = { read: true, control: true }
8-
Mapping[str, bool]
9-
| bool
10-
| None
8+
Mapping[str, bool] | bool | None
119
)
1210

1311
# Example: entities.domains = { light: … }

homeassistant/components/assist_pipeline/pipeline.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1315,9 +1315,9 @@ async def execute(self) -> None:
13151315
if stt_audio_buffer:
13161316
# Send audio in the buffer first to speech-to-text, then move on to stt_stream.
13171317
# This is basically an async itertools.chain.
1318-
async def buffer_then_audio_stream() -> AsyncGenerator[
1319-
ProcessedAudioChunk, None
1320-
]:
1318+
async def buffer_then_audio_stream() -> (
1319+
AsyncGenerator[ProcessedAudioChunk, None]
1320+
):
13211321
# Buffered audio
13221322
for chunk in stt_audio_buffer:
13231323
yield chunk

homeassistant/components/assist_pipeline/websocket_api.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,7 @@ async def websocket_device_capture(
417417
# single sample (16 bits) per queue item.
418418
max_queue_items = (
419419
# +1 for None to signal end
420-
int(math.ceil(timeout_seconds * CAPTURE_RATE))
421-
+ 1
420+
int(math.ceil(timeout_seconds * CAPTURE_RATE)) + 1
422421
)
423422

424423
audio_queue = DeviceAudioQueue(queue=asyncio.Queue(maxsize=max_queue_items))

homeassistant/components/bmw_connected_drive/select.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class BMWSelectEntityDescription(SelectEntityDescription, BMWRequiredKeysMixin):
4444
translation_key="ac_limit",
4545
is_available=lambda v: v.is_remote_set_ac_limit_enabled,
4646
dynamic_options=lambda v: [
47-
str(lim) for lim in v.charging_profile.ac_available_limits # type: ignore[union-attr]
47+
str(lim)
48+
for lim in v.charging_profile.ac_available_limits # type: ignore[union-attr]
4849
],
4950
current_option=lambda v: str(v.charging_profile.ac_current_limit), # type: ignore[union-attr]
5051
remote_service=lambda v, o: v.remote_services.trigger_charging_settings_update(

homeassistant/components/cloud/http_api.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def _ws_handle_cloud_errors(
140140
handler: Callable[
141141
[HomeAssistant, websocket_api.ActiveConnection, dict[str, Any]],
142142
Coroutine[None, None, None],
143-
]
143+
],
144144
) -> Callable[
145145
[HomeAssistant, websocket_api.ActiveConnection, dict[str, Any]],
146146
Coroutine[None, None, None],
@@ -362,8 +362,11 @@ def _require_cloud_login(
362362
handler: Callable[
363363
[HomeAssistant, websocket_api.ActiveConnection, dict[str, Any]],
364364
None,
365-
]
366-
) -> Callable[[HomeAssistant, websocket_api.ActiveConnection, dict[str, Any]], None,]:
365+
],
366+
) -> Callable[
367+
[HomeAssistant, websocket_api.ActiveConnection, dict[str, Any]],
368+
None,
369+
]:
367370
"""Websocket decorator that requires cloud to be logged in."""
368371

369372
@wraps(handler)

homeassistant/components/deconz/deconz_device.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ def async_update_callback(self) -> None:
129129
if self.gateway.ignore_state_updates:
130130
return
131131

132-
if (
133-
self._update_keys is not None
134-
and not self._device.changed_keys.intersection(self._update_keys)
132+
if self._update_keys is not None and not self._device.changed_keys.intersection(
133+
self._update_keys
135134
):
136135
return
137136

homeassistant/components/devolo_home_network/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ async def async_setup_entry( # noqa: C901
6363
)
6464
await device.async_connect(session_instance=async_client)
6565
device.password = entry.data.get(
66-
CONF_PASSWORD, "" # This key was added in HA Core 2022.6
66+
CONF_PASSWORD,
67+
"", # This key was added in HA Core 2022.6
6768
)
6869
except DeviceNotFound as err:
6970
raise ConfigEntryNotReady(

homeassistant/components/dlna_dmr/media_player.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -453,10 +453,9 @@ def _on_event(
453453
for state_variable in state_variables:
454454
# Force a state refresh when player begins or pauses playback
455455
# to update the position info.
456-
if (
457-
state_variable.name == "TransportState"
458-
and state_variable.value
459-
in (TransportState.PLAYING, TransportState.PAUSED_PLAYBACK)
456+
if state_variable.name == "TransportState" and state_variable.value in (
457+
TransportState.PLAYING,
458+
TransportState.PAUSED_PLAYBACK,
460459
):
461460
force_refresh = True
462461

homeassistant/components/dsmr/sensor.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,7 @@ def device_class_and_uom(
441441
description,
442442
entry,
443443
telegram,
444-
*device_class_and_uom(
445-
telegram, description
446-
), # type: ignore[arg-type]
444+
*device_class_and_uom(telegram, description), # type: ignore[arg-type]
447445
)
448446
for description in all_sensors
449447
if (

homeassistant/components/elmax/cover.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@
1818

1919
_LOGGER = logging.getLogger(__name__)
2020

21-
_COMMAND_BY_MOTION_STATUS = (
22-
{ # Maps the stop command to use for every cover motion status
23-
CoverStatus.DOWN: CoverCommand.DOWN,
24-
CoverStatus.UP: CoverCommand.UP,
25-
CoverStatus.IDLE: None,
26-
}
27-
)
21+
_COMMAND_BY_MOTION_STATUS = { # Maps the stop command to use for every cover motion status
22+
CoverStatus.DOWN: CoverCommand.DOWN,
23+
CoverStatus.UP: CoverCommand.UP,
24+
CoverStatus.IDLE: None,
25+
}
2826

2927

3028
async def async_setup_entry(

homeassistant/components/esphome/enum_mapper.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ class EsphomeEnumMapper(Generic[_EnumT, _ValT]):
1414
def __init__(self, mapping: dict[_EnumT, _ValT]) -> None:
1515
"""Construct a EsphomeEnumMapper."""
1616
# Add none mapping
17-
augmented_mapping: dict[
18-
_EnumT | None, _ValT | None
19-
] = mapping # type: ignore[assignment]
17+
augmented_mapping: dict[_EnumT | None, _ValT | None] = mapping # type: ignore[assignment]
2018
augmented_mapping[None] = None
2119

2220
self._mapping = augmented_mapping

homeassistant/components/esphome/fan.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ def percentage(self) -> int | None:
117117
"""Return the current speed percentage."""
118118
if not self._supports_speed_levels:
119119
return ordered_list_item_to_percentage(
120-
ORDERED_NAMED_FAN_SPEEDS, self._state.speed # type: ignore[misc]
120+
ORDERED_NAMED_FAN_SPEEDS,
121+
self._state.speed, # type: ignore[misc]
121122
)
122123

123124
return ranged_value_to_percentage(

homeassistant/components/evohome/__init__.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,13 @@ def convert_dict(dictionary: dict[str, Any]) -> dict[str, Any]:
124124
def convert_key(key: str) -> str:
125125
"""Convert a string to snake_case."""
126126
string = re.sub(r"[\-\.\s]", "_", str(key))
127-
return (string[0]).lower() + re.sub(
128-
r"[A-Z]",
129-
lambda matched: f"_{matched.group(0).lower()}", # type:ignore[str-bytes-safe]
130-
string[1:],
127+
return (
128+
(string[0]).lower()
129+
+ re.sub(
130+
r"[A-Z]",
131+
lambda matched: f"_{matched.group(0).lower()}", # type:ignore[str-bytes-safe]
132+
string[1:],
133+
)
131134
)
132135

133136
return {

homeassistant/components/goodwe/sensor.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@
7979
class GoodweSensorEntityDescription(SensorEntityDescription):
8080
"""Class describing Goodwe sensor entities."""
8181

82-
value: Callable[
83-
[GoodweUpdateCoordinator, str], Any
84-
] = lambda coordinator, sensor: coordinator.sensor_value(sensor)
85-
available: Callable[
86-
[GoodweUpdateCoordinator], bool
87-
] = lambda coordinator: coordinator.last_update_success
82+
value: Callable[[GoodweUpdateCoordinator, str], Any] = (
83+
lambda coordinator, sensor: coordinator.sensor_value(sensor)
84+
)
85+
available: Callable[[GoodweUpdateCoordinator], bool] = (
86+
lambda coordinator: coordinator.last_update_success
87+
)
8888

8989

9090
_DESCRIPTIONS: dict[str, GoodweSensorEntityDescription] = {

homeassistant/components/google_assistant/helpers.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@
5959
@callback
6060
def _get_registry_entries(
6161
hass: HomeAssistant, entity_id: str
62-
) -> tuple[er.RegistryEntry | None, dr.DeviceEntry | None, ar.AreaEntry | None,]:
62+
) -> tuple[
63+
er.RegistryEntry | None,
64+
dr.DeviceEntry | None,
65+
ar.AreaEntry | None,
66+
]:
6367
"""Get registry entries."""
6468
ent_reg = er.async_get(hass)
6569
dev_reg = dr.async_get(hass)

homeassistant/components/google_tasks/todo.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ def todo_items(self) -> list[TodoItem] | None:
9393
summary=item["title"],
9494
uid=item["id"],
9595
status=TODO_STATUS_MAP.get(
96-
item.get("status"), TodoItemStatus.NEEDS_ACTION # type: ignore[arg-type]
96+
item.get("status"), # type: ignore[arg-type]
97+
TodoItemStatus.NEEDS_ACTION,
9798
),
9899
)
99100
for item in _order_tasks(self.coordinator.data)

homeassistant/components/hdmi_cec/__init__.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,7 @@ def setup(hass: HomeAssistant, base_config: ConfigType) -> bool: # noqa: C901
195195

196196
loop = (
197197
# Create own thread if more than 1 CPU
198-
hass.loop
199-
if multiprocessing.cpu_count() < 2
200-
else None
198+
hass.loop if multiprocessing.cpu_count() < 2 else None
201199
)
202200
host = base_config[DOMAIN].get(CONF_HOST)
203201
display_name = base_config[DOMAIN].get(CONF_DISPLAY_NAME, DEFAULT_DISPLAY_NAME)

homeassistant/components/homekit/type_fans.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,15 @@ def __init__(self, *args: Any) -> None:
124124
),
125125
)
126126

127+
setter_callback = (
128+
lambda value, preset_mode=preset_mode: self.set_preset_mode(
129+
value, preset_mode
130+
)
131+
)
127132
self.preset_mode_chars[preset_mode] = preset_serv.configure_char(
128133
CHAR_ON,
129134
value=False,
130-
setter_callback=lambda value, preset_mode=preset_mode: self.set_preset_mode(
131-
value, preset_mode
132-
),
135+
setter_callback=setter_callback,
133136
)
134137

135138
if CHAR_SWING_MODE in self.chars:

homeassistant/components/hunterdouglas_powerview/select.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,6 @@ def current_option(self) -> str | None:
116116
async def async_select_option(self, option: str) -> None:
117117
"""Change the selected option."""
118118
await self.entity_description.select_fn(self._shade, option)
119-
await self._shade.refresh() # force update data to ensure new info is in coordinator
119+
# force update data to ensure new info is in coordinator
120+
await self._shade.refresh()
120121
self.async_write_ha_state()

0 commit comments

Comments
 (0)