fix: Format using black
This commit is contained in:
parent
b8be375ddb
commit
79280d9d59
@ -1,4 +1,4 @@
|
|||||||
'''
|
"""
|
||||||
This file is part of JANINE.
|
This file is part of JANINE.
|
||||||
|
|
||||||
JANINE is free software: you can redistribute it and/or modify
|
JANINE is free software: you can redistribute it and/or modify
|
||||||
@ -13,58 +13,62 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with JANINE. If not, see <https://www.gnu.org/licenses/>.
|
along with JANINE. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
def pad_time_component(c):
|
def pad_time_component(c):
|
||||||
'''
|
"""
|
||||||
If we have 12:08, it gets turned into 12:8, so we need to pad
|
If we have 12:08, it gets turned into 12:8, so we need to pad
|
||||||
the components with a leading zero, if there is none.
|
the components with a leading zero, if there is none.
|
||||||
'''
|
"""
|
||||||
if len(c) != 2:
|
if len(c) != 2:
|
||||||
return f'0{c}'
|
return f"0{c}"
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
def format_time(time_str):
|
def format_time(time_str):
|
||||||
'''
|
"""
|
||||||
Reformat ISO style time data to a more
|
Reformat ISO style time data to a more
|
||||||
readable format.
|
readable format.
|
||||||
'''
|
"""
|
||||||
try:
|
try:
|
||||||
date = datetime.datetime.fromisoformat(time_str)
|
date = datetime.datetime.fromisoformat(time_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return time_str
|
return time_str
|
||||||
|
|
||||||
return f'{date.day}.{date.month}.{date.year} {pad_time_component(date.hour)}:{pad_time_component(date.minute)}'
|
return f"{date.day}.{date.month}.{date.year} {pad_time_component(date.hour)}:{pad_time_component(date.minute)}"
|
||||||
|
|
||||||
|
|
||||||
def format_warning(warning):
|
def format_warning(warning):
|
||||||
'''
|
"""
|
||||||
Send a warning to all the recipients
|
Send a warning to all the recipients
|
||||||
'''
|
"""
|
||||||
# Reformat the message a bit
|
# Reformat the message a bit
|
||||||
effective_time = format_time(warning.effective_from)
|
effective_time = format_time(warning.effective_from)
|
||||||
expiry_time = format_time(warning.expires)
|
expiry_time = format_time(warning.expires)
|
||||||
body = f'''*{warning.headline}*
|
body = f"""*{warning.headline}*
|
||||||
({effective_time} bis {expiry_time})
|
({effective_time} bis {expiry_time})
|
||||||
|
|
||||||
{warning.description}'''
|
{warning.description}"""
|
||||||
|
|
||||||
if warning.instruction:
|
if warning.instruction:
|
||||||
body = f'''{body}
|
body = f"""{body}
|
||||||
|
|
||||||
{warning.instruction}'''
|
{warning.instruction}"""
|
||||||
|
|
||||||
# Smells like script injection, but okay
|
# Smells like script injection, but okay
|
||||||
body = body.replace('<br>', '\n')
|
body = body.replace("<br>", "\n")
|
||||||
body = body.replace('<br/>', '\n')
|
body = body.replace("<br/>", "\n")
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
|
||||||
def find_one(func, array):
|
def find_one(func, array):
|
||||||
'''
|
"""
|
||||||
Utility function
|
Utility function
|
||||||
|
|
||||||
Return the first element in array for which func returns True.
|
Return the first element in array for which func returns True.
|
||||||
'''
|
"""
|
||||||
for e in array:
|
for e in array:
|
||||||
if func(e):
|
if func(e):
|
||||||
return e
|
return e
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
'''
|
"""
|
||||||
This file is part of JANINE.
|
This file is part of JANINE.
|
||||||
|
|
||||||
JANINE is free software: you can redistribute it and/or modify
|
JANINE is free software: you can redistribute it and/or modify
|
||||||
@ -13,7 +13,7 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with JANINE. If not, see <https://www.gnu.org/licenses/>.
|
along with JANINE. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
from urllib3.exceptions import MaxRetryError
|
from urllib3.exceptions import MaxRetryError
|
||||||
@ -26,9 +26,10 @@ from janine.modules.janine.helpers import format_warning
|
|||||||
import requests
|
import requests
|
||||||
import aioxmpp
|
import aioxmpp
|
||||||
|
|
||||||
logger = logging.getLogger('mira.modules.janine.janine')
|
logger = logging.getLogger("mira.modules.janine.janine")
|
||||||
|
|
||||||
|
NAME = "janine"
|
||||||
|
|
||||||
NAME = 'janine'
|
|
||||||
|
|
||||||
class JanineModule(BaseModule):
|
class JanineModule(BaseModule):
|
||||||
__instance = None
|
__instance = None
|
||||||
@ -39,60 +40,61 @@ class JanineModule(BaseModule):
|
|||||||
JanineModule(base, **kwargs)
|
JanineModule(base, **kwargs)
|
||||||
|
|
||||||
return JanineModule.__instance
|
return JanineModule.__instance
|
||||||
|
|
||||||
def __init__(self, base, **kwargs):
|
def __init__(self, base, **kwargs):
|
||||||
if JanineModule.__instance != None:
|
if JanineModule.__instance != None:
|
||||||
raise Exception('Trying to init singleton twice')
|
raise Exception("Trying to init singleton twice")
|
||||||
|
|
||||||
super().__init__(base, **kwargs)
|
super().__init__(base, **kwargs)
|
||||||
JanineModule.__instance = self
|
JanineModule.__instance = self
|
||||||
|
|
||||||
self._subcommand_table = {
|
self._subcommand_table = {
|
||||||
'subscribe': self._subscribe,
|
"subscribe": self._subscribe,
|
||||||
'unsubscribe': self._unsubscribe,
|
"unsubscribe": self._unsubscribe,
|
||||||
'hilfe': self._help,
|
"hilfe": self._help,
|
||||||
'*': self._any
|
"*": self._any,
|
||||||
}
|
}
|
||||||
self._channels = self._stm.get_data('channels')
|
self._channels = self._stm.get_data("channels")
|
||||||
if not self._channels:
|
if not self._channels:
|
||||||
# TODO: Move out of the constructor. Perform this asynchronously,
|
# TODO: Move out of the constructor. Perform this asynchronously,
|
||||||
# and just refuse to process commands before we're done. Start the
|
# and just refuse to process commands before we're done. Start the
|
||||||
# request loop afterwards.
|
# request loop afterwards.
|
||||||
logger.info('Channels do not exist. Downloading...')
|
logger.info("Channels do not exist. Downloading...")
|
||||||
req = requests.get(MiscDataSources.channels())
|
req = requests.get(MiscDataSources.channels())
|
||||||
channels = req.json()
|
channels = req.json()
|
||||||
self._channels = [channels[key].get('NAME', '') for key in channels]
|
self._channels = [channels[key].get("NAME", "") for key in channels]
|
||||||
self._stm.set_data('channels', self._channels)
|
self._stm.set_data("channels", self._channels)
|
||||||
logger.info('Done')
|
logger.info("Done")
|
||||||
|
|
||||||
self._warnings0 = list(map(stub_warning, self._stm.get_data('warnings')))
|
self._warnings0 = list(map(stub_warning, self._stm.get_data("warnings")))
|
||||||
self._warnings1 = []
|
self._warnings1 = []
|
||||||
self._refresh_timeout = self.get_option('refresh_timeout', 15 * 60)
|
self._refresh_timeout = self.get_option("refresh_timeout", 15 * 60)
|
||||||
self._sources = list(map(WarningSources.source_by_name, self._config['sources']))
|
self._sources = list(
|
||||||
|
map(WarningSources.source_by_name, self._config["sources"])
|
||||||
|
)
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
periodic = loop.create_task(self._periodic_ticker())
|
periodic = loop.create_task(self._periodic_ticker())
|
||||||
|
|
||||||
async def _periodic_ticker(self):
|
async def _periodic_ticker(self):
|
||||||
'''
|
"""
|
||||||
"Executes" every self._refresh_timeout seconds to fetch all
|
"Executes" every self._refresh_timeout seconds to fetch all
|
||||||
configured warnings and send them to the users, if there are
|
configured warnings and send them to the users, if there are
|
||||||
any new ones.
|
any new ones.
|
||||||
'''
|
"""
|
||||||
while True:
|
while True:
|
||||||
logger.debug('Refreshing warning list')
|
logger.debug("Refreshing warning list")
|
||||||
await self._request_warnings()
|
await self._request_warnings()
|
||||||
|
|
||||||
self._stm.set_data('warnings',
|
self._stm.set_data("warnings", [x.id for x in self._warnings0])
|
||||||
[x.id for x in self._warnings0])
|
|
||||||
|
|
||||||
await asyncio.sleep(self._refresh_timeout)
|
await asyncio.sleep(self._refresh_timeout)
|
||||||
|
|
||||||
async def _request_warnings(self):
|
async def _request_warnings(self):
|
||||||
'''
|
"""
|
||||||
Requests warnings from all configured warning sources and
|
Requests warnings from all configured warning sources and
|
||||||
sends new ones as notifications
|
sends new ones as notifications
|
||||||
'''
|
"""
|
||||||
self._warnings1 = self._warnings0
|
self._warnings1 = self._warnings0
|
||||||
self._warnings0 = []
|
self._warnings0 = []
|
||||||
for source in self._sources:
|
for source in self._sources:
|
||||||
@ -100,7 +102,7 @@ class JanineModule(BaseModule):
|
|||||||
req = requests.get(source)
|
req = requests.get(source)
|
||||||
self._warnings0 += parse_data(req.json())
|
self._warnings0 += parse_data(req.json())
|
||||||
except MaxRetryError:
|
except MaxRetryError:
|
||||||
logger.warn('Connection timeout for request to %s', source)
|
logger.warn("Connection timeout for request to %s", source)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Find new warnings and send them out
|
# Find new warnings and send them out
|
||||||
@ -115,18 +117,21 @@ class JanineModule(BaseModule):
|
|||||||
|
|
||||||
async def _subscribe(self, cmd, msg):
|
async def _subscribe(self, cmd, msg):
|
||||||
if len(cmd) < 2:
|
if len(cmd) < 2:
|
||||||
self.send_message(msg.from_, 'Du hast keinen Landkreis angegeben')
|
self.send_message(msg.from_, "Du hast keinen Landkreis angegeben")
|
||||||
return
|
return
|
||||||
|
|
||||||
landkreis = ' '.join(cmd[1:])
|
landkreis = " ".join(cmd[1:])
|
||||||
if not landkreis in self._channels:
|
if not landkreis in self._channels:
|
||||||
self.send_message(msg.from_, 'Der angegebene Landkreis "%s" existiert nicht' % (landkreis))
|
self.send_message(
|
||||||
|
msg.from_, 'Der angegebene Landkreis "%s" existiert nicht' % (landkreis)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
bare = str(msg.from_.bare())
|
bare = str(msg.from_.bare())
|
||||||
if self._sum.is_subscribed_to(bare, landkreis):
|
if self._sum.is_subscribed_to(bare, landkreis):
|
||||||
self.send_message(msg.from_,
|
self.send_message(
|
||||||
'Du hast den "%s" bereits abonniert' % (landkreis))
|
msg.from_, 'Du hast den "%s" bereits abonniert' % (landkreis)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._sum.add_subscription_for(bare, landkreis)
|
self._sum.add_subscription_for(bare, landkreis)
|
||||||
@ -137,33 +142,40 @@ class JanineModule(BaseModule):
|
|||||||
|
|
||||||
async def _unsubscribe(self, cmd, msg):
|
async def _unsubscribe(self, cmd, msg):
|
||||||
if len(cmd) < 2:
|
if len(cmd) < 2:
|
||||||
self.send_message(msg.from_, 'Du hast keinen Landkreis angegeben')
|
self.send_message(msg.from_, "Du hast keinen Landkreis angegeben")
|
||||||
return
|
return
|
||||||
|
|
||||||
landkreis = ' '.join(cmd[1:])
|
landkreis = " ".join(cmd[1:])
|
||||||
bare = str(msg.from_.bare())
|
bare = str(msg.from_.bare())
|
||||||
if not self._sum.is_subscribed_to(bare, landkreis):
|
if not self._sum.is_subscribed_to(bare, landkreis):
|
||||||
self.send_message(msg.from_, 'Du hast "%s" nicht abonniert' % (landkreis))
|
self.send_message(msg.from_, 'Du hast "%s" nicht abonniert' % (landkreis))
|
||||||
return
|
return
|
||||||
|
|
||||||
self._sum.remove_subscription_for(bare, landkreis)
|
self._sum.remove_subscription_for(bare, landkreis)
|
||||||
self.send_message(msg.from_, 'Du erhälst nun keine Nachrichten zu "%s" mehr' % (landkreis))
|
self.send_message(
|
||||||
|
msg.from_, 'Du erhälst nun keine Nachrichten zu "%s" mehr' % (landkreis)
|
||||||
|
)
|
||||||
|
|
||||||
async def _help(self, cmd, msg):
|
async def _help(self, cmd, msg):
|
||||||
body = '''Verfügbare Befehle:
|
body = """Verfügbare Befehle:
|
||||||
|
|
||||||
subscribe <Landkreis> - Abonniere einen Landkreis
|
subscribe <Landkreis> - Abonniere einen Landkreis
|
||||||
unsubscribe <Landkreis> - Entferne das Abonnement zu einem Landkreis
|
unsubscribe <Landkreis> - Entferne das Abonnement zu einem Landkreis
|
||||||
help - Gebe diese Hilfe aus'''
|
help - Gebe diese Hilfe aus"""
|
||||||
self.send_message(msg.from_, body)
|
self.send_message(msg.from_, body)
|
||||||
|
|
||||||
async def _any(self, cmd, msg):
|
async def _any(self, cmd, msg):
|
||||||
if not cmd:
|
if not cmd:
|
||||||
self.send_message(msg.from_,
|
self.send_message(
|
||||||
'Ich bin die Jabber Anwendung für Notfallinformations- und -Nachrichten-Empfang')
|
msg.from_,
|
||||||
|
"Ich bin die Jabber Anwendung für Notfallinformations- und -Nachrichten-Empfang",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.send_message(msg.from_,
|
self.send_message(
|
||||||
'Unbekannter Befehl "%s". "janine hilfe" gibt alle bekannten Befehle aus' % (cmd[0]))
|
msg.from_,
|
||||||
|
'Unbekannter Befehl "%s". "janine hilfe" gibt alle bekannten Befehle aus'
|
||||||
|
% (cmd[0]),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_instance(base, **kwargs):
|
def get_instance(base, **kwargs):
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
'''
|
"""
|
||||||
This file is part of JANINE.
|
This file is part of JANINE.
|
||||||
|
|
||||||
JANINE is free software: you can redistribute it and/or modify
|
JANINE is free software: you can redistribute it and/or modify
|
||||||
@ -13,44 +13,48 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with JANINE. If not, see <https://www.gnu.org/licenses/>.
|
along with JANINE. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
|
|
||||||
class WarningSources:
|
class WarningSources:
|
||||||
'''
|
"""
|
||||||
A collection of sources of the BBK
|
A collection of sources of the BBK
|
||||||
'''
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bbk_dwd():
|
def bbk_dwd():
|
||||||
return 'https://warnung.bund.de/bbk.dwd/unwetter.json'
|
return "https://warnung.bund.de/bbk.dwd/unwetter.json"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bbk_mowas():
|
def bbk_mowas():
|
||||||
return 'https://warnung.bund.de/bbk.mowas/gefahrendurchsagen.json'
|
return "https://warnung.bund.de/bbk.mowas/gefahrendurchsagen.json"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bbk_biwapp():
|
def bbk_biwapp():
|
||||||
return 'https://warnung.bund.de/bbk.biwapp/warnmeldungen.json'
|
return "https://warnung.bund.de/bbk.biwapp/warnmeldungen.json"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bbk_ihp():
|
def bbk_ihp():
|
||||||
return 'https://warnung.bund.de/bbk.lhp/hochwassermeldungen.json'
|
return "https://warnung.bund.de/bbk.lhp/hochwassermeldungen.json"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def source_by_name(name):
|
def source_by_name(name):
|
||||||
return {
|
return {
|
||||||
'IHP': WarningSources.bbk_ihp(),
|
"IHP": WarningSources.bbk_ihp(),
|
||||||
'DWD': WarningSources.bbk_dwd(),
|
"DWD": WarningSources.bbk_dwd(),
|
||||||
'MOWAS': WarningSources.bbk_mowas(),
|
"MOWAS": WarningSources.bbk_mowas(),
|
||||||
'BIWAPP': WarningSources.bbk_biwapp()
|
"BIWAPP": WarningSources.bbk_biwapp(),
|
||||||
}[name]
|
}[name]
|
||||||
|
|
||||||
|
|
||||||
class MiscDataSources:
|
class MiscDataSources:
|
||||||
'''
|
"""
|
||||||
A collection of other data sources for various use cases
|
A collection of other data sources for various use cases
|
||||||
'''
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def channels():
|
def channels():
|
||||||
'''
|
"""
|
||||||
These are the valid names to retrieve warnings for
|
These are the valid names to retrieve warnings for
|
||||||
'''
|
"""
|
||||||
return 'https://warnung.bund.de/assets/json/converted_gemeinden.json'
|
return "https://warnung.bund.de/assets/json/converted_gemeinden.json"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
'''
|
"""
|
||||||
Copyright (C) 2021 Alexander "PapaTutuWawa"
|
Copyright (C) 2021 Alexander "PapaTutuWawa"
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
@ -13,70 +13,82 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
from janine.modules.janine.helpers import find_one
|
from janine.modules.janine.helpers import find_one
|
||||||
|
|
||||||
Warning_ = namedtuple('Warning_', ['id',
|
Warning_ = namedtuple(
|
||||||
'sent',
|
"Warning_",
|
||||||
'effective_from',
|
[
|
||||||
'expires',
|
"id",
|
||||||
'urgency',
|
"sent",
|
||||||
'sender',
|
"effective_from",
|
||||||
'headline',
|
"expires",
|
||||||
'description',
|
"urgency",
|
||||||
'instruction',
|
"sender",
|
||||||
'landkreise'])
|
"headline",
|
||||||
|
"description",
|
||||||
|
"instruction",
|
||||||
|
"landkreise",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def stub_warning(id_):
|
def stub_warning(id_):
|
||||||
'''
|
"""
|
||||||
Returns a stubbed warning for loading warnings from disk.
|
Returns a stubbed warning for loading warnings from disk.
|
||||||
The only real attribute is the @id_ .
|
The only real attribute is the @id_ .
|
||||||
'''
|
"""
|
||||||
return Warning_(id=id_,
|
return Warning_(
|
||||||
sent='',
|
id=id_,
|
||||||
effective_from='',
|
sent="",
|
||||||
expires='',
|
effective_from="",
|
||||||
urgency='',
|
expires="",
|
||||||
sender='',
|
urgency="",
|
||||||
headline='',
|
sender="",
|
||||||
description='',
|
headline="",
|
||||||
instruction='',
|
description="",
|
||||||
landkreise=[])
|
instruction="",
|
||||||
|
landkreise=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def to_warning(data):
|
def to_warning(data):
|
||||||
'''
|
"""
|
||||||
Returns a Warning given the raw data
|
Returns a Warning given the raw data
|
||||||
'''
|
"""
|
||||||
info = find_one(lambda x: 'headline' in x.keys(), data['info'])
|
info = find_one(lambda x: "headline" in x.keys(), data["info"])
|
||||||
return Warning_(id=data['identifier'],
|
return Warning_(
|
||||||
sent=data['sent'],
|
id=data["identifier"],
|
||||||
# Not all items have to have those
|
sent=data["sent"],
|
||||||
effective_from=info.get('effective', 'N/A'),
|
# Not all items have to have those
|
||||||
# Not all items have to have those
|
effective_from=info.get("effective", "N/A"),
|
||||||
expires=info.get('expires', 'N/A'),
|
# Not all items have to have those
|
||||||
urgency=info['urgency'],
|
expires=info.get("expires", "N/A"),
|
||||||
# Not all items have to have those
|
urgency=info["urgency"],
|
||||||
sender=info.get('senderName', 'N/A'),
|
# Not all items have to have those
|
||||||
headline=info['headline'],
|
sender=info.get("senderName", "N/A"),
|
||||||
description=info['description'],
|
headline=info["headline"],
|
||||||
instruction=info.get('instruction', ''),
|
description=info["description"],
|
||||||
landkreise=get_landkreise(data))
|
instruction=info.get("instruction", ""),
|
||||||
|
landkreise=get_landkreise(data),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_landkreise(data):
|
def get_landkreise(data):
|
||||||
'''
|
"""
|
||||||
Returns the list of Landkreise relevant to the warning in @data
|
Returns the list of Landkreise relevant to the warning in @data
|
||||||
'''
|
"""
|
||||||
info = find_one(lambda e: 'area' in e.keys(), data['info'])
|
info = find_one(lambda e: "area" in e.keys(), data["info"])
|
||||||
geocode = find_one(lambda e: 'geocode' in e.keys(), info['area'])
|
geocode = find_one(lambda e: "geocode" in e.keys(), info["area"])
|
||||||
|
|
||||||
# Note: Some items may have multiple Landkreise
|
# Note: Some items may have multiple Landkreise
|
||||||
return [e['valueName'] for e in geocode['geocode']]
|
return [e["valueName"] for e in geocode["geocode"]]
|
||||||
|
|
||||||
|
|
||||||
def parse_data(data):
|
def parse_data(data):
|
||||||
'''
|
"""
|
||||||
Reads the remote response, parses it and returns a list of warnings.
|
Reads the remote response, parses it and returns a list of warnings.
|
||||||
'''
|
"""
|
||||||
return [to_warning(el) for el in data]
|
return [to_warning(el) for el in data]
|
||||||
|
Loading…
Reference in New Issue
Block a user