From 62e1b4239d56662cdab121c9e0887b1e2beac6f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Aug 2021 15:12:18 -0400 Subject: [PATCH 1/5] Apply factory method to data --- app/data/__init__.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/app/data/__init__.py b/app/data/__init__.py index 60a75dac..429178de 100644 --- a/app/data/__init__.py +++ b/app/data/__init__.py @@ -1,16 +1,33 @@ """app.data""" +from ..services.location import LocationService from ..services.location.csbs import CSBSLocationService from ..services.location.jhu import JhuLocationService from ..services.location.nyt import NYTLocationService -# Mapping of services to data-sources. +class dataSourceFactory(): + def getDataSource(): + return LocationService() + +class JhuFactory(dataSourceFactory): + def getDataSource(): + return JhuLocationService() + +class CSBSFactory(dataSourceFactory): + def getDataSource(): + return CSBSLocationService() + +class NYTFactory(dataSourceFactory): + def getDataSource(): + return NYTLcationService() + + +# Mapping of factories to data-sources. DATA_SOURCES = { - "jhu": JhuLocationService(), - "csbs": CSBSLocationService(), - "nyt": NYTLocationService(), + "jhu": JhuFactory(), + "csbs": CSBSFactory(), + "nyt": NYTFactory(), } - def data_source(source): """ Retrieves the provided data-source service. @@ -18,4 +35,4 @@ def data_source(source): :returns: The service. :rtype: LocationService """ - return DATA_SOURCES.get(source.lower()) + return DATA_SOURCES.get(source.lower()).getDataSource() From 8426e97c3642dc4c3ce9e8baf6922785a70a9265 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Aug 2021 15:17:30 -0400 Subject: [PATCH 2/5] Fix a typo --- app/data/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/data/__init__.py b/app/data/__init__.py index 429178de..4089417f 100644 --- a/app/data/__init__.py +++ b/app/data/__init__.py @@ -18,7 +18,7 @@ def getDataSource(): class NYTFactory(dataSourceFactory): def getDataSource(): - return NYTLcationService() + return NYTLocationService() # Mapping of factories to data-sources. From 96e5c9ffb73a625ffb773060de6cff700582278b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Aug 2021 17:12:45 -0400 Subject: [PATCH 3/5] Apply singleton pattern to data source --- app/data/__init__.py | 105 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 17 deletions(-) diff --git a/app/data/__init__.py b/app/data/__init__.py index 4089417f..42cab8f2 100644 --- a/app/data/__init__.py +++ b/app/data/__init__.py @@ -1,31 +1,102 @@ """app.data""" -from ..services.location import LocationService +from abc import ABC, abstractmethod from ..services.location.csbs import CSBSLocationService from ..services.location.jhu import JhuLocationService from ..services.location.nyt import NYTLocationService -class dataSourceFactory(): - def getDataSource(): - return LocationService() +class DataSourceFactory(ABC): + def __init__(self): + pass + + @abstractmethod + def getInstance(): + pass -class JhuFactory(dataSourceFactory): - def getDataSource(): - return JhuLocationService() + @abstractmethod + def getService(): + pass -class CSBSFactory(dataSourceFactory): - def getDataSource(): - return CSBSLocationService() +class JhuFactory(DataSourceFactory): + __instance = None + __service = None -class NYTFactory(dataSourceFactory): - def getDataSource(): - return NYTLocationService() + def __init__(self): + if JhuFactory.__instance != None: + raise Exception("Factory is singleton!") + elif JhuFactory.__service != None: + raise Exception("Service is singleton!") + else: + JhuFactory.__instance = self + JhuFactory.__service = JhuLocationService() + + @staticmethod + def getInstance(): + if JhuFactory.__instance == None: + JhuFactory() + return JhuFactory.__instance + + @staticmethod + def getService(): + if JhuFactory.__service == None: + JhuFactory() + return JhuFactory.__service + +class CSBSFactory(DataSourceFactory): + __instance = None + __service = None + + def __init__(self): + if CSBSFactory.__instance != None: + raise Exception("Factory is singleton!") + elif CSBSFactory.__service != None: + raise Exception("Service is singleton!") + else: + CSBSFactory.__instance = self + CSBSFactory.__service = CSBSLocationService() + + @staticmethod + def getInstance(): + if CSBSFactory.__instance == None: + CSBSFactory() + return CSBSFactory.__instance + + @staticmethod + def getService(): + if CSBSFactory.__service == None: + CSBSFactory() + return CSBSFactory.__service + +class NYTFactory(DataSourceFactory): + __instance = None + __service = None + + def __init__(self): + if NYTFactory.__instance != None: + raise Exception("Factory is singleton!") + elif NYTFactory.__service != None: + raise Exception("Service is singleton!") + else: + NYTFactory.__instance = self + NYTFactory.__service = NYTLocationService() + + @staticmethod + def getInstance(): + if NYTFactory.__instance == None: + NYTFactory() + return NYTFactory.__instance + + @staticmethod + def getService(): + if NYTFactory.__service == None: + NYTFactory() + return NYTFactory.__service # Mapping of factories to data-sources. DATA_SOURCES = { - "jhu": JhuFactory(), - "csbs": CSBSFactory(), - "nyt": NYTFactory(), + "jhu": JhuFactory.getInstance(), + "csbs": CSBSFactory.getInstance(), + "nyt": NYTFactory.getInstance(), } def data_source(source): @@ -35,4 +106,4 @@ def data_source(source): :returns: The service. :rtype: LocationService """ - return DATA_SOURCES.get(source.lower()).getDataSource() + return DATA_SOURCES.get(source.lower()).getService() From 3278a3b5b832dbd5cb7b08b641e4fce0dd3cac2f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Aug 2021 20:38:58 -0400 Subject: [PATCH 4/5] Apply decorators to location --- app/location/__init__.py | 46 +++++++++++++++++++++++++++------------- app/location/csbs.py | 9 +++----- app/location/nyt.py | 11 +++------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/app/location/__init__.py b/app/location/__init__.py index 1da5e9e5..2d1b9102 100644 --- a/app/location/__init__.py +++ b/app/location/__init__.py @@ -74,6 +74,32 @@ def serialize(self): } +def decoratedSerialize(func, inc_timelines, *args, **kwargs): + serialized = func() + if kwargs.get("timelines") and inc_timelines: + # Whether to include the timelines or not. + timelines = kwargs["timelines"] + if timelines: + serialized.update( + { + "timelines": { + # Serialize all the timelines. + key: value.serialize() + for (key, value) in self.timelines.items() + } + } + ) + + if kwargs.get("state"): + state = kwargs["state"] + serialized.update({"state": state}) + + if kwargs.get("county"): + county = kwargs["county"] + serialized.update({"county": county}) + + return serialized + class TimelinedLocation(Location): """ A location with timelines. @@ -96,29 +122,19 @@ def __init__(self, id, country, province, coordinates, last_updated, timelines): # Set timelines. self.timelines = timelines + self.inc_timelines = false # pylint: disable=arguments-differ - def serialize(self, timelines=False): + @decoratedSerialize(timelines=self.timelines, inc_timelines=self.inc_timelines) + def serialize(self, inc_timelines=false): """ Serializes the location into a dict. - - :param timelines: Whether to include the timelines. + :param inc_timelines: Whether to include the timelines. :returns: The serialized location. :rtype: dict """ serialized = super().serialize() - - # Whether to include the timelines or not. - if timelines: - serialized.update( - { - "timelines": { - # Serialize all the timelines. - key: value.serialize() - for (key, value) in self.timelines.items() - } - } - ) + self.inc_timelines = inc_timelines # Return the serialized location. return serialized diff --git a/app/location/csbs.py b/app/location/csbs.py index 649e8b22..644776e0 100644 --- a/app/location/csbs.py +++ b/app/location/csbs.py @@ -25,19 +25,16 @@ def __init__(self, id, state, county, coordinates, last_updated, confirmed, deat self.state = state self.county = county - def serialize(self, timelines=False): # pylint: disable=arguments-differ,unused-argument + @decoratedSerialize(state=self.state, county=self.county) + def serialize(self): # pylint: disable=arguments-differ,unused-argument """ Serializes the location into a dict. + :returns: The serialized location. :rtype: dict """ serialized = super().serialize() - # Update with new fields. - serialized.update( - {"state": self.state, "county": self.county,} - ) - # Return the serialized location. return serialized diff --git a/app/location/nyt.py b/app/location/nyt.py index ad92212e..83a9a13f 100644 --- a/app/location/nyt.py +++ b/app/location/nyt.py @@ -14,19 +14,14 @@ def __init__(self, id, state, county, coordinates, last_updated, timelines): self.state = state self.county = county - def serialize(self, timelines=False): # pylint: disable=arguments-differ,unused-argument + @decoratedSerialize(timelines=self.timelines, state=self.state, county=self.county) + def serialize(self, inc_timelines=False): # pylint: disable=arguments-differ,unused-argument """ Serializes the location into a dict. - :returns: The serialized location. :rtype: dict """ - serialized = super().serialize(timelines) - - # Update with new fields. - serialized.update( - {"state": self.state, "county": self.county,} - ) + serialized = super().serialize(inc_timelines) # Return the serialized location. return serialized From b9c700d86528fd11e81bea28d331b3c14a28b0f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Aug 2021 20:48:42 -0400 Subject: [PATCH 5/5] fix a bug --- app/location/csbs.py | 3 ++- app/location/nyt.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/location/csbs.py b/app/location/csbs.py index 644776e0..62d11b9e 100644 --- a/app/location/csbs.py +++ b/app/location/csbs.py @@ -1,5 +1,6 @@ """app.locations.csbs.py""" from . import Location +from . import decoratedSerialize class CSBSLocation(Location): @@ -29,7 +30,7 @@ def __init__(self, id, state, county, coordinates, last_updated, confirmed, deat def serialize(self): # pylint: disable=arguments-differ,unused-argument """ Serializes the location into a dict. - + :returns: The serialized location. :rtype: dict diff --git a/app/location/nyt.py b/app/location/nyt.py index 83a9a13f..884348d5 100644 --- a/app/location/nyt.py +++ b/app/location/nyt.py @@ -1,5 +1,6 @@ """app.locations.nyt.py""" from . import TimelinedLocation +from . import decoratedSerialize class NYTLocation(TimelinedLocation):