mirror of
https://github.com/home-assistant/core.git
synced 2025-09-25 04:49:24 +00:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a0403a8864 | ||
![]() |
bfaad97318 | ||
![]() |
d6c15d2f45 | ||
![]() |
815502044e | ||
![]() |
08f5b49dc4 | ||
![]() |
fab55b0ea2 | ||
![]() |
649ec2fc8e | ||
![]() |
21e0df42ac | ||
![]() |
f7f9126610 | ||
![]() |
52809396d4 | ||
![]() |
121d967732 |
@@ -68,6 +68,7 @@ homeassistant/components/config/* @home-assistant/core
|
||||
homeassistant/components/configurator/* @home-assistant/core
|
||||
homeassistant/components/conversation/* @home-assistant/core
|
||||
homeassistant/components/coolmaster/* @OnFreund
|
||||
homeassistant/components/coronavirus/* @home_assistant/core
|
||||
homeassistant/components/counter/* @fabaff
|
||||
homeassistant/components/cover/* @home-assistant/core
|
||||
homeassistant/components/cpuspeed/* @fabaff
|
||||
|
@@ -41,7 +41,7 @@ stages:
|
||||
jq curl
|
||||
|
||||
release="$(Build.SourceBranchName)"
|
||||
created_by="$(curl -s https://api.github.com/repos/home-assistant/home-assistant/releases/tags/${release} | jq --raw-output '.author.login')"
|
||||
created_by="$(curl -s https://api.github.com/repos/home-assistant/core/releases/tags/${release} | jq --raw-output '.author.login')"
|
||||
|
||||
if [[ "${created_by}" =~ ^(balloob|pvizeli|fabaff|robbiet480|bramkragten|frenck)$ ]]; then
|
||||
exit 0
|
||||
|
13
homeassistant/components/coronavirus/.translations/en.json
Normal file
13
homeassistant/components/coronavirus/.translations/en.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"country": "Country"
|
||||
},
|
||||
"title": "Pick a country to monitor"
|
||||
}
|
||||
},
|
||||
"title": "Coronavirus"
|
||||
}
|
||||
}
|
95
homeassistant/components/coronavirus/__init__.py
Normal file
95
homeassistant/components/coronavirus/__init__.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""The Coronavirus integration."""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import aiohttp
|
||||
import async_timeout
|
||||
import coronavirus
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import aiohttp_client, entity_registry, update_coordinator
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
PLATFORMS = ["sensor"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
"""Set up the Coronavirus component."""
|
||||
# Make sure coordinator is initialized.
|
||||
await get_coordinator(hass)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
"""Set up Coronavirus from a config entry."""
|
||||
if isinstance(entry.data["country"], int):
|
||||
hass.config_entries.async_update_entry(
|
||||
entry, data={**entry.data, "country": entry.title}
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_migrator(entity_entry: entity_registry.RegistryEntry):
|
||||
"""Migrate away from unstable ID."""
|
||||
country, info_type = entity_entry.unique_id.rsplit("-", 1)
|
||||
if not country.isnumeric():
|
||||
return None
|
||||
return {"new_unique_id": f"{entry.title}-{info_type}"}
|
||||
|
||||
await entity_registry.async_migrate_entries(
|
||||
hass, entry.entry_id, _async_migrator
|
||||
)
|
||||
|
||||
if not entry.unique_id:
|
||||
hass.config_entries.async_update_entry(entry, unique_id=entry.data["country"])
|
||||
|
||||
for component in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
"""Unload a config entry."""
|
||||
unload_ok = all(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
hass.config_entries.async_forward_entry_unload(entry, component)
|
||||
for component in PLATFORMS
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
||||
async def get_coordinator(hass):
|
||||
"""Get the data update coordinator."""
|
||||
if DOMAIN in hass.data:
|
||||
return hass.data[DOMAIN]
|
||||
|
||||
async def async_get_cases():
|
||||
try:
|
||||
with async_timeout.timeout(10):
|
||||
return {
|
||||
case.country: case
|
||||
for case in await coronavirus.get_cases(
|
||||
aiohttp_client.async_get_clientsession(hass)
|
||||
)
|
||||
}
|
||||
except (asyncio.TimeoutError, aiohttp.ClientError):
|
||||
raise update_coordinator.UpdateFailed
|
||||
|
||||
hass.data[DOMAIN] = update_coordinator.DataUpdateCoordinator(
|
||||
hass,
|
||||
logging.getLogger(__name__),
|
||||
name=DOMAIN,
|
||||
update_method=async_get_cases,
|
||||
update_interval=timedelta(hours=1),
|
||||
)
|
||||
await hass.data[DOMAIN].async_refresh()
|
||||
return hass.data[DOMAIN]
|
45
homeassistant/components/coronavirus/config_flow.py
Normal file
45
homeassistant/components/coronavirus/config_flow.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""Config flow for Coronavirus integration."""
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
||||
from . import get_coordinator
|
||||
from .const import DOMAIN, OPTION_WORLDWIDE # pylint:disable=unused-import
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for Coronavirus."""
|
||||
|
||||
VERSION = 1
|
||||
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
|
||||
|
||||
_options = None
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle the initial step."""
|
||||
errors = {}
|
||||
|
||||
if self._options is None:
|
||||
self._options = {OPTION_WORLDWIDE: "Worldwide"}
|
||||
coordinator = await get_coordinator(self.hass)
|
||||
for case in sorted(
|
||||
coordinator.data.values(), key=lambda case: case.country
|
||||
):
|
||||
self._options[case.country] = case.country
|
||||
|
||||
if user_input is not None:
|
||||
await self.async_set_unique_id(user_input["country"])
|
||||
self._abort_if_unique_id_configured()
|
||||
return self.async_create_entry(
|
||||
title=self._options[user_input["country"]], data=user_input
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema({vol.Required("country"): vol.In(self._options)}),
|
||||
errors=errors,
|
||||
)
|
6
homeassistant/components/coronavirus/const.py
Normal file
6
homeassistant/components/coronavirus/const.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""Constants for the Coronavirus integration."""
|
||||
from coronavirus import DEFAULT_SOURCE
|
||||
|
||||
DOMAIN = "coronavirus"
|
||||
OPTION_WORLDWIDE = "__worldwide"
|
||||
ATTRIBUTION = f"Data provided by {DEFAULT_SOURCE.NAME}"
|
12
homeassistant/components/coronavirus/manifest.json
Normal file
12
homeassistant/components/coronavirus/manifest.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"domain": "coronavirus",
|
||||
"name": "Coronavirus (COVID-19)",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/coronavirus",
|
||||
"requirements": ["coronavirus==1.0.1"],
|
||||
"ssdp": [],
|
||||
"zeroconf": [],
|
||||
"homekit": {},
|
||||
"dependencies": [],
|
||||
"codeowners": ["@home_assistant/core"]
|
||||
}
|
69
homeassistant/components/coronavirus/sensor.py
Normal file
69
homeassistant/components/coronavirus/sensor.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""Sensor platform for the Corona virus."""
|
||||
from homeassistant.const import ATTR_ATTRIBUTION
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from . import get_coordinator
|
||||
from .const import ATTRIBUTION, OPTION_WORLDWIDE
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Defer sensor setup to the shared sensor module."""
|
||||
coordinator = await get_coordinator(hass)
|
||||
|
||||
async_add_entities(
|
||||
CoronavirusSensor(coordinator, config_entry.data["country"], info_type)
|
||||
for info_type in ("confirmed", "recovered", "deaths", "current")
|
||||
)
|
||||
|
||||
|
||||
class CoronavirusSensor(Entity):
|
||||
"""Sensor representing corona virus data."""
|
||||
|
||||
name = None
|
||||
unique_id = None
|
||||
|
||||
def __init__(self, coordinator, country, info_type):
|
||||
"""Initialize coronavirus sensor."""
|
||||
if country == OPTION_WORLDWIDE:
|
||||
self.name = f"Worldwide Coronavirus {info_type}"
|
||||
else:
|
||||
self.name = f"{coordinator.data[country].country} Coronavirus {info_type}"
|
||||
self.unique_id = f"{country}-{info_type}"
|
||||
self.coordinator = coordinator
|
||||
self.country = country
|
||||
self.info_type = info_type
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return if sensor is available."""
|
||||
return self.coordinator.last_update_success and (
|
||||
self.country in self.coordinator.data or self.country == OPTION_WORLDWIDE
|
||||
)
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""State of the sensor."""
|
||||
if self.country == OPTION_WORLDWIDE:
|
||||
return sum(
|
||||
getattr(case, self.info_type) for case in self.coordinator.data.values()
|
||||
)
|
||||
|
||||
return getattr(self.coordinator.data[self.country], self.info_type)
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return unit of measurement."""
|
||||
return "people"
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return device attributes."""
|
||||
return {ATTR_ATTRIBUTION: ATTRIBUTION}
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""When entity is added to hass."""
|
||||
self.coordinator.async_add_listener(self.async_write_ha_state)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""When entity will be removed from hass."""
|
||||
self.coordinator.async_remove_listener(self.async_write_ha_state)
|
16
homeassistant/components/coronavirus/strings.json
Normal file
16
homeassistant/components/coronavirus/strings.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"config": {
|
||||
"title": "Coronavirus",
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Pick a country to monitor",
|
||||
"data": {
|
||||
"country": "Country"
|
||||
}
|
||||
}
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "This country is already configured."
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
"domain": "eight_sleep",
|
||||
"name": "Eight Sleep",
|
||||
"documentation": "https://www.home-assistant.io/integrations/eight_sleep",
|
||||
"requirements": ["pyeight==0.1.3"],
|
||||
"requirements": ["pyeight==0.1.4"],
|
||||
"dependencies": [],
|
||||
"codeowners": ["@mezz64"]
|
||||
}
|
||||
|
@@ -261,14 +261,26 @@ class EightUserSensor(EightSleepUserEntity):
|
||||
bed_temp = None
|
||||
|
||||
if "current" in self._sensor_root:
|
||||
state_attr[ATTR_RESP_RATE] = round(self._attr["resp_rate"], 2)
|
||||
state_attr[ATTR_HEART_RATE] = round(self._attr["heart_rate"], 2)
|
||||
try:
|
||||
state_attr[ATTR_RESP_RATE] = round(self._attr["resp_rate"], 2)
|
||||
except TypeError:
|
||||
state_attr[ATTR_RESP_RATE] = None
|
||||
try:
|
||||
state_attr[ATTR_HEART_RATE] = round(self._attr["heart_rate"], 2)
|
||||
except TypeError:
|
||||
state_attr[ATTR_HEART_RATE] = None
|
||||
state_attr[ATTR_SLEEP_STAGE] = self._attr["stage"]
|
||||
state_attr[ATTR_ROOM_TEMP] = room_temp
|
||||
state_attr[ATTR_BED_TEMP] = bed_temp
|
||||
elif "last" in self._sensor_root:
|
||||
state_attr[ATTR_AVG_RESP_RATE] = round(self._attr["resp_rate"], 2)
|
||||
state_attr[ATTR_AVG_HEART_RATE] = round(self._attr["heart_rate"], 2)
|
||||
try:
|
||||
state_attr[ATTR_AVG_RESP_RATE] = round(self._attr["resp_rate"], 2)
|
||||
except TypeError:
|
||||
state_attr[ATTR_AVG_RESP_RATE] = None
|
||||
try:
|
||||
state_attr[ATTR_AVG_HEART_RATE] = round(self._attr["heart_rate"], 2)
|
||||
except TypeError:
|
||||
state_attr[ATTR_AVG_HEART_RATE] = None
|
||||
state_attr[ATTR_AVG_ROOM_TEMP] = room_temp
|
||||
state_attr[ATTR_AVG_BED_TEMP] = bed_temp
|
||||
|
||||
|
@@ -47,7 +47,7 @@ async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry)
|
||||
await server.async_update()
|
||||
server.start_periodic_update()
|
||||
|
||||
# Set up platform(s).
|
||||
# Set up platforms.
|
||||
for platform in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(config_entry, platform)
|
||||
@@ -103,7 +103,6 @@ class MinecraftServer:
|
||||
self._mc_status = MCStatus(self.host, self.port)
|
||||
|
||||
# Data provided by 3rd party library
|
||||
self.description = None
|
||||
self.version = None
|
||||
self.protocol_version = None
|
||||
self.latency_time = None
|
||||
@@ -168,7 +167,6 @@ class MinecraftServer:
|
||||
)
|
||||
|
||||
# Got answer to request, update properties.
|
||||
self.description = status_response.description["text"]
|
||||
self.version = status_response.version.name
|
||||
self.protocol_version = status_response.version.protocol
|
||||
self.players_online = status_response.players.online
|
||||
@@ -185,7 +183,6 @@ class MinecraftServer:
|
||||
self._last_status_request_failed = False
|
||||
except OSError as error:
|
||||
# No answer to request, set all properties to unknown.
|
||||
self.description = None
|
||||
self.version = None
|
||||
self.protocol_version = None
|
||||
self.players_online = None
|
||||
|
@@ -1,7 +1,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 106
|
||||
PATCH_VERSION = "2"
|
||||
PATCH_VERSION = "4"
|
||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER = (3, 7, 0)
|
||||
|
@@ -17,6 +17,7 @@ FLOWS = [
|
||||
"cast",
|
||||
"cert_expiry",
|
||||
"coolmaster",
|
||||
"coronavirus",
|
||||
"daikin",
|
||||
"deconz",
|
||||
"dialogflow",
|
||||
|
@@ -11,7 +11,7 @@ import asyncio
|
||||
from collections import OrderedDict
|
||||
from itertools import chain
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, cast
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Optional, cast
|
||||
|
||||
import attr
|
||||
|
||||
@@ -560,3 +560,21 @@ def async_setup_entity_restore(
|
||||
states.async_set(entry.entity_id, STATE_UNAVAILABLE, attrs)
|
||||
|
||||
hass.bus.async_listen(EVENT_HOMEASSISTANT_START, _write_unavailable_states)
|
||||
|
||||
|
||||
async def async_migrate_entries(
|
||||
hass: HomeAssistantType,
|
||||
config_entry_id: str,
|
||||
entry_callback: Callable[[RegistryEntry], Optional[dict]],
|
||||
) -> None:
|
||||
"""Migrator of unique IDs."""
|
||||
ent_reg = await async_get_registry(hass)
|
||||
|
||||
for entry in ent_reg.entities.values():
|
||||
if entry.config_entry_id != config_entry_id:
|
||||
continue
|
||||
|
||||
updates = entry_callback(entry)
|
||||
|
||||
if updates is not None:
|
||||
ent_reg.async_update_entity(entry.entity_id, **updates) # type: ignore
|
||||
|
@@ -398,6 +398,9 @@ connect-box==0.2.5
|
||||
# homeassistant.components.xiaomi_miio
|
||||
construct==2.9.45
|
||||
|
||||
# homeassistant.components.coronavirus
|
||||
coronavirus==1.0.1
|
||||
|
||||
# homeassistant.scripts.credstash
|
||||
# credstash==1.15.0
|
||||
|
||||
@@ -1223,7 +1226,7 @@ pyeconet==0.0.11
|
||||
pyedimax==0.2.1
|
||||
|
||||
# homeassistant.components.eight_sleep
|
||||
pyeight==0.1.3
|
||||
pyeight==0.1.4
|
||||
|
||||
# homeassistant.components.emby
|
||||
pyemby==1.6
|
||||
|
@@ -143,6 +143,9 @@ colorlog==4.1.0
|
||||
# homeassistant.components.xiaomi_miio
|
||||
construct==2.9.45
|
||||
|
||||
# homeassistant.components.coronavirus
|
||||
coronavirus==1.0.1
|
||||
|
||||
# homeassistant.scripts.credstash
|
||||
# credstash==1.15.0
|
||||
|
||||
|
1
tests/components/coronavirus/__init__.py
Normal file
1
tests/components/coronavirus/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Tests for the Coronavirus integration."""
|
33
tests/components/coronavirus/test_config_flow.py
Normal file
33
tests/components/coronavirus/test_config_flow.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Test the Coronavirus config flow."""
|
||||
from asynctest import patch
|
||||
|
||||
from homeassistant import config_entries, setup
|
||||
from homeassistant.components.coronavirus.const import DOMAIN, OPTION_WORLDWIDE
|
||||
|
||||
|
||||
async def test_form(hass):
|
||||
"""Test we get the form."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch("coronavirus.get_cases", return_value=[],), patch(
|
||||
"homeassistant.components.coronavirus.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.coronavirus.async_setup_entry", return_value=True,
|
||||
) as mock_setup_entry:
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], {"country": OPTION_WORLDWIDE},
|
||||
)
|
||||
assert result2["type"] == "create_entry"
|
||||
assert result2["title"] == "Worldwide"
|
||||
assert result2["result"].unique_id == OPTION_WORLDWIDE
|
||||
assert result2["data"] == {
|
||||
"country": OPTION_WORLDWIDE,
|
||||
}
|
||||
await hass.async_block_till_done()
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
58
tests/components/coronavirus/test_init.py
Normal file
58
tests/components/coronavirus/test_init.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""Test init of Coronavirus integration."""
|
||||
from asynctest import Mock, patch
|
||||
|
||||
from homeassistant.components.coronavirus.const import DOMAIN, OPTION_WORLDWIDE
|
||||
from homeassistant.helpers import entity_registry
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import MockConfigEntry, mock_registry
|
||||
|
||||
|
||||
async def test_migration(hass):
|
||||
"""Test that we can migrate coronavirus to stable unique ID."""
|
||||
nl_entry = MockConfigEntry(domain=DOMAIN, title="Netherlands", data={"country": 34})
|
||||
nl_entry.add_to_hass(hass)
|
||||
worldwide_entry = MockConfigEntry(
|
||||
domain=DOMAIN, title="Worldwide", data={"country": OPTION_WORLDWIDE}
|
||||
)
|
||||
worldwide_entry.add_to_hass(hass)
|
||||
mock_registry(
|
||||
hass,
|
||||
{
|
||||
"sensor.netherlands_confirmed": entity_registry.RegistryEntry(
|
||||
entity_id="sensor.netherlands_confirmed",
|
||||
unique_id="34-confirmed",
|
||||
platform="coronavirus",
|
||||
config_entry_id=nl_entry.entry_id,
|
||||
),
|
||||
"sensor.worldwide_confirmed": entity_registry.RegistryEntry(
|
||||
entity_id="sensor.worldwide_confirmed",
|
||||
unique_id="__worldwide-confirmed",
|
||||
platform="coronavirus",
|
||||
config_entry_id=worldwide_entry.entry_id,
|
||||
),
|
||||
},
|
||||
)
|
||||
with patch(
|
||||
"coronavirus.get_cases",
|
||||
return_value=[
|
||||
Mock(country="Netherlands", confirmed=10, recovered=8, deaths=1, current=1),
|
||||
Mock(country="Germany", confirmed=1, recovered=0, deaths=0, current=0),
|
||||
],
|
||||
):
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
ent_reg = await entity_registry.async_get_registry(hass)
|
||||
|
||||
sensor_nl = ent_reg.async_get("sensor.netherlands_confirmed")
|
||||
assert sensor_nl.unique_id == "Netherlands-confirmed"
|
||||
|
||||
sensor_worldwide = ent_reg.async_get("sensor.worldwide_confirmed")
|
||||
assert sensor_worldwide.unique_id == "__worldwide-confirmed"
|
||||
|
||||
assert hass.states.get("sensor.netherlands_confirmed").state == "10"
|
||||
assert hass.states.get("sensor.worldwide_confirmed").state == "11"
|
||||
|
||||
assert nl_entry.unique_id == "Netherlands"
|
||||
assert worldwide_entry.unique_id == OPTION_WORLDWIDE
|
Reference in New Issue
Block a user