Remove XML provider.

Remove caching provider - ESI calls are cached according to expiry headers now.
Remove evelink as a requirement.
Initialize API response objects using kwargs.

I won't miss XML.
This commit is contained in:
Adarnof 2017-09-19 20:55:26 -04:00
parent 954f36dae6
commit 1a8d163d45
4 changed files with 38 additions and 328 deletions

View File

@ -1,6 +1,6 @@
import logging import logging
from .providers import eve_adapter_factory from .providers import provider
from .models import EveAllianceInfo from .models import EveAllianceInfo
from .models import EveCharacter from .models import EveCharacter
@ -10,17 +10,9 @@ logger = logging.getLogger(__name__)
class EveManager(object): class EveManager(object):
adapter = None
@classmethod
def get_adapter(cls):
if not cls.adapter:
cls.adapter = eve_adapter_factory()
return cls.adapter
@classmethod @classmethod
def get_character(cls, character_id): def get_character(cls, character_id):
return cls.get_adapter().get_character(character_id) return provider.get_character(character_id)
@staticmethod @staticmethod
def create_character(id): def create_character(id):
@ -56,7 +48,7 @@ class EveManager(object):
@classmethod @classmethod
def get_alliance(cls, alliance_id): def get_alliance(cls, alliance_id):
return cls.get_adapter().get_alliance(alliance_id) return provider.get_alliance(alliance_id)
@staticmethod @staticmethod
def create_alliance(id): def create_alliance(id):
@ -95,7 +87,7 @@ class EveManager(object):
@classmethod @classmethod
def get_corporation(cls, corp_id): def get_corporation(cls, corp_id):
return cls.get_adapter().get_corp(corp_id) return provider.get_corp(corp_id)
@staticmethod @staticmethod
def create_corporation(id): def create_corporation(id):
@ -132,7 +124,7 @@ class EveManager(object):
@classmethod @classmethod
def get_itemtype(cls, type_id): def get_itemtype(cls, type_id):
return cls.get_adapter().get_itemtype(type_id) return provider.get_itemtype(type_id)
@staticmethod @staticmethod
def check_if_character_exist(char_name): def check_if_character_exist(char_name):

View File

