Variable itemtype name datasources (#662)

Make provider settings optional
Wait to initialize adapter until first external call
Abstract get methods from adapter
This commit is contained in:
Adarnof 2017-01-19 19:19:20 -05:00 committed by GitHub
parent 3d50f977d9
commit 0b57e027f7
7 changed files with 127 additions and 58 deletions

View File

@ -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_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_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_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_CHARACTER_PROVIDER = os.environ.get('AA_EVEONLINE_CHARACTER_PROVIDER', '')
EVEONLINE_CORP_PROVIDER = os.environ.get('AA_EVEONLINE_CORP_PROVIDER', 'esi') EVEONLINE_CORP_PROVIDER = os.environ.get('AA_EVEONLINE_CORP_PROVIDER', '')
EVEONLINE_ALLIANCE_PROVIDER = os.environ.get('AA_EVEONLINE_ALLIANCE_PROVIDER', 'esi') EVEONLINE_ALLIANCE_PROVIDER = os.environ.get('AA_EVEONLINE_ALLIANCE_PROVIDER', '')
EVEONLINE_ITEMTYPE_PROVIDER = os.environ.get('AA_EVEONLINE_ITEMTYPE_PROVIDER', '')
##################### #####################
# Alliance Market # Alliance Market

View File

@ -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` The default data source to get corporation information. Default is `esi`
### EVEONLINE_ALLIANCE_PROVIDER ### EVEONLINE_ALLIANCE_PROVIDER
The default data source to get alliance information. Default is `esi` 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 ## Alliance Market
### MARKET_URL ### MARKET_URL
The web address to access the Evernus Alliance Market application. The web address to access the Evernus Alliance Market application.

View File

@ -9,15 +9,23 @@ import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
adapter = eve_adapter_factory()
class EveManager: class EveManager(object):
def __init__(self): adapter = None
pass
@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 @staticmethod
def create_character(id, user, api_id): 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 @staticmethod
def create_character_obj(character, user, api_id): def create_character_obj(character, user, api_id):
@ -35,7 +43,7 @@ class EveManager:
@staticmethod @staticmethod
def update_character(id): def update_character(id):
return EveManager.update_character_obj(adapter.get_character(id)) return EveManager.update_character_obj(EveManager.get_character(id))
@staticmethod @staticmethod
def update_character_obj(char): def update_character_obj(char):
@ -61,9 +69,13 @@ class EveManager:
else: else:
logger.warn("Attempting to create existing api keypair with id %s" % api_id) 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 @staticmethod
def create_alliance(id, is_blue=False): 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 @staticmethod
def create_alliance_obj(alliance, is_blue=False): def create_alliance_obj(alliance, is_blue=False):
@ -77,7 +89,7 @@ class EveManager:
@staticmethod @staticmethod
def update_alliance(id, is_blue=None): 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 @staticmethod
def update_alliance_obj(alliance, is_blue=None): def update_alliance_obj(alliance, is_blue=None):
@ -89,17 +101,20 @@ class EveManager:
@staticmethod @staticmethod
def populate_alliance(id): def populate_alliance(id):
alliance_model = EveAllianceInfo.objects.get(alliance_id=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: for corp_id in alliance.corp_ids:
if not EveCorporationInfo.objects.filter(corporation_id=corp_id).exists(): if not EveCorporationInfo.objects.filter(corporation_id=corp_id).exists():
EveManager.create_corporation(corp_id, is_blue=alliance_model.is_blue) 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(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) 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 @staticmethod
def create_corporation(id, is_blue=False): 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 @staticmethod
def create_corporation_obj(corp, is_blue=False): def create_corporation_obj(corp, is_blue=False):
@ -118,7 +133,7 @@ class EveManager:
@staticmethod @staticmethod
def update_corporation(id, is_blue=None): 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 @staticmethod
def update_corporation_obj(corp, is_blue=None): 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.is_blue = model.is_blue if is_blue == None else is_blue
model.save() model.save()
@classmethod
def get_itemtype(cls, type_id):
return cls.get_adapter().get_itemtype(type_id)
@staticmethod @staticmethod
def get_characters_from_api(api): def get_characters_from_api(api):
char_result = EveApiManager.get_characters_from_api(api.api_id, api.api_key).result 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()] return [provider._build_character(result) for id, result in char_result.items()]
@staticmethod @staticmethod

View File

@ -15,9 +15,9 @@ OBJ_CACHE_DURATION = int(getattr(settings, 'EVEONLINE_OBJ_CACHE_DURATION', 300))
@python_2_unicode_compatible @python_2_unicode_compatible
class ObjectNotFound(Exception): class ObjectNotFound(Exception):
def __init__(self, id, type): def __init__(self, obj_id, type_name):
self.id = id self.id = obj_id
self.type = type self.type = type_name
def __str__(self): def __str__(self):
return '%s with ID %s not found.' % (self.type, self.id) return '%s with ID %s not found.' % (self.type, self.id)
@ -48,8 +48,8 @@ class Entity(object):
} }
@classmethod @classmethod
def from_dict(cls, dict): def from_dict(cls, data_dict):
return cls(dict['id'], dict['name']) return cls(data_dict['id'], data_dict['name'])
class Corporation(Entity): 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): class EveProvider(object):
def get_alliance(self, alliance_id): def get_alliance(self, alliance_id):
""" """
@ -198,12 +212,18 @@ class EveProvider(object):
""" """
raise NotImplementedError() raise NotImplementedError()
def get_character(self, corp_id): def get_character(self, character_id):
""" """
:return: a Character object for the given ID :return: a Character object for the given ID
""" """
raise NotImplementedError() raise NotImplementedError()
def get_itemtype(self, type_id):
"""
:return: an ItemType object for the given ID
"""
raise NotImplemented()
@python_2_unicode_compatible @python_2_unicode_compatible
class EveSwaggerProvider(EveProvider): class EveSwaggerProvider(EveProvider):
@ -214,13 +234,13 @@ class EveSwaggerProvider(EveProvider):
def __str__(self): def __str__(self):
return 'esi' return 'esi'
def get_alliance(self, id): def get_alliance(self, alliance_id):
try: try:
data = self.client.Alliance.get_alliances_alliance_id(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=id).result() corps = self.client.Alliance.get_alliances_alliance_id_corporations(alliance_id=alliance_id).result()
model = Alliance( model = Alliance(
self.adapter, self.adapter,
id, alliance_id,
data['alliance_name'], data['alliance_name'],
data['ticker'], data['ticker'],
corps, corps,
@ -228,14 +248,14 @@ class EveSwaggerProvider(EveProvider):
) )
return model return model
except HTTPNotFound: except HTTPNotFound:
raise ObjectNotFound(id, 'alliance') raise ObjectNotFound(alliance_id, 'alliance')
def get_corp(self, id): def get_corp(self, corp_id):
try: 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( model = Corporation(
self.adapter, self.adapter,
id, corp_id,
data['corporation_name'], data['corporation_name'],
data['ticker'], data['ticker'],
data['ceo_id'], data['ceo_id'],
@ -246,20 +266,27 @@ class EveSwaggerProvider(EveProvider):
except HTTPNotFound: except HTTPNotFound:
raise ObjectNotFound(id, 'corporation') raise ObjectNotFound(id, 'corporation')
def get_character(self, id): def get_character(self, character_id):
try: 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 alliance_id = self.adapter.get_corp(data['corporation_id']).alliance_id
model = Character( model = Character(
self.adapter, self.adapter,
id, character_id,
data['name'], data['name'],
data['corporation_id'], data['corporation_id'],
alliance_id, alliance_id,
) )
return model return model
except (HTTPNotFound, HTTPUnprocessableEntity): 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 @python_2_unicode_compatible
@ -329,23 +356,37 @@ class EveXmlProvider(EveProvider):
raise e raise e
return self._build_character(charinfo) 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): class EveAdapter(EveProvider):
""" """
Redirects queries to appropriate data source. 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.char_provider = char_provider
self.corp_provider = corp_provider self.corp_provider = corp_provider
self.alliance_provider = alliance_provider self.alliance_provider = alliance_provider
self.itemtype_provider = itemtype_provider
self.char_provider.adapter = self self.char_provider.adapter = self
self.corp_provider.adapter = self self.corp_provider.adapter = self
self.alliance_provider.adapter = self self.alliance_provider.adapter = self
self.itemtype_provider.adapter = self
def __repr__(self): def __repr__(self):
return "<{} (char:{}, corp:{}, alliance:{})>".format(self.__class__.__name__, str(self.char_provider), return "<{} (character:{} corp:{} alliance:{} itemtype:{})>".format(self.__class__.__name__,
str(self.corp_provider), str(self.alliance_provider)) str(self.char_provider),
str(self.corp_provider),
str(self.alliance_provider),
str(self.itemtype_provider))
@staticmethod @staticmethod
def _get_from_cache(obj_class, id): def _get_from_cache(obj_class, id):
@ -390,6 +431,15 @@ class EveAdapter(EveProvider):
self._cache(obj) self._cache(obj)
return 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): def _get_character(self, id):
return self.char_provider.get_character(id) return self.char_provider.get_character(id)
@ -399,11 +449,19 @@ class EveAdapter(EveProvider):
def _get_alliance(self, id): def _get_alliance(self, id):
return self.alliance_provider.get_alliance(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, CHARACTER_PROVIDER = getattr(settings, 'EVEONLINE_CHARACTER_PROVIDER', 'esi')
alliance_source=settings.EVEONLINE_ALLIANCE_PROVIDER, api_key=None, token=None): CORP_PROVIDER = getattr(settings, 'EVEONLINE_CORP_PROVIDER', 'esi')
sources = [character_source, corp_source, alliance_source] 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 = [] providers = []
if 'xml' in sources: if 'xml' in sources:
@ -418,4 +476,4 @@ def eve_adapter_factory(character_source=settings.EVEONLINE_CHARACTER_PROVIDER,
providers.append(esi) providers.append(esi)
else: else:
raise ValueError('Unrecognized data source "%s"' % source) 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])

View File

@ -12,7 +12,6 @@ from services.managers.eve_api_manager import EveApiManager
from eveonline.models import EveCharacter from eveonline.models import EveCharacter
from eveonline.models import EveCorporationInfo from eveonline.models import EveCorporationInfo
from eveonline.models import EveAllianceInfo from eveonline.models import EveAllianceInfo
from eveonline.providers import eve_adapter_factory
from authentication.tasks import set_state from authentication.tasks import set_state
import logging import logging
import evelink import evelink

View File

@ -13,7 +13,6 @@ from eveonline.models import EveCorporationInfo
from eveonline.managers import EveManager from eveonline.managers import EveManager
from fleetactivitytracking.forms import FatlinkForm from fleetactivitytracking.forms import FatlinkForm
from fleetactivitytracking.models import Fatlink, Fat from fleetactivitytracking.models import Fatlink, Fat
from bravado.exception import HTTPError
from esi.decorators import token_required from esi.decorators import token_required
@ -222,8 +221,7 @@ def click_fatlink_view(request, token, hash, fatname):
'station_name'] 'station_name']
else: else:
location['station_name'] = "No Station" location['station_name'] = "No Station"
ship['ship_type_name'] = c.Universe.get_universe_types_type_id(type_id=ship['ship_type_id']).result()[ ship['ship_type_name'] = EveManager.get_itemtype(ship['ship_type_id']).name
'type_name']
fat = Fat() fat = Fat()
fat.system = location['solar_system_name'] 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.') messages.error(request, 'FAT link has expired.')
except (ObjectDoesNotExist, KeyError): except (ObjectDoesNotExist, KeyError):
messages.error(request, 'Invalid FAT link.') messages.error(request, 'Invalid FAT link.')
except HTTPError as e:
messages.error(request, str(e))
return redirect('auth_fatlink_view') return redirect('auth_fatlink_view')

View File

@ -15,8 +15,6 @@ from services.managers.srp_manager import srpManager
from notifications import notify from notifications import notify
from django.utils import timezone from django.utils import timezone
from authentication.decorators import members_and_blues from authentication.decorators import members_and_blues
from esi.clients import esi_client_factory
from bravado.exception import HTTPError
import uuid import uuid
import logging import logging
@ -220,7 +218,7 @@ def srp_request_view(request, fleet_srp):
try: try:
srp_kill_link = srpManager.get_kill_id(srp_request.killboard_link) 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: except ValueError:
logger.debug("User %s Submitted Invalid Killmail Link %s or server could not be reached" % ( logger.debug("User %s Submitted Invalid Killmail Link %s or server could not be reached" % (
request.user, srp_request.killboard_link)) request.user, srp_request.killboard_link))
@ -228,12 +226,7 @@ def srp_request_view(request, fleet_srp):
messages.error(request, messages.error(request,
"Your SRP request Killmail link is invalid. Please make sure you are using zKillboard.") "Your SRP request Killmail link is invalid. Please make sure you are using zKillboard.")
return redirect("auth_srp_management_view") return redirect("auth_srp_management_view")
try: srp_ship_name = EveManager.get_itemtype(ship_type_id).name
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_request.srp_ship_name = srp_ship_name srp_request.srp_ship_name = srp_ship_name
kb_total_loss = ship_value kb_total_loss = ship_value
srp_request.kb_total_loss = kb_total_loss srp_request.kb_total_loss = kb_total_loss