From 20f4465d6832fd228d1afc8f41828aceff9aec38 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Thu, 2 Dec 2010 12:57:49 +0000 Subject: [PATCH] Removed in-model functions for corp updates, switch to tasks. Cleaned up and improved API tasks --- ...ter_security_status__add_field_eveplaye.py | 143 ++++++++++++++++++ eve_api/models/api_player.py | 98 +++--------- eve_api/tasks/alliance.py | 15 +- eve_api/tasks/character.py | 17 ++- eve_api/tasks/corporation.py | 63 +++++++- 5 files changed, 241 insertions(+), 95 deletions(-) create mode 100644 eve_api/migrations/0007_auto__chg_field_eveplayercharacter_security_status__add_field_eveplaye.py diff --git a/eve_api/migrations/0007_auto__chg_field_eveplayercharacter_security_status__add_field_eveplaye.py b/eve_api/migrations/0007_auto__chg_field_eveplayercharacter_security_status__add_field_eveplaye.py new file mode 100644 index 0000000..aaf506d --- /dev/null +++ b/eve_api/migrations/0007_auto__chg_field_eveplayercharacter_security_status__add_field_eveplaye.py @@ -0,0 +1,143 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Changing field 'EVEPlayerCharacter.security_status' + db.alter_column('eve_api_eveplayercharacter', 'security_status', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)) + + # Adding field 'EVEPlayerAlliance.executor' + db.add_column('eve_api_eveplayeralliance', 'executor', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['eve_api.EVEPlayerCorporation'], null=True, blank=True), keep_default=False) + + + def backwards(self, orm): + + # Changing field 'EVEPlayerCharacter.security_status' + db.alter_column('eve_api_eveplayercharacter', 'security_status', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=2, decimal_places=2, blank=True)) + + # Deleting field 'EVEPlayerAlliance.executor' + db.delete_column('eve_api_eveplayeralliance', 'executor_id') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'eve_api.eveaccount': { + 'Meta': {'object_name': 'EVEAccount'}, + 'api_key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'api_keytype': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'api_status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'api_user_id': ('django.db.models.fields.IntegerField', [], {}), + 'characters': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['eve_api.EVEPlayerCharacter']", 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'eve_api.eveplayeralliance': { + 'Meta': {'object_name': 'EVEPlayerAlliance'}, + 'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'date_founded': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'executor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCorporation']", 'null': 'True', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'ticker': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}) + }, + 'eve_api.eveplayercharacter': { + 'Meta': {'object_name': 'EVEPlayerCharacter'}, + 'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'attrib_charisma': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'attrib_intelligence': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'attrib_memory': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'attrib_perception': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'attrib_willpower': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'balance': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'corporation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCorporation']", 'null': 'True', 'blank': 'True'}), + 'corporation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'current_location_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'director': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'gender': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_logoff': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'race': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'roles': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['eve_api.EVEPlayerCharacterRole']", 'null': 'True', 'blank': 'True'}), + 'security_status': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'total_sp': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, + 'eve_api.eveplayercharacterrole': { + 'Meta': {'object_name': 'EVEPlayerCharacterRole'}, + 'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'roleid': ('django.db.models.fields.CharField', [], {'max_length': '64'}) + }, + 'eve_api.eveplayercorporation': { + 'Meta': {'object_name': 'EVEPlayerCorporation'}, + 'alliance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerAlliance']", 'null': 'True', 'blank': 'True'}), + 'alliance_join_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'api_last_updated': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'applications': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'ceo_character': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['eve_api.EVEPlayerCharacter']", 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'logo_color1': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'logo_color2': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'logo_color3': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'logo_graphic_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'logo_shape1': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'logo_shape2': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'logo_shape3': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'member_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'shares': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'tax_rate': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'ticker': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['eve_api'] diff --git a/eve_api/models/api_player.py b/eve_api/models/api_player.py index 36682ff..48f9066 100644 --- a/eve_api/models/api_player.py +++ b/eve_api/models/api_player.py @@ -133,33 +133,6 @@ class EVEPlayerCharacterRole(EVEAPIModel): verbose_name = 'Player Role' verbose_name_plural = 'Player Roles' -class EVEPlayerAlliance(EVEAPIModel): - """ - Represents a player-controlled alliance. Updated from the alliance - EVE XML API puller at intervals. - """ - name = models.CharField(max_length=255, blank=True, null=False) - ticker = models.CharField(max_length=15, blank=True, null=False) - #executor_character = models.ForeignKey(EVECharacter, blank=True, null=False) - member_count = models.IntegerField(blank=True, null=True) - date_founded = models.DateField(blank=True, null=True) - group = models.ForeignKey(Group, blank=True, null=True) - - class Meta: - app_label = 'eve_api' - ordering = ['date_founded'] - verbose_name = 'Player Alliance' - verbose_name_plural = 'Player Alliances' - - def __unicode__(self): - if self.name: - return self.name - else: - return "(#%d)" % self.id - - def __str__(self): - return self.__unicode__() - class EVEPlayerCorporation(EVEAPIModel): """ Represents a player-controlled corporation. Updated from a mixture of @@ -170,8 +143,7 @@ class EVEPlayerCorporation(EVEAPIModel): description = models.TextField(blank=True, null=True) url = models.URLField(verify_exists=False, blank=True, null=True) ceo_character = models.ForeignKey(EVEPlayerCharacter, blank=True, null=True) - #home_station = models.ForeignKey(EVEStation, blank=True, null=False) - alliance = models.ForeignKey(EVEPlayerAlliance, blank=True, null=True) + alliance = models.ForeignKey('eve_api.EVEPlayerAlliance', blank=True, null=True) alliance_join_date = models.DateField(blank=True, null=True) tax_rate = models.FloatField(blank=True, null=True) member_count = models.IntegerField(blank=True, null=True) @@ -199,51 +171,31 @@ class EVEPlayerCorporation(EVEAPIModel): return self.name else: return "Corp #%d" % self.id - - def query_and_update_corp(self): - """ - Takes an EVEPlayerCorporation object and updates it from the - EVE API service. - """ - # Pull XML from the EVE API via eve_proxy. - dom = EVEPlayerCorporation.objects.api_corp_sheet_xml(self.id) - - # Tuples of pairings of tag names and the attribute on the Corporation - # object to set the data to. - tag_mappings = ( - ('corporationName', 'name'), - ('ticker', 'ticker'), - ('url', 'url'), - ('description', 'description'), - ('memberCount', 'member_count'), - ('graphicID', 'logo_graphic_id'), - ('shape1', 'logo_shape1'), - ('shape2', 'logo_shape2'), - ('shape3', 'logo_shape3'), - ('color1', 'logo_color1'), - ('color2', 'logo_color2'), - ('color3', 'logo_color3'), - ) - - # Iterate through the tag mappings, setting the values of the tag names - # (first member of the tuple) to the attribute named in the second member - # of the tuple on the EVEPlayerCorporation object. - for tag_map in tag_mappings: - try: - setattr(self, tag_map[1], - dom.getElementsByTagName(tag_map[0])[0].firstChild.nodeValue) - except AttributeError: - # This tag has no value, skip it. - continue - except IndexError: - # Something weird has happened - continue +class EVEPlayerAlliance(EVEAPIModel): + """ + Represents a player-controlled alliance. Updated from the alliance + EVE XML API puller at intervals. + """ + name = models.CharField(max_length=255, blank=True, null=False) + ticker = models.CharField(max_length=15, blank=True, null=False) + executor = models.ForeignKey(EVEPlayerCorporation, blank=True, null=True) + member_count = models.IntegerField(blank=True, null=True) + date_founded = models.DateField(blank=True, null=True) + group = models.ForeignKey(Group, blank=True, null=True) - from eve_api.tasks import import_eve_character + class Meta: + app_label = 'eve_api' + ordering = ['date_founded'] + verbose_name = 'Player Alliance' + verbose_name_plural = 'Player Alliances' - ceoid = dom.getElementsByTagName('ceoID')[0].firstChild.nodeValue - self.ceo_character = import_eve_character(ceoid) + def __unicode__(self): + if self.name: + return self.name + else: + return "(#%d)" % self.id + + def __str__(self): + return self.__unicode__() - self.api_last_updated = datetime.utcnow() - self.save() diff --git a/eve_api/tasks/alliance.py b/eve_api/tasks/alliance.py index 2e49f2a..997c87a 100644 --- a/eve_api/tasks/alliance.py +++ b/eve_api/tasks/alliance.py @@ -6,8 +6,8 @@ from celery.decorators import task from eve_proxy.models import CachedDocument from eve_api.models import EVEAccount, EVEPlayerCorporation, EVEPlayerAlliance -from eve_api.utils import basic_xml_parse -from eve_api.tasks.corporation import import_corp_details +from eve_api.utils import basic_xml_parse_doc +from eve_api.tasks.corporation import import_corp_details, import_corp_details_result @task(ignore_result=True) @@ -18,16 +18,16 @@ def import_alliance_details(): """ doc = CachedDocument.objects.api_query('/eve/AllianceList.xml.aspx') - dom = minidom.parseString(doc.body.encode('utf-8')) - nodes = dom.getElementsByTagName('result')[0].childNodes - for alliance in basic_xml_parse(nodes)['alliances']: - print alliance + for alliance in basic_xml_parse_doc(doc)['eveapi']['result']['alliances']: allobj, created = EVEPlayerAlliance.objects.get_or_create(pk=alliance['allianceID']) if created: allobj.name = alliance['name'] allobj.ticker = alliance['shortName'] allobj.date_founded = alliance['startDate'] + allobj.executor, created = EVEPlayerCorporation.objects.get_or_create(id=alliance['executorCorpID']) + if created: + import_corp_details.delay(alliance['executorCorpID']) allobj.member_count = alliance['memberCount'] allobj.api_last_updated = datetime.utcnow() allobj.save() @@ -36,10 +36,11 @@ def import_alliance_details(): validcorps = [] for corp in alliance['memberCorporations']: - if corp.id not in corplist: + if int(corp['corporationID']) not in corplist: corpobj, created = EVEPlayerCorporation.objects.get_or_create(pk=corp['corporationID']) corpobj.alliance = allobj corpobj.save() + if created: import_corp_details.delay(corp['corporationID']) validcorps.append(int(corp['corporationID'])) diff --git a/eve_api/tasks/character.py b/eve_api/tasks/character.py index f40a14f..dd8809c 100644 --- a/eve_api/tasks/character.py +++ b/eve_api/tasks/character.py @@ -7,12 +7,11 @@ from eve_proxy.models import CachedDocument from eve_api.models import EVEPlayerCorporation, EVEPlayerCharacter, EVEPlayerCharacterRole from eve_api.app_defines import * -from eve_api.utils import basic_xml_parse -from eve_api.tasks.corporation import import_corp_details +from eve_api.utils import basic_xml_parse, basic_xml_parse_doc @task() -def import_eve_character(character_id, api_key=None, user_id=None): +def import_eve_character(character_id, api_key=None, user_id=None, callback=None): """ Imports a character from the API, providing a API key will populate further details @@ -23,10 +22,10 @@ def import_eve_character(character_id, api_key=None, user_id=None): params={'characterID': character_id}, no_cache=False) - dom = minidom.parseString(char_doc.body.encode('utf-8')) - if dom.getElementsByTagName('error'): + d = basic_xml_parse_doc(char_doc)['eveapi'] + if 'error' in d: return - values = basic_xml_parse(dom.getElementsByTagName('result')[0].childNodes) + values = d['result'] pchar, created = EVEPlayerCharacter.objects.get_or_create(id=character_id) pchar.name = values['characterName'] @@ -34,6 +33,7 @@ def import_eve_character(character_id, api_key=None, user_id=None): corp, created = EVEPlayerCorporation.objects.get_or_create(id=values['corporationID']) if created: + from eve_api.tasks.corporation import import_corp_details import_corp_details.delay(values['corporationID']) pchar.corporation = corp pchar.corporation_date = values['corporationDate'] @@ -85,4 +85,7 @@ def import_eve_character(character_id, api_key=None, user_id=None): pchar.api_last_updated = datetime.utcnow() pchar.save() - return pchar + if callback: + callback.delay(character=pchar.id) + else: + return pchar diff --git a/eve_api/tasks/corporation.py b/eve_api/tasks/corporation.py index aa9d7f7..06c542a 100644 --- a/eve_api/tasks/corporation.py +++ b/eve_api/tasks/corporation.py @@ -3,18 +3,65 @@ from xml.dom import minidom from celery.decorators import task from eve_proxy.models import CachedDocument -from eve_api.models import EVEPlayerCorporation -from eve_api.api_puller.corp_management import pull_corp_members -from eve_api.utils import basic_xml_parse - +from eve_api.models import EVEPlayerCorporation, EVEPlayerCharacter +from eve_api.utils import basic_xml_parse_doc +from eve_api.tasks.character import import_eve_character @task(ignore_result=True) def import_corp_details(corp_id): - corp, created = EVEPlayerCorporation.objects.get_or_create(id=corp_id) + import_corp_details_func(corp_id) + +@task() +def import_corp_details_result(corp_id): + return import_corp_details_func(corp_id) + + +def import_corp_details_func(corp_id): + corpobj, created = EVEPlayerCorporation.objects.get_or_create(id=corp_id) - if created or not corp.api_last_updated or corp.api_last_updated < (datetime.utcnow() - timedelta(hours=12)): - corp.query_and_update_corp() - corp.save() + if created or not corpobj.api_last_updated or corpobj.api_last_updated < (datetime.utcnow() - timedelta(hours=12)): + + doc = CachedDocument.objects.api_query('/corp/CorporationSheet.xml.aspx', {'corporationID': corp_id}) + d = basic_xml_parse_doc(doc)['eveapi']['result'] + + tag_mappings = ( + ('corporationName', 'name'), + ('ticker', 'ticker'), + ('url', 'url'), + ('description', 'description'), + ('memberCount', 'member_count'), + ) + + for tag_map in tag_mappings: + setattr(corpobj, tag_map[1], d[tag_map[0]]) + + logo_mappings = ( + ('graphicID', 'logo_graphic_id'), + ('shape1', 'logo_shape1'), + ('shape2', 'logo_shape2'), + ('shape3', 'logo_shape3'), + ('color1', 'logo_color1'), + ('color2', 'logo_color2'), + ('color3', 'logo_color3'), + ) + + for logo_map in logo_mappings: + setattr(corpobj, logo_map[1], d['logo'][logo_map[0]]) + + import_eve_character.delay(d['ceoID'], callback=link_ceo.subtask(corporation=corpobj.id)) + + corpobj.api_last_updated = datetime.utcnow() + corpobj.save() + + return EVEPlayerCorporation.objects.get(pk=corpobj.pk) + + +@task(ignore_result=True) +def link_ceo(corporation, character): + """ Links a character to the CEO position of a corporation """ + corpobj = EVEPlayerCorporation.objects.get(id=corporation) + corpobj.ceo_character = EVEPlayerCharacter.objects.get(id=character) + corpobj.save() @task(ignore_result=True)