Rename AlarmControlPanel to AlarmControlPanelEntity (#34590)

This commit is contained in:
Erik Montnemery 2020-04-25 18:05:28 +02:00 committed by GitHub
parent 29bc93ea98
commit 6f7f5b4034
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 75 additions and 48 deletions

View file

@ -25,7 +25,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
) )
class AbodeAlarm(AbodeDevice, alarm.AlarmControlPanel): class AbodeAlarm(AbodeDevice, alarm.AlarmControlPanelEntity):
"""An alarm_control_panel implementation for Abode.""" """An alarm_control_panel implementation for Abode."""
@property @property

View file

@ -32,6 +32,8 @@ from .const import (
SUPPORT_ALARM_TRIGGER, SUPPORT_ALARM_TRIGGER,
) )
_LOGGER = logging.getLogger(__name__)
DOMAIN = "alarm_control_panel" DOMAIN = "alarm_control_panel"
SCAN_INTERVAL = timedelta(seconds=30) SCAN_INTERVAL = timedelta(seconds=30)
ATTR_CHANGED_BY = "changed_by" ATTR_CHANGED_BY = "changed_by"
@ -99,8 +101,8 @@ async def async_unload_entry(hass, entry):
return await hass.data[DOMAIN].async_unload_entry(entry) return await hass.data[DOMAIN].async_unload_entry(entry)
class AlarmControlPanel(Entity): class AlarmControlPanelEntity(Entity):
"""An abstract class for alarm control devices.""" """An abstract class for alarm control entities."""
@property @property
def code_format(self): def code_format(self):
@ -179,3 +181,15 @@ class AlarmControlPanel(Entity):
ATTR_CODE_ARM_REQUIRED: self.code_arm_required, ATTR_CODE_ARM_REQUIRED: self.code_arm_required,
} }
return state_attr return state_attr
class AlarmControlPanel(AlarmControlPanelEntity):
"""An abstract class for alarm control entities (for backwards compatibility)."""
def __init_subclass__(cls, **kwargs):
"""Print deprecation warning."""
super().__init_subclass__(**kwargs)
_LOGGER.warning(
"AlarmControlPanel is deprecated, modify %s to extend AlarmControlPanelEntity",
cls.__name__,
)

View file

@ -5,7 +5,7 @@ import voluptuous as vol
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
FORMAT_NUMBER, FORMAT_NUMBER,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -74,7 +74,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
) )
class AlarmDecoderAlarmPanel(AlarmControlPanel): class AlarmDecoderAlarmPanel(AlarmControlPanelEntity):
"""Representation of an AlarmDecoder-based alarm panel.""" """Representation of an AlarmDecoder-based alarm panel."""
def __init__(self, auto_bypass, code_arm_required): def __init__(self, auto_bypass, code_arm_required):

View file

@ -5,7 +5,7 @@ import voluptuous as vol
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -66,7 +66,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities(base_stations, True) add_entities(base_stations, True)
class ArloBaseStation(AlarmControlPanel): class ArloBaseStation(AlarmControlPanelEntity):
"""Representation of an Arlo Alarm Control Panel.""" """Representation of an Arlo Alarm Control Panel."""
def __init__(self, data, home_mode_name, away_mode_name, night_mode_name): def __init__(self, data, home_mode_name, away_mode_name, night_mode_name):

View file

