Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
This change encompasses refactoring the “__init__” file in the /app/l…
…ocation/ to follow the Prototype Creational Design Pattern.
  • Loading branch information
nullptr02 committed Aug 15, 2021
commit 007b0eba9be6fb19e3ac0557014e285df2d95f89
205 changes: 186 additions & 19 deletions app/location/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,205 @@
"""app.location"""
from ..coordinates import Coordinates

import copy

from ..utils import countries
from ..utils.populations import country_population

from abc import ABCMeta, abstractmethod

# pylint: disable=redefined-builtin,invalid-name
class Location: # pylint: disable=too-many-instance-attributes
"""
A location in the world affected by the coronavirus.
"""

def __init__(
self, id, country, province, coordinates, last_updated, confirmed, deaths, recovered,
): # pylint: disable=too-many-arguments
# General info.
class PrototypeLocations(metaclass=ABCMeta):
def __init__(self, id, country, province, coordinates, last_updated, confirmed, deaths, recovered, timelines):
self.id = None
self.country = None
self.province = None
self.coordinates = None

# Last update.
self.last_updated = None

# Statistics.
self.confirmed = None
self.deaths = None
self.recovered = None

# Set timelines.
self.timelines = None

def set_id(self, id):
self.id = id

def set_country(self, country):
self.country = country.strip()

def set_province(self, province):
self.province = province.strip()

def set_coordinates(self, coordinates):
self.coordinates = coordinates

# Last update.
def set_last_update(self, last_updated):
self.last_updated = last_updated

# Statistics.
def set_confirmed(self, confirmed):
self.confirmed = confirmed

def set_deaths(self, deaths):
self.deaths = deaths

def set_recovered(self, recovered):
self.recovered = recovered

def set_timelines(self, timelines):
self.timelines = timelines

def get_id(self):
return self.id

def get_country(self):
return self.country.strip()

def get_province(self):
return self.province.strip()

def get_coordinates(self):
return self.coordinates

def get_last_update(self):
return self.last_updated

def get_confirmed(self):
return self.confirmed

def get_deaths(self):
return self.deaths

def get_recovered(self):
return self.recovered

def get_timelines(self):
return self.timelines

def clone(self):
return copy.copy(self)

@property
def country_code(self):
"""
Gets the alpha-2 code represention of the country. Returns 'XX' if none is found.

:returns: The country code.
:rtype: str
"""
return (countries.country_code(self.country) or countries.DEFAULT_COUNTRY_CODE).upper()

@property
def country_population(self):
"""
Gets the population of this location.

:returns: The population.
:rtype: int
"""
return country_population(self.country_code)

def serialize(self):
"""
Serializes the location into a dict.

:returns: The serialized location.
:rtype: dict
"""
return {
# General info.
"id": self.id,
"country": self.country,
"country_code": self.country_code,
"country_population": self.country_population,
"province": self.province,
# Coordinates.
"coordinates": self.coordinates.serialize(),
# Last updated.
"last_updated": self.last_updated,
# Latest data (statistics).
"latest": {
"confirmed": self.confirmed,
"deaths": self.deaths,
"recovered": self.recovered,
},
}

def __copy__(self):
"""
Create a shallow copy. This method will be called whenever someone calls
`copy.copy` with this object and the returned value is returned as the
new shallow copy.
"""

# First, let's create copies of the nested objects.
id = copy.deepcopy(self.id)
country = copy.copy(self.country)
province = copy.copy(self.province)
coordinates = copy.copy(self.coordinates)
last_updated = copy.copy(self.last_updated)
confirmed = copy.copy(self.confirmed)
deaths = copy.copy(self.deaths)
recovered = copy.copy(self.recovered)
timelines = copy.copy(self.timelines)

# Then, let's clone the object itself, using the prepared clones of the
# nested objects.
new = self.__class__(
id, country, province, coordinates, last_updated, confirmed, deaths, recovered, timelines
)
new.__dict__.update(self.__dict__)

return new

def __deepcopy__(self, memo=None):
"""
Create a deep copy. This method will be called whenever someone calls
`copy.deepcopy` with this object and the returned value is returned as
the new deep copy.

What is the use of the argument `memo`? Memo is the dictionary that is
used by the `deepcopy` library to prevent infinite recursive copies in
instances of circular references. Pass it to all the `deepcopy` calls
you make in the `__deepcopy__` implementation to prevent infinite
recursions.
"""

# First, let's create copies of the nested objects.
if memo is None:
memo = {}
id = copy.deepcopy(self.id, memo)
country = copy.deepcopy(self.country, memo)
province = copy.deepcopy(self.province, memo)
coordinates = copy.deepcopy(self.coordinates, memo)
last_updated = copy.deepcopy(self.last_updated, memo)
confirmed = copy.deepcopy(self.confirmed, memo)
deaths = copy.deepcopy(self.deaths, memo)
recovered = copy.deepcopy(self.recovered, memo)
timelines = copy.deepcopy(self.timelines, memo)

# Then, let's clone the object itself, using the prepared clones of the
# nested objects.
new = self.__class__(
id, country, province, coordinates, last_updated, confirmed, deaths, recovered, timelines
)
new.__dict__ = copy.deepcopy(self.__dict__, memo)

return new


class Location: # pylint: disable=too-many-instance-attributes
"""
A location in the world affected by the coronavirus.
"""

def __init__(self):
super().__init__()

@property
def country_code(self):
"""
Expand Down Expand Up @@ -80,14 +253,8 @@ class TimelinedLocation(Location):
"""

# pylint: disable=too-many-arguments
def __init__(self, id, country, province, coordinates, last_updated, timelines):
def __init__(self, timelines):
super().__init__(
# General info.
id,
country,
province,
coordinates,
last_updated,
# Statistics (retrieve latest from timelines).
confirmed=timelines.get("confirmed").latest or 0,
deaths=timelines.get("deaths").latest or 0,
Expand Down