Deploy script for Windows
This commit is contained in:
123
threads.py
123
threads.py
@@ -14,6 +14,8 @@ from utilities import checksum_ok
|
||||
|
||||
|
||||
class ThreadStatus(Enum):
|
||||
"""Possible thread status."""
|
||||
|
||||
OK = auto()
|
||||
NO_CONNECTION_ERR = auto()
|
||||
UNKNOWN_ERR = auto()
|
||||
@@ -22,62 +24,88 @@ class ThreadStatus(Enum):
|
||||
|
||||
|
||||
class BaseDownloadThread(QThread):
|
||||
"""Subclass QThread. Base class for the download threads."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
"""Set the status to 'UNDEFINED'."""
|
||||
super().__init__(parent)
|
||||
self.status = ThreadStatus.UNDEFINED
|
||||
|
||||
def __del__(self):
|
||||
"""Force the termination of the thread."""
|
||||
self.terminate()
|
||||
self.wait()
|
||||
|
||||
|
||||
class DownloadThread(BaseDownloadThread):
|
||||
"""Subclass BaseDownloadThread. Download the database, images and audio samples."""
|
||||
|
||||
progress = pyqtSignal(int, float)
|
||||
CHUNK = 1024**2
|
||||
_CHUNK = 512 * 1024
|
||||
_MEGA = 1024**2
|
||||
|
||||
def __init__(self):
|
||||
"""Just call super().__init__."""
|
||||
self._db = None
|
||||
self._exit_call = False
|
||||
super().__init__()
|
||||
|
||||
def __pretty_len(self, byte_obj):
|
||||
mega = len(byte_obj) / self.CHUNK
|
||||
def _pretty_len(self, byte_obj):
|
||||
"""Return a well-formatted number of downloaded MB."""
|
||||
mega = len(byte_obj) / self._MEGA
|
||||
if mega.is_integer():
|
||||
return int(mega)
|
||||
else:
|
||||
return ceil(mega)
|
||||
|
||||
def __get_download_speed(self, data, delta):
|
||||
def _get_download_speed(self, data, delta):
|
||||
"""Return the download speed in MB/s."""
|
||||
return round(
|
||||
(len(data) / self.CHUNK) / delta,
|
||||
2
|
||||
(len(data) / self._MEGA) / delta, 2
|
||||
)
|
||||
|
||||
def set_exit(self):
|
||||
self._exit_call = True
|
||||
|
||||
def run(self):
|
||||
"""Override QThread.run. Download the database, images and audio samples.
|
||||
|
||||
Handle all possible exceptions. Also extract the files
|
||||
in the local folder."""
|
||||
self.status = ThreadStatus.UNDEFINED
|
||||
self._db = None
|
||||
raw_data = bytes(0)
|
||||
try:
|
||||
db = urllib3.PoolManager().request(
|
||||
self._db = urllib3.PoolManager().request(
|
||||
'GET',
|
||||
Database.LINK_LOC,
|
||||
preload_content=False
|
||||
preload_content=False,
|
||||
timeout=4.0
|
||||
)
|
||||
while True:
|
||||
start = time()
|
||||
data = db.read(self.CHUNK)
|
||||
delta = time() - start
|
||||
if not data:
|
||||
break
|
||||
raw_data += data
|
||||
self.progress.emit(
|
||||
self.__pretty_len(raw_data),
|
||||
self.__get_download_speed(data, delta)
|
||||
)
|
||||
db.release_conn()
|
||||
except Exception: # No internet connection.
|
||||
db.release_conn()
|
||||
try:
|
||||
data = self._db.read(self._CHUNK)
|
||||
except Exception:
|
||||
raise
|
||||
else:
|
||||
delta = time() - start
|
||||
if not data:
|
||||
break
|
||||
raw_data += data
|
||||
self.progress.emit(
|
||||
self._pretty_len(raw_data),
|
||||
self._get_download_speed(data, delta)
|
||||
)
|
||||
if self._exit_call:
|
||||
self._exit_call = False
|
||||
self._db.release_conn()
|
||||
return
|
||||
except Exception: # No internet connection.
|
||||
self._db.release_conn()
|
||||
self.status = ThreadStatus.NO_CONNECTION_ERR
|
||||
return
|
||||
if db.status != 200:
|
||||
if self._db.status != 200:
|
||||
self.status = ThreadStatus.BAD_DOWNLOAD_ERR
|
||||
return
|
||||
try:
|
||||
@@ -102,42 +130,54 @@ class DownloadThread(BaseDownloadThread):
|
||||
|
||||
|
||||
class _AsyncDownloader:
|
||||
"""Mixin class for asynchronous threads."""
|
||||
|
||||
async def _download_resource(self, session, link):
|
||||
"""Return the content of 'link' as bytes."""
|
||||
resp = await session.get(link)
|
||||
return await resp.read()
|
||||
|
||||
|
||||
class UpdateSpaceWeatherThread(BaseDownloadThread, _AsyncDownloader):
|
||||
"""Subclass BaseDownloadThread. Downlaod the space weather data."""
|
||||
|
||||
__properties = ("xray", "prot_el", "ak_index", "sgas", "geo_storm")
|
||||
_PROPERTIES = ("xray", "prot_el", "ak_index", "sgas", "geo_storm")
|
||||
|
||||
def __init__(self, space_weather_data):
|
||||
"""Initialize the a local space_weather_data."""
|
||||
super().__init__()
|
||||
self.__space_weather_data = space_weather_data
|
||||
self._space_weather_data = space_weather_data
|
||||
|
||||
async def __download_property(self, session, property_name):
|
||||
async def _download_property(self, session, property_name):
|
||||
"""Download the data conteining the information of a specific property."""
|
||||
link = getattr(Constants, "SPACE_WEATHER_" + property_name.upper())
|
||||
data = await self._download_resource(session, link)
|
||||
setattr(self.__space_weather_data, property_name, str(data, 'utf-8'))
|
||||
setattr(self._space_weather_data, property_name, str(data, 'utf-8'))
|
||||
|
||||
async def __download_image(self, session, n):
|
||||
im = await self._download_resource(session, Constants.SPACE_WEATHER_IMGS[n])
|
||||
self.__space_weather_data.images[n].loadFromData(im)
|
||||
async def _download_image(self, session, n):
|
||||
"""Download the data corresponding the n-th image displayed in the screen."""
|
||||
im = await self._download_resource(
|
||||
session, Constants.SPACE_WEATHER_IMGS[n]
|
||||
)
|
||||
self._space_weather_data.images[n].loadFromData(im)
|
||||
|
||||
async def _download_resources(self):
|
||||
"""Download all the data."""
|
||||
session = aiohttp.ClientSession()
|
||||
try:
|
||||
t = []
|
||||
for p in self.__properties:
|
||||
for p in self._PROPERTIES:
|
||||
t.append(
|
||||
asyncio.create_task(self.__download_property(session, p))
|
||||
asyncio.create_task(self._download_property(session, p))
|
||||
)
|
||||
|
||||
tot_images = range(len(Constants.SPACE_WEATHER_IMGS))
|
||||
t1 = []
|
||||
for im_number in tot_images:
|
||||
t1.append(
|
||||
asyncio.create_task(self.__download_image(session, im_number))
|
||||
asyncio.create_task(
|
||||
self._download_image(session, im_number)
|
||||
)
|
||||
)
|
||||
await asyncio.gather(*t, *t1)
|
||||
except Exception:
|
||||
@@ -148,41 +188,47 @@ class UpdateSpaceWeatherThread(BaseDownloadThread, _AsyncDownloader):
|
||||
await session.close()
|
||||
|
||||
def run(self):
|
||||
"""Override QThread.run. Start the download of the data."""
|
||||
self.status = ThreadStatus.UNDEFINED
|
||||
asyncio.run(self._download_resources())
|
||||
|
||||
|
||||
class UpdateForecastThread(BaseDownloadThread, _AsyncDownloader):
|
||||
"""Subclass BaseDownloadThread. Download the forecast data."""
|
||||
|
||||
class _PropertyName(Enum):
|
||||
"""Enum used to differentiate between the two data needed."""
|
||||
FORECAST = auto()
|
||||
PROBABILITIES = auto()
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, owner):
|
||||
"""Set the owner object (a ForecastData instance)."""
|
||||
super().__init__()
|
||||
self.parent = parent
|
||||
self.owner = owner
|
||||
|
||||
async def __download_property(self, session, link, prop_name):
|
||||
async def _download_property(self, session, link, prop_name):
|
||||
"""Download the data from 'link' and set the corresponding property of the owner."""
|
||||
resp = await self._download_resource(session, link)
|
||||
resp = str(resp, 'utf-8')
|
||||
if prop_name is self._PropertyName.FORECAST:
|
||||
self.parent.forecast = resp
|
||||
self.owner.forecast = resp
|
||||
if prop_name is self._PropertyName.PROBABILITIES:
|
||||
self.parent.probabilities = resp
|
||||
self.owner.probabilities = resp
|
||||
|
||||
async def _download_resources(self):
|
||||
"""Download all the data needed."""
|
||||
session = aiohttp.ClientSession()
|
||||
try:
|
||||
await asyncio.gather(
|
||||
asyncio.create_task(
|
||||
self.__download_property(
|
||||
self._download_property(
|
||||
session,
|
||||
Constants.SPACE_WEATHER_GEO_STORM,
|
||||
self._PropertyName.FORECAST
|
||||
)
|
||||
),
|
||||
asyncio.create_task(
|
||||
self.__download_property(
|
||||
self._download_property(
|
||||
session,
|
||||
Constants.FORECAST_PROBABILITIES,
|
||||
self._PropertyName.PROBABILITIES
|
||||
@@ -197,5 +243,6 @@ class UpdateForecastThread(BaseDownloadThread, _AsyncDownloader):
|
||||
await session.close()
|
||||
|
||||
def run(self):
|
||||
"""Override QThread.run. Start the data download."""
|
||||
self.status = ThreadStatus.UNDEFINED
|
||||
asyncio.run(self._download_resources())
|
||||
|
||||
Reference in New Issue
Block a user