commit
83d617737f
|
@ -215,10 +215,12 @@ class AmcrestBinarySensor(BinarySensorEntity):
|
|||
raise ValueError(f"Binary sensor {self.name} event codes not set")
|
||||
|
||||
try:
|
||||
self._attr_is_on = any( # type: ignore[arg-type]
|
||||
len(await self._api.async_event_channels_happened(event_code)) > 0
|
||||
for event_code in event_codes
|
||||
)
|
||||
for event_code in event_codes:
|
||||
if await self._api.async_event_channels_happened(event_code):
|
||||
self._attr_is_on = True
|
||||
break
|
||||
else:
|
||||
self._attr_is_on = False
|
||||
except AmcrestError as error:
|
||||
log_update_error(_LOGGER, "update", self.name, "binary sensor", error)
|
||||
return
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"bleak==0.18.1",
|
||||
"bleak-retry-connector==2.1.3",
|
||||
"bluetooth-adapters==0.6.0",
|
||||
"bluetooth-auto-recovery==0.3.4",
|
||||
"bluetooth-auto-recovery==0.3.6",
|
||||
"dbus-fast==1.24.0"
|
||||
],
|
||||
"codeowners": ["@bdraco"],
|
||||
|
|
|
@ -279,6 +279,7 @@ class HaBleakClientWrapper(BleakClient):
|
|||
async def connect(self, **kwargs: Any) -> bool:
|
||||
"""Connect to the specified GATT server."""
|
||||
if not self._backend:
|
||||
assert MANAGER is not None
|
||||
wrapped_backend = (
|
||||
self._async_get_backend() or await self._async_get_fallback_backend()
|
||||
)
|
||||
|
@ -287,6 +288,7 @@ class HaBleakClientWrapper(BleakClient):
|
|||
or wrapped_backend.device,
|
||||
disconnected_callback=self.__disconnected_callback,
|
||||
timeout=self.__timeout,
|
||||
hass=MANAGER.hass,
|
||||
)
|
||||
return await super().connect(**kwargs)
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ from bleak.backends.device import BLEDevice
|
|||
from bleak.backends.service import BleakGATTServiceCollection
|
||||
from bleak.exc import BleakError
|
||||
|
||||
from homeassistant.core import CALLBACK_TYPE, async_get_hass
|
||||
from homeassistant.core import CALLBACK_TYPE
|
||||
|
||||
from ..domain_data import DomainData
|
||||
from .characteristic import BleakGATTCharacteristicESPHome
|
||||
|
@ -83,7 +83,7 @@ class ESPHomeClient(BaseBleakClient):
|
|||
self._address_as_int = mac_to_int(self._ble_device.address)
|
||||
assert self._ble_device.details is not None
|
||||
self._source = self._ble_device.details["source"]
|
||||
self.domain_data = DomainData.get(async_get_hass())
|
||||
self.domain_data = DomainData.get(kwargs["hass"])
|
||||
config_entry = self.domain_data.get_by_unique_id(self._source)
|
||||
self.entry_data = self.domain_data.get_entry_data(config_entry)
|
||||
self._client = self.entry_data.client
|
||||
|
|
|
@ -40,7 +40,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
|
||||
try:
|
||||
await conn.async_setup()
|
||||
except (AccessoryNotFoundError, EncryptionError, AccessoryDisconnectedError) as ex:
|
||||
except (
|
||||
asyncio.TimeoutError,
|
||||
AccessoryNotFoundError,
|
||||
EncryptionError,
|
||||
AccessoryDisconnectedError,
|
||||
) as ex:
|
||||
del hass.data[KNOWN_DEVICES][conn.unique_id]
|
||||
with contextlib.suppress(asyncio.TimeoutError):
|
||||
await conn.pairing.close()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "HomeKit Controller",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/homekit_controller",
|
||||
"requirements": ["aiohomekit==2.0.1"],
|
||||
"requirements": ["aiohomekit==2.0.2"],
|
||||
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."],
|
||||
"bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }],
|
||||
"dependencies": ["bluetooth", "zeroconf"],
|
||||
|
|
|
@ -38,7 +38,7 @@ async def validate_host_input(host: str, dhcp_mode: bool = False) -> str:
|
|||
"""
|
||||
LOGGER.debug("Instantiating IntellifireAPI with host: [%s]", host)
|
||||
api = IntellifireAPILocal(fireplace_ip=host)
|
||||
await api.poll(supress_warnings=dhcp_mode)
|
||||
await api.poll(suppress_warnings=dhcp_mode)
|
||||
serial = api.data.serial
|
||||
|
||||
LOGGER.debug("Found a fireplace: %s", serial)
|
||||
|
@ -62,7 +62,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
async def _find_fireplaces(self):
|
||||
"""Perform UDP discovery."""
|
||||
fireplace_finder = AsyncUDPFireplaceFinder()
|
||||
discovered_hosts = await fireplace_finder.search_fireplace(timeout=1)
|
||||
discovered_hosts = await fireplace_finder.search_fireplace(timeout=12)
|
||||
configured_hosts = {
|
||||
entry.data[CONF_HOST]
|
||||
for entry in self._async_current_entries(include_ignore=False)
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
"name": "IntelliFire",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/intellifire",
|
||||
"requirements": ["intellifire4py==2.0.1"],
|
||||
"requirements": ["intellifire4py==2.2.1"],
|
||||
"codeowners": ["@jeeftor"],
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["intellifire4py"],
|
||||
"dhcp": [{ "hostname": "zentrios-*" }]
|
||||
"dhcp": [
|
||||
{
|
||||
"hostname": "zentrios-*"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -767,6 +767,7 @@ class MqttCover(MqttEntity, CoverEntity):
|
|||
|
||||
return position
|
||||
|
||||
@callback
|
||||
def tilt_payload_received(self, _payload):
|
||||
"""Set the tilt value."""
|
||||
|
||||
|
@ -784,7 +785,7 @@ class MqttCover(MqttEntity, CoverEntity):
|
|||
):
|
||||
level = self.find_percentage_in_range(payload)
|
||||
self._tilt_value = level
|
||||
self.async_write_ha_state()
|
||||
get_mqtt_data(self.hass).state_write_requests.write_state_request(self)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Payload '%s' is out of range, must be between '%s' and '%s' inclusive",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"domain": "plugwise",
|
||||
"name": "Plugwise",
|
||||
"documentation": "https://www.home-assistant.io/integrations/plugwise",
|
||||
"requirements": ["plugwise==0.21.3"],
|
||||
"requirements": ["plugwise==0.21.4"],
|
||||
"codeowners": ["@CoMPaTech", "@bouwew", "@brefra", "@frenck"],
|
||||
"zeroconf": ["_plugwise._tcp.local."],
|
||||
"config_flow": true,
|
||||
|
|
|
@ -34,7 +34,7 @@ from .model import (
|
|||
RainMachineEntityDescriptionMixinDataKey,
|
||||
RainMachineEntityDescriptionMixinUid,
|
||||
)
|
||||
from .util import RUN_STATE_MAP
|
||||
from .util import RUN_STATE_MAP, key_exists
|
||||
|
||||
ATTR_AREA = "area"
|
||||
ATTR_CS_ON = "cs_on"
|
||||
|
@ -237,6 +237,8 @@ async def async_setup_entry(
|
|||
|
||||
# Add switches to control restrictions:
|
||||
for description in RESTRICTIONS_SWITCH_DESCRIPTIONS:
|
||||
if not key_exists(coordinator.data, description.data_key):
|
||||
continue
|
||||
entities.append(RainMachineRestrictionSwitch(entry, data, description))
|
||||
|
||||
async_add_entities(entities)
|
||||
|
|
|
@ -69,7 +69,7 @@ from .const import (
|
|||
|
||||
KEY_PRESS_TIMEOUT = 1.2
|
||||
|
||||
ENCRYPTED_MODEL_USES_POWER_OFF = {"H6400"}
|
||||
ENCRYPTED_MODEL_USES_POWER_OFF = {"H6400", "H6410"}
|
||||
ENCRYPTED_MODEL_USES_POWER = {"JU6400", "JU641D"}
|
||||
|
||||
REST_EXCEPTIONS = (HttpApiError, AsyncioTimeoutError, ResponseError)
|
||||
|
|
|
@ -140,6 +140,7 @@ class BlockSleepingClimate(
|
|||
self.last_state: State | None = None
|
||||
self.last_state_attributes: Mapping[str, Any]
|
||||
self._preset_modes: list[str] = []
|
||||
self._last_target_temp = 20.0
|
||||
|
||||
if self.block is not None and self.device_block is not None:
|
||||
self._unique_id = f"{self.wrapper.mac}-{self.block.description}"
|
||||
|
@ -266,9 +267,15 @@ class BlockSleepingClimate(
|
|||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set hvac mode."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
if isinstance(self.target_temperature, float):
|
||||
self._last_target_temp = self.target_temperature
|
||||
await self.set_state_full_path(
|
||||
target_t_enabled=1, target_t=f"{self._attr_min_temp}"
|
||||
)
|
||||
if hvac_mode == HVACMode.HEAT:
|
||||
await self.set_state_full_path(
|
||||
target_t_enabled=1, target_t=self._last_target_temp
|
||||
)
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set preset mode."""
|
||||
|
|
|
@ -144,7 +144,7 @@ SENSORS: Final = {
|
|||
key="emeter|powerFactor",
|
||||
name="Power Factor",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value=lambda value: round(value * 100, 1),
|
||||
value=lambda value: abs(round(value * 100, 1)),
|
||||
device_class=SensorDeviceClass.POWER_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
|
|
|
@ -276,17 +276,19 @@ class SolarEdgePowerFlowDataService(SolarEdgeDataService):
|
|||
|
||||
for key, value in power_flow.items():
|
||||
if key in ["LOAD", "PV", "GRID", "STORAGE"]:
|
||||
self.data[key] = value["currentPower"]
|
||||
self.data[key] = value.get("currentPower")
|
||||
self.attributes[key] = {"status": value["status"]}
|
||||
|
||||
if key in ["GRID"]:
|
||||
export = key.lower() in power_to
|
||||
self.data[key] *= -1 if export else 1
|
||||
if self.data[key]:
|
||||
self.data[key] *= -1 if export else 1
|
||||
self.attributes[key]["flow"] = "export" if export else "import"
|
||||
|
||||
if key in ["STORAGE"]:
|
||||
charge = key.lower() in power_to
|
||||
self.data[key] *= -1 if charge else 1
|
||||
if self.data[key]:
|
||||
self.data[key] *= -1 if charge else 1
|
||||
self.attributes[key]["flow"] = "charge" if charge else "discharge"
|
||||
self.attributes[key]["soc"] = value["chargeLevel"]
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ from __future__ import annotations
|
|||
from collections.abc import Generator
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from io import BufferedIOBase
|
||||
|
||||
|
@ -11,7 +13,7 @@ if TYPE_CHECKING:
|
|||
def find_box(
|
||||
mp4_bytes: bytes, target_type: bytes, box_start: int = 0
|
||||
) -> Generator[int, None, None]:
|
||||
"""Find location of first box (or sub_box if box_start provided) of given type."""
|
||||
"""Find location of first box (or sub box if box_start provided) of given type."""
|
||||
if box_start == 0:
|
||||
index = 0
|
||||
box_end = len(mp4_bytes)
|
||||
|
@ -141,12 +143,26 @@ def get_codec_string(mp4_bytes: bytes) -> str:
|
|||
return ",".join(codecs)
|
||||
|
||||
|
||||
def find_moov(mp4_io: BufferedIOBase) -> int:
|
||||
"""Find location of moov atom in a BufferedIOBase mp4."""
|
||||
index = 0
|
||||
while 1:
|
||||
mp4_io.seek(index)
|
||||
box_header = mp4_io.read(8)
|
||||
if len(box_header) != 8:
|
||||
raise HomeAssistantError("moov atom not found")
|
||||
if box_header[4:8] == b"moov":
|
||||
return index
|
||||
index += int.from_bytes(box_header[0:4], byteorder="big")
|
||||
|
||||
|
||||
def read_init(bytes_io: BufferedIOBase) -> bytes:
|
||||
"""Read the init from a mp4 file."""
|
||||
bytes_io.seek(24)
|
||||
moov_loc = find_moov(bytes_io)
|
||||
bytes_io.seek(moov_loc)
|
||||
moov_len = int.from_bytes(bytes_io.read(4), byteorder="big")
|
||||
bytes_io.seek(0)
|
||||
return bytes_io.read(24 + moov_len)
|
||||
return bytes_io.read(moov_loc + moov_len)
|
||||
|
||||
|
||||
ZERO32 = b"\x00\x00\x00\x00"
|
||||
|
|
|
@ -46,7 +46,8 @@ async def async_validate_trigger_config(
|
|||
device_id = config[CONF_DEVICE_ID]
|
||||
try:
|
||||
device = async_get_device_entry_by_device_id(hass, device_id)
|
||||
async_get_client_wrapper_by_device_entry(hass, device)
|
||||
if DOMAIN in hass.data:
|
||||
async_get_client_wrapper_by_device_entry(hass, device)
|
||||
except ValueError as err:
|
||||
raise InvalidDeviceAutomationConfig(err) from err
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from httpx import ConnectError, ConnectTimeout
|
||||
from httpx import RequestError
|
||||
from wolf_smartset.token_auth import InvalidAuth
|
||||
from wolf_smartset.wolf_client import FetchFailed, ParameterReadError, WolfClient
|
||||
|
||||
|
@ -74,7 +74,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
for parameter in parameters
|
||||
if parameter.value_id in values
|
||||
}
|
||||
except ConnectError as exception:
|
||||
except RequestError as exception:
|
||||
raise UpdateFailed(
|
||||
f"Error communicating with API: {exception}"
|
||||
) from exception
|
||||
|
@ -134,7 +134,7 @@ async def fetch_parameters_init(client: WolfClient, gateway_id: int, device_id:
|
|||
"""Fetch all available parameters with usage of WolfClient but handles all exceptions and results in ConfigEntryNotReady."""
|
||||
try:
|
||||
return await fetch_parameters(client, gateway_id, device_id)
|
||||
except (ConnectError, ConnectTimeout, FetchFailed) as exception:
|
||||
except (FetchFailed, RequestError) as exception:
|
||||
raise ConfigEntryNotReady(
|
||||
f"Error communicating with API: {exception}"
|
||||
) from exception
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"bellows==0.34.2",
|
||||
"pyserial==3.5",
|
||||
"pyserial-asyncio==0.6",
|
||||
"zha-quirks==0.0.82",
|
||||
"zha-quirks==0.0.83",
|
||||
"zigpy-deconz==0.19.0",
|
||||
"zigpy==0.51.3",
|
||||
"zigpy-xbee==0.16.2",
|
||||
|
|
|
@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
|||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2022
|
||||
MINOR_VERSION: Final = 10
|
||||
PATCH_VERSION: Final = "4"
|
||||
PATCH_VERSION: Final = "5"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
||||
|
|
|
@ -13,7 +13,7 @@ bcrypt==3.1.7
|
|||
bleak-retry-connector==2.1.3
|
||||
bleak==0.18.1
|
||||
bluetooth-adapters==0.6.0
|
||||
bluetooth-auto-recovery==0.3.4
|
||||
bluetooth-auto-recovery==0.3.6
|
||||
certifi>=2021.5.30
|
||||
ciso8601==2.2.0
|
||||
cryptography==38.0.1
|
||||
|
@ -132,3 +132,6 @@ iso4217!=1.10.20220401
|
|||
|
||||
# Pandas 1.4.4 has issues with wheels om armhf + Py3.10
|
||||
pandas==1.4.3
|
||||
|
||||
# uamqp 1.6.1, has 1 failing test during built on armv7/armhf
|
||||
uamqp==1.6.0
|
||||
|
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2022.10.4"
|
||||
version = "2022.10.5"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
readme = "README.rst"
|
||||
|
|
|
@ -171,7 +171,7 @@ aioguardian==2022.07.0
|
|||
aioharmony==0.2.9
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==2.0.1
|
||||
aiohomekit==2.0.2
|
||||
|
||||
# homeassistant.components.emulated_hue
|
||||
# homeassistant.components.http
|
||||
|
@ -435,7 +435,7 @@ bluemaestro-ble==0.2.0
|
|||
bluetooth-adapters==0.6.0
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bluetooth-auto-recovery==0.3.4
|
||||
bluetooth-auto-recovery==0.3.6
|
||||
|
||||
# homeassistant.components.bond
|
||||
bond-async==0.1.22
|
||||
|
@ -934,7 +934,7 @@ inkbird-ble==0.5.5
|
|||
insteon-frontend-home-assistant==0.2.0
|
||||
|
||||
# homeassistant.components.intellifire
|
||||
intellifire4py==2.0.1
|
||||
intellifire4py==2.2.1
|
||||
|
||||
# homeassistant.components.iotawatt
|
||||
iotawattpy==0.1.0
|
||||
|
@ -1306,7 +1306,7 @@ plexauth==0.0.6
|
|||
plexwebsocket==0.0.13
|
||||
|
||||
# homeassistant.components.plugwise
|
||||
plugwise==0.21.3
|
||||
plugwise==0.21.4
|
||||
|
||||
# homeassistant.components.plum_lightpad
|
||||
plumlightpad==0.0.11
|
||||
|
@ -2592,7 +2592,7 @@ zengge==0.2
|
|||
zeroconf==0.39.1
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.82
|
||||
zha-quirks==0.0.83
|
||||
|
||||
# homeassistant.components.zhong_hong
|
||||
zhong_hong_hvac==1.0.9
|
||||
|
|
|
@ -155,7 +155,7 @@ aioguardian==2022.07.0
|
|||
aioharmony==0.2.9
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==2.0.1
|
||||
aiohomekit==2.0.2
|
||||
|
||||
# homeassistant.components.emulated_hue
|
||||
# homeassistant.components.http
|
||||
|
@ -349,7 +349,7 @@ bluemaestro-ble==0.2.0
|
|||
bluetooth-adapters==0.6.0
|
||||
|
||||
# homeassistant.components.bluetooth
|
||||
bluetooth-auto-recovery==0.3.4
|
||||
bluetooth-auto-recovery==0.3.6
|
||||
|
||||
# homeassistant.components.bond
|
||||
bond-async==0.1.22
|
||||
|
@ -690,7 +690,7 @@ inkbird-ble==0.5.5
|
|||
insteon-frontend-home-assistant==0.2.0
|
||||
|
||||
# homeassistant.components.intellifire
|
||||
intellifire4py==2.0.1
|
||||
intellifire4py==2.2.1
|
||||
|
||||
# homeassistant.components.iotawatt
|
||||
iotawattpy==0.1.0
|
||||
|
@ -933,7 +933,7 @@ plexauth==0.0.6
|
|||
plexwebsocket==0.0.13
|
||||
|
||||
# homeassistant.components.plugwise
|
||||
plugwise==0.21.3
|
||||
plugwise==0.21.4
|
||||
|
||||
# homeassistant.components.plum_lightpad
|
||||
plumlightpad==0.0.11
|
||||
|
@ -1793,7 +1793,7 @@ youless-api==0.16
|
|||
zeroconf==0.39.1
|
||||
|
||||
# homeassistant.components.zha
|
||||
zha-quirks==0.0.82
|
||||
zha-quirks==0.0.83
|
||||
|
||||
# homeassistant.components.zha
|
||||
zigpy-deconz==0.19.0
|
||||
|
|
|
@ -142,6 +142,9 @@ iso4217!=1.10.20220401
|
|||
|
||||
# Pandas 1.4.4 has issues with wheels om armhf + Py3.10
|
||||
pandas==1.4.3
|
||||
|
||||
# uamqp 1.6.1, has 1 failing test during built on armv7/armhf
|
||||
uamqp==1.6.0
|
||||
"""
|
||||
|
||||
IGNORE_PRE_COMMIT_HOOK_ID = (
|
||||
|
|
|
@ -29,7 +29,7 @@ from .common import (
|
|||
from tests.common import async_fire_time_changed
|
||||
|
||||
STREAM_SOURCE = "some-stream-source"
|
||||
INIT_BYTES = b"init"
|
||||
INIT_BYTES = b"\x00\x00\x00\x08moov"
|
||||
FAKE_PAYLOAD = b"fake-payload"
|
||||
SEGMENT_DURATION = 10
|
||||
TEST_TIMEOUT = 5.0 # Lower than 9s home assistant timeout
|
||||
|
|
|
@ -30,7 +30,7 @@ TEST_PART_DURATION = 0.75
|
|||
NUM_PART_SEGMENTS = int(-(-SEGMENT_DURATION // TEST_PART_DURATION))
|
||||
PART_INDEPENDENT_PERIOD = int(1 / TEST_PART_DURATION) or 1
|
||||
BYTERANGE_LENGTH = 1
|
||||
INIT_BYTES = b"init"
|
||||
INIT_BYTES = b"\x00\x00\x00\x08moov"
|
||||
SEQUENCE_BYTES = bytearray(range(NUM_PART_SEGMENTS * BYTERANGE_LENGTH))
|
||||
ALT_SEQUENCE_BYTES = bytearray(range(20, 20 + NUM_PART_SEGMENTS * BYTERANGE_LENGTH))
|
||||
VERY_LARGE_LAST_BYTE_POS = 9007199254740991
|
||||
|
|
|
@ -242,7 +242,7 @@ class FakePyAvBuffer:
|
|||
# Forward to appropriate FakeStream
|
||||
packet.stream.mux(packet)
|
||||
# Make new init/part data available to the worker
|
||||
self.memory_file.write(b"0")
|
||||
self.memory_file.write(b"\x00\x00\x00\x00moov")
|
||||
|
||||
def close(self):
|
||||
"""Close the buffer."""
|
||||
|
|
Loading…
Reference in New Issue