@ -1,7 +1,7 @@
"""Support for Blink Alarm Control Panel.""" """Support for Blink Alarm Control Panel."""
import logging import logging
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import SUPPORT_ALARM_ARM_AWAY from homeassistant.components.alarm_control_panel.const import SUPPORT_ALARM_ARM_AWAY
from homeassistant.const import ( from homeassistant.const import (
ATTR_ATTRIBUTION, ATTR_ATTRIBUTION,
@ -28,7 +28,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities(sync_modules, True) add_entities(sync_modules, True)
class BlinkSyncModule(AlarmControlPanel): class BlinkSyncModule(AlarmControlPanelEntity):
"""Representation of a Blink Alarm Control Panel.""" """Representation of a Blink Alarm Control Panel."""
def __init__(self, data, name, sync): def __init__(self, data, name, sync):

View file

@ -3,7 +3,7 @@ import logging
from canary.api import LOCATION_MODE_AWAY, LOCATION_MODE_HOME, LOCATION_MODE_NIGHT from canary.api import LOCATION_MODE_AWAY, LOCATION_MODE_HOME, LOCATION_MODE_NIGHT
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_HOME,
@ -32,7 +32,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities(devices, True) add_entities(devices, True)
class CanaryAlarm(AlarmControlPanel): class CanaryAlarm(AlarmControlPanelEntity):
"""Representation of a Canary alarm control panel.""" """Representation of a Canary alarm control panel."""
def __init__(self, data, location_id): def __init__(self, data, location_id):

View file

@ -60,7 +60,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
_LOGGER.error("Unable to connect to Concord232: %s", str(ex)) _LOGGER.error("Unable to connect to Concord232: %s", str(ex))
class Concord232Alarm(alarm.AlarmControlPanel): class Concord232Alarm(alarm.AlarmControlPanelEntity):
"""Representation of the Concord232-based alarm panel.""" """Representation of the Concord232-based alarm panel."""
def __init__(self, url, name, code, mode): def __init__(self, url, name, code, mode):

View file

@ -53,7 +53,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([device], True) add_entities([device], True)
class EgardiaAlarm(alarm.AlarmControlPanel): class EgardiaAlarm(alarm.AlarmControlPanelEntity):
"""Representation of a Egardia alarm.""" """Representation of a Egardia alarm."""
def __init__( def __init__(

View file

@ -8,7 +8,7 @@ import voluptuous as vol
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
ATTR_CHANGED_BY, ATTR_CHANGED_BY,
FORMAT_NUMBER, FORMAT_NUMBER,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -109,7 +109,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
) )
class ElkArea(ElkAttachedEntity, AlarmControlPanel, RestoreEntity): class ElkArea(ElkAttachedEntity, AlarmControlPanelEntity, RestoreEntity):
"""Representation of an Area / Partition within the ElkM1 alarm panel.""" """Representation of an Area / Partition within the ElkM1 alarm panel."""
def __init__(self, element, elk, elk_data): def __init__(self, element, elk, elk_data):

View file

@ -5,7 +5,7 @@ import voluptuous as vol
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
FORMAT_NUMBER, FORMAT_NUMBER,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -96,7 +96,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
return True return True
class EnvisalinkAlarm(EnvisalinkDevice, AlarmControlPanel): class EnvisalinkAlarm(EnvisalinkDevice, AlarmControlPanelEntity):
"""Representation of an Envisalink-based alarm panel.""" """Representation of an Envisalink-based alarm panel."""
def __init__( def __init__(

View file

@ -3,7 +3,7 @@ import logging
from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.characteristics import CharacteristicsTypes
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_HOME,
@ -51,13 +51,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
if service["stype"] != "security-system": if service["stype"] != "security-system":
return False return False
info = {"aid": aid, "iid": service["iid"]} info = {"aid": aid, "iid": service["iid"]}
async_add_entities([HomeKitAlarmControlPanel(conn, info)], True) async_add_entities([HomeKitAlarmControlPanelEntity(conn, info)], True)
return True return True
conn.add_listener(async_add_service) conn.add_listener(async_add_service)
class HomeKitAlarmControlPanel(HomeKitEntity, AlarmControlPanel): class HomeKitAlarmControlPanelEntity(HomeKitEntity, AlarmControlPanelEntity):
"""Representation of a Homekit Alarm Control Panel.""" """Representation of a Homekit Alarm Control Panel."""
def get_characteristic_types(self): def get_characteristic_types(self):

View file

@ -4,7 +4,7 @@ from typing import Any, Dict
from homematicip.functionalHomes import SecurityAndAlarmHome from homematicip.functionalHomes import SecurityAndAlarmHome
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_HOME,
@ -32,10 +32,10 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up the HomematicIP alrm control panel from a config entry.""" """Set up the HomematicIP alrm control panel from a config entry."""
hap = hass.data[HMIPC_DOMAIN][config_entry.unique_id] hap = hass.data[HMIPC_DOMAIN][config_entry.unique_id]
async_add_entities([HomematicipAlarmControlPanel(hap)]) async_add_entities([HomematicipAlarmControlPanelEntity(hap)])
class HomematicipAlarmControlPanel(AlarmControlPanel): class HomematicipAlarmControlPanelEntity(AlarmControlPanelEntity):
"""Representation of an alarm control panel.""" """Representation of an alarm control panel."""
def __init__(self, hap: HomematicipHAP) -> None: def __init__(self, hap: HomematicipHAP) -> None:

View file

@ -62,7 +62,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([ialarm], True) add_entities([ialarm], True)
class IAlarmPanel(alarm.AlarmControlPanel): class IAlarmPanel(alarm.AlarmControlPanelEntity):
"""Representation of an iAlarm status.""" """Representation of an iAlarm status."""
def __init__(self, name, code, username, password, url): def __init__(self, name, code, username, password, url):

View file

@ -8,7 +8,7 @@ from homeassistant.components.alarm_control_panel import (
FORMAT_NUMBER, FORMAT_NUMBER,
FORMAT_TEXT, FORMAT_TEXT,
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -108,7 +108,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
) )
class IFTTTAlarmPanel(AlarmControlPanel): class IFTTTAlarmPanel(AlarmControlPanelEntity):
"""Representation of an alarm control panel controlled through IFTTT.""" """Representation of an alarm control panel controlled through IFTTT."""
def __init__( def __init__(

View file

@ -1,7 +1,7 @@
"""Support for Lupusec System alarm control panels.""" """Support for Lupusec System alarm control panels."""
from datetime import timedelta from datetime import timedelta
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_HOME,
@ -32,7 +32,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities(alarm_devices) add_entities(alarm_devices)
class LupusecAlarm(LupusecDevice, AlarmControlPanel): class LupusecAlarm(LupusecDevice, AlarmControlPanelEntity):
"""An alarm_control_panel implementation for Lupusec.""" """An alarm_control_panel implementation for Lupusec."""
@property @property

View file

@ -164,7 +164,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
) )
class ManualAlarm(alarm.AlarmControlPanel, RestoreEntity): class ManualAlarm(alarm.AlarmControlPanelEntity, RestoreEntity):
""" """
Representation of an alarm status. Representation of an alarm status.

View file

@ -184,7 +184,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
) )
class ManualMQTTAlarm(alarm.AlarmControlPanel): class ManualMQTTAlarm(alarm.AlarmControlPanelEntity):
""" """
Representation of an alarm status. Representation of an alarm status.

View file

@ -135,7 +135,7 @@ class MqttAlarm(
MqttAvailability, MqttAvailability,
MqttDiscoveryUpdate, MqttDiscoveryUpdate,
MqttEntityDeviceInfo, MqttEntityDeviceInfo,
alarm.AlarmControlPanel, alarm.AlarmControlPanelEntity,
): ):
"""Representation of a MQTT alarm status.""" """Representation of a MQTT alarm status."""

View file

@ -34,7 +34,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async_add_entities([device]) async_add_entities([device])
class NessAlarmPanel(alarm.AlarmControlPanel): class NessAlarmPanel(alarm.AlarmControlPanelEntity):
"""Representation of a Ness alarm panel.""" """Representation of a Ness alarm panel."""
def __init__(self, client, name): def __init__(self, client, name):

View file

@ -52,7 +52,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
return return
class NX584Alarm(alarm.AlarmControlPanel): class NX584Alarm(alarm.AlarmControlPanelEntity):
"""Representation of a NX584-based alarm panel.""" """Representation of a NX584-based alarm panel."""
def __init__(self, hass, url, name): def __init__(self, hass, url, name):

View file

@ -1,7 +1,7 @@
"""Support for Minut Point.""" """Support for Minut Point."""
import logging import logging
from homeassistant.components.alarm_control_panel import DOMAIN, AlarmControlPanel from homeassistant.components.alarm_control_panel import DOMAIN, AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import SUPPORT_ALARM_ARM_AWAY from homeassistant.components.alarm_control_panel.const import SUPPORT_ALARM_ARM_AWAY
from homeassistant.const import ( from homeassistant.const import (
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_AWAY,
@ -36,7 +36,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
) )
class MinutPointAlarmControl(AlarmControlPanel): class MinutPointAlarmControl(AlarmControlPanelEntity):
"""The platform class required by Home Assistant.""" """The platform class required by Home Assistant."""
def __init__(self, point_client, home_id): def __init__(self, point_client, home_id):

View file

@ -52,7 +52,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async_add_entities(devices) async_add_entities(devices)
class SatelIntegraAlarmPanel(alarm.AlarmControlPanel): class SatelIntegraAlarmPanel(alarm.AlarmControlPanelEntity):
"""Representation of an AlarmDecoder-based alarm panel.""" """Representation of an AlarmDecoder-based alarm panel."""
def __init__(self, controller, name, arm_home_mode, partition_id): def __init__(self, controller, name, arm_home_mode, partition_id):

View file

@ -21,7 +21,7 @@ from simplipy.websocket import (
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
FORMAT_NUMBER, FORMAT_NUMBER,
FORMAT_TEXT, FORMAT_TEXT,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -72,7 +72,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
) )
class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanel): class SimpliSafeAlarm(SimpliSafeEntity, AlarmControlPanelEntity):
"""Representation of a SimpliSafe alarm.""" """Representation of a SimpliSafe alarm."""
def __init__(self, simplisafe, system): def __init__(self, simplisafe, system):

View file

@ -47,7 +47,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async_add_entities([SpcAlarm(area=area, api=api) for area in api.areas.values()]) async_add_entities([SpcAlarm(area=area, api=api) for area in api.areas.values()])
class SpcAlarm(alarm.AlarmControlPanel): class SpcAlarm(alarm.AlarmControlPanelEntity):
"""Representation of the SPC alarm panel.""" """Representation of the SPC alarm panel."""
def __init__(self, area, api): def __init__(self, area, api):

View file

@ -7,7 +7,7 @@ from homeassistant.components.alarm_control_panel import (
ENTITY_ID_FORMAT, ENTITY_ID_FORMAT,
FORMAT_NUMBER, FORMAT_NUMBER,
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -117,7 +117,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async_add_entities(alarm_control_panels) async_add_entities(alarm_control_panels)
class AlarmControlPanelTemplate(AlarmControlPanel): class AlarmControlPanelTemplate(AlarmControlPanelEntity):
"""Representation of a templated Alarm Control Panel.""" """Representation of a templated Alarm Control Panel."""
def __init__( def __init__(

View file

@ -36,7 +36,7 @@ async def async_setup_entry(hass, entry, async_add_entities) -> None:
async_add_entities(alarms, True) async_add_entities(alarms, True)
class TotalConnectAlarm(alarm.AlarmControlPanel): class TotalConnectAlarm(alarm.AlarmControlPanelEntity):
"""Represent an TotalConnect status.""" """Represent an TotalConnect status."""
def __init__(self, name, location_id, client): def __init__(self, name, location_id, client):

View file

@ -40,7 +40,7 @@ def set_arm_state(state, code=None):
hub.update_overview(no_throttle=True) hub.update_overview(no_throttle=True)
class VerisureAlarm(alarm.AlarmControlPanel): class VerisureAlarm(alarm.AlarmControlPanelEntity):
"""Representation of a Verisure alarm status.""" """Representation of a Verisure alarm status."""
def __init__(self): def __init__(self):

View file

@ -35,7 +35,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([WinkCameraDevice(camera, hass)]) add_entities([WinkCameraDevice(camera, hass)])
class WinkCameraDevice(WinkDevice, alarm.AlarmControlPanel): class WinkCameraDevice(WinkDevice, alarm.AlarmControlPanelEntity):
"""Representation a Wink camera alarm.""" """Representation a Wink camera alarm."""
async def async_added_to_hass(self): async def async_added_to_hass(self):

View file

@ -12,7 +12,7 @@ from yalesmartalarmclient.client import (
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
PLATFORM_SCHEMA, PLATFORM_SCHEMA,
AlarmControlPanel, AlarmControlPanelEntity,
) )
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
@ -62,7 +62,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([YaleAlarmDevice(name, client)], True) add_entities([YaleAlarmDevice(name, client)], True)
class YaleAlarmDevice(AlarmControlPanel): class YaleAlarmDevice(AlarmControlPanelEntity):
"""Represent a Yale Smart Alarm.""" """Represent a Yale Smart Alarm."""
def __init__(self, name, client): def __init__(self, name, client):

View file

@ -0,0 +1,13 @@
"""Tests for Alarm control panel."""
from homeassistant.components import alarm_control_panel
def test_deprecated_base_class(caplog):
"""Test deprecated base class."""
class CustomAlarm(alarm_control_panel.AlarmControlPanel):
def supported_features(self):
pass
CustomAlarm()
assert "AlarmControlPanel is deprecated, modify CustomAlarm" in caplog.text

View file

@ -3,7 +3,7 @@ Provide a mock alarm_control_panel platform.
Call init before using it in your tests to ensure clean test data. Call init before using it in your tests to ensure clean test data.
""" """
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanelEntity
from homeassistant.components.alarm_control_panel.const import ( from homeassistant.components.alarm_control_panel.const import (
SUPPORT_ALARM_ARM_AWAY, SUPPORT_ALARM_ARM_AWAY,
SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_HOME,
@ -52,7 +52,7 @@ async def async_setup_platform(
async_add_entities_callback(list(ENTITIES.values())) async_add_entities_callback(list(ENTITIES.values()))
class MockAlarm(MockEntity, AlarmControlPanel): class MockAlarm(MockEntity, AlarmControlPanelEntity):
"""Mock Alarm control panel class.""" """Mock Alarm control panel class."""
def __init__(self, **values): def __init__(self, **values):