from datetime import datetime import pytz from core.data_store import DATA_STORE class CallsignDataProvider: """Generic callsign reference data provider class. Subclasses of this set up the various mechanisms via which Spothole can look up data for callsigns.""" def __init__(self, name, provider_config, storage): """Constructor. As well as name and config, provide the storage object from DATA_STORE that will be used to store the result of lookups to speed up future access.""" self.name = name self.enabled = provider_config["enabled"] self.last_update_time = datetime.min.replace(tzinfo=pytz.UTC) self.status = "Not Started" if self.enabled else "Disabled" self._storage = storage def start(self): """Start the provider. This should return immediately after spawning threads to access remote resources, if needed.""" raise NotImplementedError("Subclasses must implement this method") def stop(self): """Stop any threads and prepare for application shutdown""" raise NotImplementedError("Subclasses must implement this method") def lookup(self, callsign, lookup_credentials): """Looks up data for the provided callsign. Takes a LookupCredentials object, which provides any credentials that have been provided by the user for this session (QRZ.com/HamQTH) to allow us to look up using those services on the user's behalf. (Clublog is looked up using an API key owned by the server and provided in its config file, so users need not provide their own.) Returns a Callsign object with as much data populated as possible. Data is cached internally for a set period of 30 days to avoid the need to request data from servers each time.""" if callsign in self._storage: return self._storage[callsign] else: c = self._perform_new_lookup(callsign, lookup_credentials) if c: self._storage.set(callsign, c, expire=DATA_STORE.CALLSIGN_DATA_TTL_SEC) return c def _perform_new_lookup(self, callsign, lookup_credentials): """Makes a new request to the data source for callsign data.""" raise NotImplementedError("Subclasses must implement this method")