@ -1,9 +1,5 @@
from esi.clients import esi_client_factory from esi.clients import esi_client_factory
from django.conf import settings
from django.core.cache import cache
import json
from bravado.exception import HTTPNotFound, HTTPUnprocessableEntity from bravado.exception import HTTPNotFound, HTTPUnprocessableEntity
import evelink
import logging import logging
import os import os
@ -11,9 +7,6 @@ SWAGGER_SPEC_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'sw
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# optional setting to control cached object lifespan
OBJ_CACHE_DURATION = int(getattr(settings, 'EVEONLINE_OBJ_CACHE_DURATION', 300))
class ObjectNotFound(Exception): class ObjectNotFound(Exception):
def __init__(self, obj_id, type_name): def __init__(self, obj_id, type_name):
@ -25,7 +18,7 @@ class ObjectNotFound(Exception):
class Entity(object): class Entity(object):
def __init__(self, id, name): def __init__(self, id=None, name=None):
self.id = id self.id = id
self.name = name self.name = name
@ -41,21 +34,10 @@ class Entity(object):
def __eq__(self, other): def __eq__(self, other):
return self.id == other.id return self.id == other.id
def serialize(self):
return {
'id': self.id,
'name': self.name,
}
@classmethod
def from_dict(cls, data_dict):
return cls(data_dict['id'], data_dict['name'])
class Corporation(Entity): class Corporation(Entity):
def __init__(self, provider, id, name, ticker, ceo_id, members, alliance_id): def __init__(self, ticker=None, ceo_id=None, members=None, alliance_id=None, **kwargs):
super(Corporation, self).__init__(id, name) super(Corporation, self).__init__(**kwargs)
self.provider = provider
self.ticker = ticker self.ticker = ticker
self.ceo_id = ceo_id self.ceo_id = ceo_id
self.members = members self.members = members
@ -67,43 +49,20 @@ class Corporation(Entity):
def alliance(self): def alliance(self):
if self.alliance_id: if self.alliance_id:
if not self._alliance: if not self._alliance:
self._alliance = self.provider.get_alliance(self.alliance_id) self._alliance = provider.get_alliance(self.alliance_id)
return self._alliance return self._alliance
return Entity(None, None) return Entity(None, None)
@property @property
def ceo(self): def ceo(self):
if not self._ceo: if not self._ceo:
self._ceo = self.provider.get_character(self.ceo_id) self._ceo = provider.get_character(self.ceo_id)
return self._ceo return self._ceo
def serialize(self):
return {
'id': self.id,
'name': self.name,
'ticker': self.ticker,
'ceo_id': self.ceo_id,
'members': self.members,
'alliance_id': self.alliance_id
}
@classmethod
def from_dict(cls, dict):
return cls(
None,
dict['id'],
dict['name'],
dict['ticker'],
dict['ceo_id'],
dict['members'],
dict['alliance_id'],
)
class Alliance(Entity): class Alliance(Entity):
def __init__(self, provider, id, name, ticker, corp_ids, executor_corp_id): def __init__(self, ticker=None, corp_ids=None, executor_corp_id=None, **kwargs):
super(Alliance, self).__init__(id, name) super(Alliance, self).__init__(**kwargs)
self.provider = provider
self.ticker = ticker self.ticker = ticker
self.corp_ids = corp_ids self.corp_ids = corp_ids
self.executor_corp_id = executor_corp_id self.executor_corp_id = executor_corp_id
@ -112,43 +71,22 @@ class Alliance(Entity):
def corp(self, id): def corp(self, id):
assert id in self.corp_ids assert id in self.corp_ids
if id not in self._corps: if id not in self._corps:
self._corps[id] = self.provider.get_corp(id) self._corps[id] = provider.get_corp(id)
self._corps[id]._alliance = self self._corps[id]._alliance = self
return self._corps[id] return self._corps[id]
@property @property
def corps(self): def corps(self):
return sorted([self.corp(id) for id in self.corp_ids], key=lambda x: x.name) return sorted([self.corp(c_id) for c_id in self.corp_ids], key=lambda x: x.name)
@property @property
def executor_corp(self): def executor_corp(self):
return self.corp(self.executor_corp_id) return self.corp(self.executor_corp_id)
def serialize(self):
return {
'id': self.id,
'name': self.name,
'ticker': self.ticker,
'corp_ids': self.corp_ids,
'executor_corp_id': self.executor_corp_id,
}
@classmethod
def from_dict(cls, dict):
return cls(
None,
dict['id'],
dict['name'],
dict['ticker'],
dict['corp_ids'],
dict['executor_corp_id'],
)
class Character(Entity): class Character(Entity):
def __init__(self, provider, id, name, corp_id, alliance_id): def __init__(self, corp_id=None, alliance_id=None, **kwargs):
super(Character, self).__init__(id, name) super(Character, self).__init__(**kwargs)
self.provider = provider
self.corp_id = corp_id self.corp_id = corp_id
self.alliance_id = alliance_id self.alliance_id = alliance_id
self._corp = None self._corp = None
@ -157,7 +95,7 @@ class Character(Entity):
@property @property
def corp(self): def corp(self):
if not self._corp: if not self._corp:
self._corp = self.provider.get_corp(self.corp_id) self._corp = provider.get_corp(self.corp_id)
return self._corp return self._corp
@property @property
@ -166,37 +104,10 @@ class Character(Entity):
return self.corp.alliance return self.corp.alliance
return Entity(None, None) return Entity(None, None)
def serialize(self):
return {
'id': self.id,
'name': self.name,
'corp_id': self.corp_id,
'alliance_id': self.alliance_id,
}
@classmethod
def from_dict(cls, dict):
return cls(
None,
dict['id'],
dict['name'],
dict['corp_id'],
dict['alliance_id'],
)
class ItemType(Entity): class ItemType(Entity):
def __init__(self, provider, type_id, name): def __init__(self, **kwargs):
super(ItemType, self).__init__(type_id, name) super(ItemType, self).__init__(**kwargs)
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):
@ -238,12 +149,11 @@ class EveSwaggerProvider(EveProvider):
data = self.client.Alliance.get_alliances_alliance_id(alliance_id=alliance_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() corps = self.client.Alliance.get_alliances_alliance_id_corporations(alliance_id=alliance_id).result()
model = Alliance( model = Alliance(
self.adapter, id=alliance_id,
alliance_id, name=data['alliance_name'],
data['alliance_name'], ticker=data['ticker'],
data['ticker'], corp_ids=corps,
corps, executor_corp_id=data['executor_corp'],
data['executor_corp'],
) )
return model return model
except HTTPNotFound: except HTTPNotFound:
@ -253,13 +163,12 @@ class EveSwaggerProvider(EveProvider):
try: try:
data = self.client.Corporation.get_corporations_corporation_id(corporation_id=corp_id).result() data = self.client.Corporation.get_corporations_corporation_id(corporation_id=corp_id).result()
model = Corporation( model = Corporation(
self.adapter, id=corp_id,
corp_id, name=data['corporation_name'],
data['corporation_name'], ticker=data['ticker'],
data['ticker'], ceo_id=data['ceo_id'],
data['ceo_id'], members=data['member_count'],
data['member_count'], alliance_id=data['alliance_id'] if 'alliance_id' in data else None,
data['alliance_id'] if 'alliance_id' in data else None,
) )
return model return model
except HTTPNotFound: except HTTPNotFound:
@ -270,11 +179,10 @@ class EveSwaggerProvider(EveProvider):
data = self.client.Character.get_characters_character_id(character_id=character_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, id=character_id,
character_id, name=data['name'],
data['name'], corp_id=data['corporation_id'],
data['corporation_id'], alliance_id=alliance_id,
alliance_id,
) )
return model return model
except (HTTPNotFound, HTTPUnprocessableEntity): except (HTTPNotFound, HTTPUnprocessableEntity):
@ -283,195 +191,9 @@ class EveSwaggerProvider(EveProvider):
def get_itemtype(self, type_id): def get_itemtype(self, type_id):
try: try:
data = self.client.Universe.get_universe_types_type_id(type_id=type_id).result() data = self.client.Universe.get_universe_types_type_id(type_id=type_id).result()
return ItemType(self.adapter, type_id, data['name']) return ItemType(id=type_id, name=data['name'])
except (HTTPNotFound, HTTPUnprocessableEntity): except (HTTPNotFound, HTTPUnprocessableEntity):
raise ObjectNotFound(type_id, 'type') raise ObjectNotFound(type_id, 'type')
class EveXmlProvider(EveProvider): provider = EveSwaggerProvider()
def __init__(self, api_key=None, adapter=None):
"""
:param api_key: eveonline.EveApiKeyPair
"""
self.api = evelink.api.API(api_key=(api_key.api_id, api_key.api_key)) if api_key else evelink.api.API()
self.adapter = adapter or self
def __str__(self):
return 'xml'
def get_alliance(self, id):
api = evelink.eve.EVE(api=self.api)
alliances = api.alliances().result
try:
results = alliances[int(id)]
except KeyError:
raise ObjectNotFound(id, 'alliance')
model = Alliance(
self.adapter,
id,
results['name'],
results['ticker'],
results['member_corps'],
results['executor_id'],
)
return model
def get_corp(self, id):
api = evelink.corp.Corp(api=self.api)
try:
corpinfo = api.corporation_sheet(corp_id=int(id)).result
except evelink.api.APIError as e:
if int(e.code) == 523:
raise ObjectNotFound(id, 'corporation')
raise e
model = Corporation(
self.adapter,
id,
corpinfo['name'],
corpinfo['ticker'],
corpinfo['ceo']['id'],
corpinfo['members']['current'],
corpinfo['alliance']['id'] if corpinfo['alliance'] else None,
)
return model
def _build_character(self, result):
return Character(
self.adapter,
result['id'],
result['name'],
result['corp']['id'],
result['alliance']['id'],
)
def get_character(self, id):
api = evelink.eve.EVE(api=self.api)
try:
charinfo = api.character_info_from_id(id).result
except evelink.api.APIError as e:
if int(e.code) == 105:
raise ObjectNotFound(id, 'character')
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, 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 "<{} (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):
data = cache.get('%s__%s' % (obj_class.__name__.lower(), id))
if data:
obj = obj_class.from_dict(json.loads(data))
logger.debug('Got from cache: %s' % obj.__repr__())
return obj
else:
return None
@staticmethod
def _cache(obj):
logger.debug('Caching: %s ' % obj.__repr__())
cache.set('%s__%s' % (obj.__class__.__name__.lower(), obj.id), json.dumps(obj.serialize()),
int(OBJ_CACHE_DURATION))
def get_character(self, id):
obj = self._get_from_cache(Character, id)
if obj:
obj.provider = self
else:
obj = self._get_character(id)
self._cache(obj)
return obj
def get_corp(self, id):
obj = self._get_from_cache(Corporation, id)
if obj:
obj.provider = self
else:
obj = self._get_corp(id)
self._cache(obj)
return obj
def get_alliance(self, id):
obj = self._get_from_cache(Alliance, id)
if obj:
obj.provider = self
else:
obj = self._get_alliance(id)
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)
def _get_corp(self, id):
return self.corp_provider.get_corp(id)
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)
CHARACTER_PROVIDER = getattr(settings, 'EVEONLINE_CHARACTER_PROVIDER', '') or 'esi'
CORP_PROVIDER = getattr(settings, 'EVEONLINE_CORP_PROVIDER', '') or 'esi'
ALLIANCE_PROVIDER = getattr(settings, 'EVEONLINE_ALLIANCE_PROVIDER', '') or 'esi'
ITEMTYPE_PROVIDER = getattr(settings, 'EVEONLINE_ITEMTYPE_PROVIDER', '') or '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:
xml = EveXmlProvider(api_key=api_key)
if 'esi' in sources:
esi = EveSwaggerProvider(token=token)
for source in sources:
if source == 'xml':
providers.append(xml)
elif source == 'esi':
providers.append(esi)
else:
raise ValueError('Unrecognized data source "%s"' % source)
return EveAdapter(providers[0], providers[1], providers[2], providers[3])

