From 0b57e027f759d6556ae158271756801957182a19 Mon Sep 17 00:00:00 2001 From: Adarnof Date: Thu, 19 Jan 2017 19:19:20 -0500 Subject: [PATCH] Variable itemtype name datasources (#662) Make provider settings optional Wait to initialize adapter until first external call Abstract get methods from adapter --- alliance_auth/settings.py.example | 10 +-- docs/installation/auth/settings.md | 2 + eveonline/managers.py | 45 ++++++++---- eveonline/providers.py | 110 ++++++++++++++++++++++------- eveonline/tasks.py | 1 - fleetactivitytracking/views.py | 6 +- srp/views.py | 11 +-- 7 files changed, 127 insertions(+), 58 deletions(-) diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 2f2a1ba7..f753be20 100644 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -359,12 +359,14 @@ API_SSO_VALIDATION = 'True' == os.environ.get('AA_API_SSO_VALIDATION', 'False') # EVEONLINE_CHARACTER_PROVIDER - Name of default data source for getting eve character data # EVEONLINE_CORP_PROVIDER - Name of default data source for getting eve corporation data # EVEONLINE_ALLIANCE_PROVIDER - Name of default data source for getting eve alliance data +# EVEONLINE_ITEMTYPE_PROVIDER - Name of default data source for getting eve item type data # -# Available sources are 'esi' and 'xml' +# Available sources are 'esi' and 'xml'. Leaving blank results in the default 'esi' being used. ####################### -EVEONLINE_CHARACTER_PROVIDER = os.environ.get('AA_EVEONLINE_CHARACTER_PROVIDER', 'esi') -EVEONLINE_CORP_PROVIDER = os.environ.get('AA_EVEONLINE_CORP_PROVIDER', 'esi') -EVEONLINE_ALLIANCE_PROVIDER = os.environ.get('AA_EVEONLINE_ALLIANCE_PROVIDER', 'esi') +EVEONLINE_CHARACTER_PROVIDER = os.environ.get('AA_EVEONLINE_CHARACTER_PROVIDER', '') +EVEONLINE_CORP_PROVIDER = os.environ.get('AA_EVEONLINE_CORP_PROVIDER', '') +EVEONLINE_ALLIANCE_PROVIDER = os.environ.get('AA_EVEONLINE_ALLIANCE_PROVIDER', '') +EVEONLINE_ITEMTYPE_PROVIDER = os.environ.get('AA_EVEONLINE_ITEMTYPE_PROVIDER', '') ##################### # Alliance Market diff --git a/docs/installation/auth/settings.md b/docs/installation/auth/settings.md index bfdaa216..c5c76145 100644 --- a/docs/installation/auth/settings.md +++ b/docs/installation/auth/settings.md @@ -310,6 +310,8 @@ The default data source to get character information. Default is `esi` The default data source to get corporation information. Default is `esi` ### EVEONLINE_ALLIANCE_PROVIDER The default data source to get alliance information. Default is `esi` +### EVEONLINE_ITEMTYPE_PROVIDER +The default data source to get item type information. Default is `esi` ## Alliance Market ### MARKET_URL The web address to access the Evernus Alliance Market application. diff --git a/eveonline/managers.py b/eveonline/managers.py index ebcf8dab..013fecca 100644 --- a/eveonline/managers.py +++ b/eveonline/managers.py @@ -9,15 +9,23 @@ import logging logger = logging.getLogger(__name__) -adapter = eve_adapter_factory() -class EveManager: - def __init__(self): - pass +class EveManager(object): + adapter = None + + @classmethod + def get_adapter(cls): + if not cls.adapter: + cls.adapter = eve_adapter_factory() + return cls.adapter + + @classmethod + def get_character(cls, character_id): + return cls.get_adapter().get_character(character_id) @staticmethod def create_character(id, user, api_id): - return EveManager.create_character_obj(adapter.get_character(id), user, api_id) + return EveManager.create_character_obj(EveManager.get_character(id), user, api_id) @staticmethod def create_character_obj(character, user, api_id): @@ -35,7 +43,7 @@ class EveManager: @staticmethod def update_character(id): - return EveManager.update_character_obj(adapter.get_character(id)) + return EveManager.update_character_obj(EveManager.get_character(id)) @staticmethod def update_character_obj(char): @@ -61,9 +69,13 @@ class EveManager: else: logger.warn("Attempting to create existing api keypair with id %s" % api_id) + @classmethod + def get_alliance(cls, alliance_id): + return cls.get_adapter().get_alliance(alliance_id) + @staticmethod def create_alliance(id, is_blue=False): - return EveManager.create_alliance_obj(adapter.get_alliance(id), is_blue=is_blue) + return EveManager.create_alliance_obj(EveManager.get_alliance(id), is_blue=is_blue) @staticmethod def create_alliance_obj(alliance, is_blue=False): @@ -77,7 +89,7 @@ class EveManager: @staticmethod def update_alliance(id, is_blue=None): - return EveManager.update_alliance_obj(adapter.get_alliance(id), is_blue=is_blue) + return EveManager.update_alliance_obj(EveManager.get_alliance(id), is_blue=is_blue) @staticmethod def update_alliance_obj(alliance, is_blue=None): @@ -89,17 +101,20 @@ class EveManager: @staticmethod def populate_alliance(id): alliance_model = EveAllianceInfo.objects.get(alliance_id=id) - alliance = adapter.get_alliance(id) + alliance = EveManager.get_alliance(id) for corp_id in alliance.corp_ids: if not EveCorporationInfo.objects.filter(corporation_id=corp_id).exists(): EveManager.create_corporation(corp_id, is_blue=alliance_model.is_blue) EveCorporationInfo.objects.filter(corporation_id__in=alliance.corp_ids).update(alliance=alliance_model) EveCorporationInfo.objects.filter(alliance=alliance_model).exclude(corporation_id__in=alliance.corp_ids).update(alliance=None) - + + @classmethod + def get_corporation(cls, corp_id): + return cls.get_adapter().get_corp(corp_id) @staticmethod def create_corporation(id, is_blue=False): - return EveManager.create_corporation_obj(adapter.get_corp(id), is_blue=is_blue) + return EveManager.create_corporation_obj(EveManager.get_corporation(id), is_blue=is_blue) @staticmethod def create_corporation_obj(corp, is_blue=False): @@ -118,7 +133,7 @@ class EveManager: @staticmethod def update_corporation(id, is_blue=None): - return EveManager.update_corporation_obj(adapter.get_corp(id), is_blue=is_blue) + return EveManager.update_corporation_obj(EveManager.get_corporation(id), is_blue=is_blue) @staticmethod def update_corporation_obj(corp, is_blue=None): @@ -131,10 +146,14 @@ class EveManager: model.is_blue = model.is_blue if is_blue == None else is_blue model.save() + @classmethod + def get_itemtype(cls, type_id): + return cls.get_adapter().get_itemtype(type_id) + @staticmethod def get_characters_from_api(api): char_result = EveApiManager.get_characters_from_api(api.api_id, api.api_key).result - provider = EveXmlProvider(adapter=adapter) + provider = EveXmlProvider(adapter=EveManager.get_adapter()) return [provider._build_character(result) for id, result in char_result.items()] @staticmethod diff --git a/eveonline/providers.py b/eveonline/providers.py index 258eb766..d717faed 100644 --- a/eveonline/providers.py +++ b/eveonline/providers.py @@ -15,9 +15,9 @@ OBJ_CACHE_DURATION = int(getattr(settings, 'EVEONLINE_OBJ_CACHE_DURATION', 300)) @python_2_unicode_compatible class ObjectNotFound(Exception): - def __init__(self, id, type): - self.id = id - self.type = type + def __init__(self, obj_id, type_name): + self.id = obj_id + self.type = type_name def __str__(self): return '%s with ID %s not found.' % (self.type, self.id) @@ -48,8 +48,8 @@ class Entity(object): } @classmethod - def from_dict(cls, dict): - return cls(dict['id'], dict['name']) + def from_dict(cls, data_dict): + return cls(data_dict['id'], data_dict['name']) class Corporation(Entity): @@ -185,6 +185,20 @@ class Character(Entity): ) +class ItemType(Entity): + def __init__(self, provider, type_id, name): + super(ItemType, self).__init__(type_id, name) + self.provider = provider + + @classmethod + def from_dict(cls, data_dict): + return cls( + None, + data_dict['id'], + data_dict['name'], + ) + + class EveProvider(object): def get_alliance(self, alliance_id): """ @@ -198,12 +212,18 @@ class EveProvider(object): """ raise NotImplementedError() - def get_character(self, corp_id): + def get_character(self, character_id): """ :return: a Character object for the given ID """ raise NotImplementedError() + def get_itemtype(self, type_id): + """ + :return: an ItemType object for the given ID + """ + raise NotImplemented() + @python_2_unicode_compatible class EveSwaggerProvider(EveProvider): @@ -214,13 +234,13 @@ class EveSwaggerProvider(EveProvider): def __str__(self): return 'esi' - def get_alliance(self, id): + def get_alliance(self, alliance_id): try: - data = self.client.Alliance.get_alliances_alliance_id(alliance_id=id).result() - corps = self.client.Alliance.get_alliances_alliance_id_corporations(alliance_id=id).result() + data = self.client.Alliance.get_alliances_alliance_id(alliance_id=alliance_id).result() + corps = self.client.Alliance.get_alliances_alliance_id_corporations(alliance_id=alliance_id).result() model = Alliance( self.adapter, - id, + alliance_id, data['alliance_name'], data['ticker'], corps, @@ -228,14 +248,14 @@ class EveSwaggerProvider(EveProvider): ) return model except HTTPNotFound: - raise ObjectNotFound(id, 'alliance') + raise ObjectNotFound(alliance_id, 'alliance') - def get_corp(self, id): + def get_corp(self, corp_id): try: - data = self.client.Corporation.get_corporations_corporation_id(corporation_id=id).result() + data = self.client.Corporation.get_corporations_corporation_id(corporation_id=corp_id).result() model = Corporation( self.adapter, - id, + corp_id, data['corporation_name'], data['ticker'], data['ceo_id'], @@ -246,20 +266,27 @@ class EveSwaggerProvider(EveProvider): except HTTPNotFound: raise ObjectNotFound(id, 'corporation') - def get_character(self, id): + def get_character(self, character_id): try: - data = self.client.Character.get_characters_character_id(character_id=id).result() + data = self.client.Character.get_characters_character_id(character_id=character_id).result() alliance_id = self.adapter.get_corp(data['corporation_id']).alliance_id model = Character( self.adapter, - id, + character_id, data['name'], data['corporation_id'], alliance_id, ) return model except (HTTPNotFound, HTTPUnprocessableEntity): - raise ObjectNotFound(id, 'character') + raise ObjectNotFound(character_id, 'character') + + def get_itemtype(self, type_id): + try: + data = self.client.Universe.get_universe_types_type_id(type_id=type_id).result() + return ItemType(self.adapter, type_id, data['name']) + except (HTTPNotFound, HTTPUnprocessableEntity): + raise ObjectNotFound(type_id, 'type') @python_2_unicode_compatible @@ -329,23 +356,37 @@ class EveXmlProvider(EveProvider): raise e return self._build_character(charinfo) + def get_itemtype(self, type_id): + api = evelink.eve.EVE(api=self.api) + try: + type_name = api.type_name_from_id(type_id).result + assert type_name != 'Unknown Type' + return ItemType(self.adapter, type_id, type_name) + except AssertionError: + raise ObjectNotFound(type_id, 'itemtype') + class EveAdapter(EveProvider): """ Redirects queries to appropriate data source. """ - def __init__(self, char_provider, corp_provider, alliance_provider): + def __init__(self, char_provider, corp_provider, alliance_provider, itemtype_provider): self.char_provider = char_provider self.corp_provider = corp_provider self.alliance_provider = alliance_provider + self.itemtype_provider = itemtype_provider self.char_provider.adapter = self self.corp_provider.adapter = self self.alliance_provider.adapter = self + self.itemtype_provider.adapter = self def __repr__(self): - return "<{} (char:{}, corp:{}, alliance:{})>".format(self.__class__.__name__, str(self.char_provider), - str(self.corp_provider), str(self.alliance_provider)) + return "<{} (character:{} corp:{} alliance:{} itemtype:{})>".format(self.__class__.__name__, + str(self.char_provider), + str(self.corp_provider), + str(self.alliance_provider), + str(self.itemtype_provider)) @staticmethod def _get_from_cache(obj_class, id): @@ -390,6 +431,15 @@ class EveAdapter(EveProvider): self._cache(obj) return obj + def get_itemtype(self, type_id): + obj = self._get_from_cache(ItemType, type_id) + if obj: + obj.provider = self + else: + obj = self._get_itemtype(type_id) + self._cache(obj) + return obj + def _get_character(self, id): return self.char_provider.get_character(id) @@ -399,11 +449,19 @@ class EveAdapter(EveProvider): def _get_alliance(self, id): return self.alliance_provider.get_alliance(id) + def _get_itemtype(self, type_id): + return self.itemtype_provider.get_itemtype(type_id) -def eve_adapter_factory(character_source=settings.EVEONLINE_CHARACTER_PROVIDER, - corp_source=settings.EVEONLINE_CORP_PROVIDER, - alliance_source=settings.EVEONLINE_ALLIANCE_PROVIDER, api_key=None, token=None): - sources = [character_source, corp_source, alliance_source] + +CHARACTER_PROVIDER = getattr(settings, 'EVEONLINE_CHARACTER_PROVIDER', 'esi') +CORP_PROVIDER = getattr(settings, 'EVEONLINE_CORP_PROVIDER', 'esi') +ALLIANCE_PROVIDER = getattr(settings, 'EVEONLINE_ALLIANCE_PROVIDER', 'esi') +ITEMTYPE_PROVIDER = getattr(settings, 'EVEONLINE_ITEMTYPE_PROVIDER', 'esi') + + +def eve_adapter_factory(character_source=CHARACTER_PROVIDER, corp_source=CORP_PROVIDER, + alliance_source=ALLIANCE_PROVIDER, itemtype_source=ITEMTYPE_PROVIDER, api_key=None, token=None): + sources = [character_source, corp_source, alliance_source, itemtype_source] providers = [] if 'xml' in sources: @@ -418,4 +476,4 @@ def eve_adapter_factory(character_source=settings.EVEONLINE_CHARACTER_PROVIDER, providers.append(esi) else: raise ValueError('Unrecognized data source "%s"' % source) - return EveAdapter(providers[0], providers[1], providers[2]) + return EveAdapter(providers[0], providers[1], providers[2], providers[3]) diff --git a/eveonline/tasks.py b/eveonline/tasks.py index 109d1ffb..d050cc8c 100644 --- a/eveonline/tasks.py +++ b/eveonline/tasks.py @@ -12,7 +12,6 @@ from services.managers.eve_api_manager import EveApiManager from eveonline.models import EveCharacter from eveonline.models import EveCorporationInfo from eveonline.models import EveAllianceInfo -from eveonline.providers import eve_adapter_factory from authentication.tasks import set_state import logging import evelink diff --git a/fleetactivitytracking/views.py b/fleetactivitytracking/views.py index 4b36b564..9fd3df75 100644 --- a/fleetactivitytracking/views.py +++ b/fleetactivitytracking/views.py @@ -13,7 +13,6 @@ from eveonline.models import EveCorporationInfo from eveonline.managers import EveManager from fleetactivitytracking.forms import FatlinkForm from fleetactivitytracking.models import Fatlink, Fat -from bravado.exception import HTTPError from esi.decorators import token_required @@ -222,8 +221,7 @@ def click_fatlink_view(request, token, hash, fatname): 'station_name'] else: location['station_name'] = "No Station" - ship['ship_type_name'] = c.Universe.get_universe_types_type_id(type_id=ship['ship_type_id']).result()[ - 'type_name'] + ship['ship_type_name'] = EveManager.get_itemtype(ship['ship_type_id']).name fat = Fat() fat.system = location['solar_system_name'] @@ -249,8 +247,6 @@ def click_fatlink_view(request, token, hash, fatname): messages.error(request, 'FAT link has expired.') except (ObjectDoesNotExist, KeyError): messages.error(request, 'Invalid FAT link.') - except HTTPError as e: - messages.error(request, str(e)) return redirect('auth_fatlink_view') diff --git a/srp/views.py b/srp/views.py index 2d286642..f327108b 100755 --- a/srp/views.py +++ b/srp/views.py @@ -15,8 +15,6 @@ from services.managers.srp_manager import srpManager from notifications import notify from django.utils import timezone from authentication.decorators import members_and_blues -from esi.clients import esi_client_factory -from bravado.exception import HTTPError import uuid import logging @@ -220,7 +218,7 @@ def srp_request_view(request, fleet_srp): try: srp_kill_link = srpManager.get_kill_id(srp_request.killboard_link) - (srp_kill_data, ship_value) = srpManager.get_kill_data(srp_kill_link) + (ship_type_id, ship_value) = srpManager.get_kill_data(srp_kill_link) except ValueError: logger.debug("User %s Submitted Invalid Killmail Link %s or server could not be reached" % ( request.user, srp_request.killboard_link)) @@ -228,12 +226,7 @@ def srp_request_view(request, fleet_srp): messages.error(request, "Your SRP request Killmail link is invalid. Please make sure you are using zKillboard.") return redirect("auth_srp_management_view") - try: - c = esi_client_factory() - srp_ship_name = c.Universe.get_universe_types_type_id(type_id=srp_kill_data).result()['name'] - except HTTPError as e: - messages.error(request, str(e)) - return redirect('auth_dashboard') + srp_ship_name = EveManager.get_itemtype(ship_type_id).name srp_request.srp_ship_name = srp_ship_name kb_total_loss = ship_value srp_request.kb_total_loss = kb_total_loss