View File

@ -2,7 +2,6 @@
# Any changes in these package requirements # Any changes in these package requirements
# should be reflected in setup.py as well. # should be reflected in setup.py as well.
mysqlclient mysqlclient
evelink
dnspython dnspython
passlib passlib
requests>=2.9.1 requests>=2.9.1
@ -20,11 +19,10 @@ django-bootstrap-pagination
django-registration django-registration
django-sortedm2m django-sortedm2m
django-redis-cache>=1.7.1 django-redis-cache>=1.7.1
django-recaptcha
django-celery-beat django-celery-beat
# Openfire # Openfire
sleekxmpp sleekxmpp
openfire-restapi openfire-restapi
adarnauth-esi<2.0 adarnauth-esi>=1.4,<2.0

View File

@ -13,7 +13,6 @@ setup(
# should be reflected in requirements.txt as well. # should be reflected in requirements.txt as well.
install_requires=[ install_requires=[
'mysqlclient', 'mysqlclient',
'evelink',
'dnspython', 'dnspython',
'passlib', 'passlib',
'requests>=2.9.1', 'requests>=2.9.1',
@ -30,14 +29,13 @@ setup(
'django-registration', 'django-registration',
'django-sortedm2m', 'django-sortedm2m',
'django-redis-cache>=1.7.1', 'django-redis-cache>=1.7.1',
'django-recaptcha',
'django-celery-beat', 'django-celery-beat',
# Openfire # Openfire
'openfire-restapi', 'openfire-restapi',
'sleekxmpp', 'sleekxmpp',
'adarnauth-esi', 'adarnauth-esi>=1.4,<2.0',
], ],
license='GPLv2', license='GPLv2',
packages=['allianceauth'], packages=['allianceauth'],