From 12790be989cce129534430f341d9875c63a0adfb Mon Sep 17 00:00:00 2001 From: Amber Yust Date: Mon, 13 Jul 2015 18:24:27 -0700 Subject: [PATCH 1/3] Add x,y,z to the station endpoints. Closes #220. --- evelink/corp.py | 3 +++ evelink/eve.py | 5 ++++- tests/test_corp.py | 3 +++ tests/test_eve.py | 10 ++++++++-- tests/xml/corp/stations.xml | 6 +++++- tests/xml/eve/conquerable_stations.xml | 6 ++++-- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/evelink/corp.py b/evelink/corp.py index ebf1133..4e8168d 100644 --- a/evelink/corp.py +++ b/evelink/corp.py @@ -593,6 +593,9 @@ def stations(self, api_result=None): 'cut': float(a['reprocessingStationTake']), }, 'standing_owner_id': int(a['standingOwnerID']), + 'x': float(a['x']), + 'y': float(a['y']), + 'z': float(a['z']), } results[station['id']] = station diff --git a/evelink/eve.py b/evelink/eve.py index 4d51fe4..e814507 100644 --- a/evelink/eve.py +++ b/evelink/eve.py @@ -448,7 +448,10 @@ def conquerable_stations(self, api_result=None): 'system_id': int(row.attrib['solarSystemID']), 'corp': { 'id': int(row.attrib['corporationID']), - 'name': row.attrib['corporationName'] } + 'name': row.attrib['corporationName'] }, + 'x': float(row.attrib['x']), + 'y': float(row.attrib['y']), + 'z': float(row.attrib['z']), } results[station['id']] = station diff --git a/tests/test_corp.py b/tests/test_corp.py index 5738401..ce594f8 100644 --- a/tests/test_corp.py +++ b/tests/test_corp.py @@ -701,6 +701,9 @@ def test_stations(self): 'standing_owner_id': 673381830, 'system_id': 30004181, 'type_id': 21645, + 'x': 61066567680, + 'y': 2632949760, + 'z': 285129646080, }, }) self.assertEqual(self.api.mock_calls, [ diff --git a/tests/test_eve.py b/tests/test_eve.py index f3671fc..0bff8d6 100644 --- a/tests/test_eve.py +++ b/tests/test_eve.py @@ -388,7 +388,10 @@ def test_conquerable_stations(self): 'system_id':512, 'corp':{ 'id':444, - 'name':"Valkyries of Night" } + 'name':"Valkyries of Night" }, + 'x': 61066567680, + 'y': 2632949760, + 'z': 285129646080, }, 2:{ 'id':2, 'name':"Station the station", @@ -396,7 +399,10 @@ def test_conquerable_stations(self): 'system_id':503, 'corp':{ 'id':400, - 'name':"Deus Fides Empire"} + 'name':"Deus Fides Empire"}, + 'x': 11066567680, + 'y': 2632949760, + 'z': 385129646080, } }) self.assertEqual(self.api.mock_calls, [ diff --git a/tests/xml/corp/stations.xml b/tests/xml/corp/stations.xml index 04db9df..c48ca3e 100644 --- a/tests/xml/corp/stations.xml +++ b/tests/xml/corp/stations.xml @@ -9,6 +9,10 @@ stationTypeID="21645" reprocessingEfficiency="0.5" reprocessingStationTake="0.025" - standingOwnerID="673381830" /> + standingOwnerID="673381830" + x="61066567680" + y="2632949760.0" + z="285129646080" + /> diff --git a/tests/xml/eve/conquerable_stations.xml b/tests/xml/eve/conquerable_stations.xml index aeddd4e..f8066ef 100644 --- a/tests/xml/eve/conquerable_stations.xml +++ b/tests/xml/eve/conquerable_stations.xml @@ -1,8 +1,10 @@ + solarSystemID="512" corporationID="444" corporationName="Valkyries of Night" + x="61066567680" y="2632949760.0" z="285129646080"/> + solarSystemID="503" corporationID="400" corporationName="Deus Fides Empire" + x="11066567680" y="2632949760" z="385129646080"/> From 00abe9b334d3e9423e65e2a0f26f6a22e9a43fbc Mon Sep 17 00:00:00 2001 From: Amber Yust Date: Mon, 13 Jul 2015 19:02:21 -0700 Subject: [PATCH 2/3] Add labels to contact parsing. Closes #221. --- evelink/parsing/contact_list.py | 61 +++++++++++++++++++------- tests/parsing/test_contact_list.py | 69 +++++++++++++++++++++++------- tests/xml/char/contact_list.xml | 19 ++++++-- tests/xml/corp/contact_list.xml | 11 ++++- 4 files changed, 125 insertions(+), 35 deletions(-) diff --git a/evelink/parsing/contact_list.py b/evelink/parsing/contact_list.py index 4bdfe46..d80e79c 100644 --- a/evelink/parsing/contact_list.py +++ b/evelink/parsing/contact_list.py @@ -1,26 +1,57 @@ -LABEL_MAP = { +CONTACTS_MAP = { 'allianceContactList': 'alliance', 'corporateContactList': 'corp', 'contactList': 'personal', } +LABEL_MAP = { + 'contactLabels': 'personal', + 'corporateContactLabels': 'corp', + 'allianceContactLabels': 'alliance', +} + def parse_contact_list(api_result): - result = {} + result = {'labels': {}} for rowset in api_result.findall('rowset'): - contact_list = result[LABEL_MAP[rowset.get('name')]] = {} - for row in rowset.findall('row'): - in_watchlist = (row.get('inWatchlist') == 'True' - if 'inWatchlist' in row.attrib - else None) - contact_id = int(row.get('contactID')) - contact_list[contact_id] = { - 'id': contact_id, - 'name': row.get('contactName'), - 'standing': float(row.get('standing')), - 'in_watchlist': in_watchlist - } + setname = rowset.get('name') + + if setname in CONTACTS_MAP: + contact_list = result[CONTACTS_MAP[rowset.get('name')]] = {} + for row in rowset.findall('row'): + in_watchlist = (row.get('inWatchlist') == 'True' + if 'inWatchlist' in row.attrib + else None) + contact_id = int(row.get('contactID')) + contact_list[contact_id] = { + 'id': contact_id, + 'name': row.get('contactName'), + 'standing': float(row.get('standing')), + 'in_watchlist': in_watchlist, + 'label_mask': int(row.get('labelMask') or 0), + 'labels': {}, + } + elif setname in LABEL_MAP: + label_list = result['labels'][LABEL_MAP[setname]] = {} + for row in rowset.findall('row'): + label_id = int(row.get('labelID')) + label_list[label_id] = { + 'id': label_id, + 'name': row.get('name'), + } + for grouping in ('personal', 'corp', 'alliance'): + group = result.get(grouping) + if not group: + continue + labels = result['labels'][grouping] + for contact_id in group: + contact = group[contact_id] + labelMask = contact['label_mask'] + if labelMask: + for label_id in labels: + if labelMask & label_id: + contact['labels'][label_id] = labels[label_id] + del contact['label_mask'] return result - diff --git a/tests/parsing/test_contact_list.py b/tests/parsing/test_contact_list.py index 22c34f4..b898645 100644 --- a/tests/parsing/test_contact_list.py +++ b/tests/parsing/test_contact_list.py @@ -17,33 +17,57 @@ def test_parse_char_contact_list(self): 'corp': { 1082138174: {'standing': 10.0, 'id': 1082138174, 'name': 'Nomad LLP', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': {}}, 1086308227: {'standing': 0.0, 'id': 1086308227, 'name': 'Rebel Alliance of New Eden', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': { + 1: {'id': 1, 'name': 'Corp Spies!'}}}, 1113838907: {'standing': -10.0, 'id': 1113838907, 'name': 'Significant other', - 'in_watchlist': None} + 'in_watchlist': None, + 'labels': {}} }, 'alliance': { 2049763943: {'standing': -10.0, 'id': 2049763943, 'name': 'EntroPraetorian Aegis', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': {}}, 2067199408: {'standing': -10.0, 'id': 2067199408, 'name': 'Vera Cruz Alliance', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': { + 2: {'id': 2, 'name': 'Stupid'}}}, 2081065875: {'standing': -7.5, 'id': 2081065875, 'name': 'TheRedMaple', - 'in_watchlist': None} + 'in_watchlist': None, + 'labels': {}} }, 'personal': { 3009988: {'standing': 0.0, 'id': 3009988, 'name': 'Navittus Sildbena', - 'in_watchlist': True}, + 'in_watchlist': True, + 'labels': {}}, 544497016: {'standing': 10.0, 'id': 544497016, 'name': 'Valkyries of Night', - 'in_watchlist': False} - } + 'in_watchlist': False, + 'labels': { + 1: {'id': 1, 'name': 'Alts'}, + 2: {'id': 2, 'name': 'Evil Twins'}}}, + + }, + 'labels': { + 'corp': { + 1: {'id': 1, 'name': 'Corp Spies!'}}, + 'alliance': { + 1: {'id': 1, 'name': 'Alliance Friend'}, + 2: {'id': 2, 'name': 'Stupid'}}, + 'personal': { + 1: {'id': 1, 'name': 'Alts'}, + 2: {'id': 2, 'name': 'Evil Twins'}, + 4611686018427387904: {'id': 4611686018427387904, 'name': 'Label 61'}}, + }, } self.assertEqual(result['personal'], expected_result['personal']) @@ -60,24 +84,39 @@ def test_parse_corp_contact_list(self): 'corp': { 1082138174: {'standing': 10.0, 'id': 1082138174, 'name': 'Nomad LLP', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': {}}, 1086308227: {'standing': 0.0, 'id': 1086308227, 'name': 'Rebel Alliance of New Eden', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': { + 1: {'id': 1, 'name': 'Corp Spies!'}}}, 1113838907: {'standing': -10.0, 'id': 1113838907, 'name': 'Significant other', - 'in_watchlist': None} + 'in_watchlist': None, + 'labels': {}} }, 'alliance': { 2049763943: {'standing': -10.0, 'id': 2049763943, 'name': 'EntroPraetorian Aegis', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': {}}, 2067199408: {'standing': -10.0, 'id': 2067199408, 'name': 'Vera Cruz Alliance', - 'in_watchlist': None}, + 'in_watchlist': None, + 'labels': { + 2: {'id': 2, 'name': 'Stupid'}}}, 2081065875: {'standing': -10.0, 'id': 2081065875, 'name': 'TheRedMaple', - 'in_watchlist': None} + 'in_watchlist': None, + 'labels': {}} + }, + 'labels': { + 'corp': { + 1: {'id': 1, 'name': 'Corp Spies!'}}, + 'alliance': { + 1: {'id': 1, 'name': 'Alliance Friend'}, + 2: {'id': 2, 'name': 'Stupid'}}, }, } diff --git a/tests/xml/char/contact_list.xml b/tests/xml/char/contact_list.xml index 66025c8..2ae89fd 100644 --- a/tests/xml/char/contact_list.xml +++ b/tests/xml/char/contact_list.xml @@ -1,17 +1,30 @@ - + + + + + + - + + + + - + + + + + diff --git a/tests/xml/corp/contact_list.xml b/tests/xml/corp/contact_list.xml index 81ee273..3589283 100644 --- a/tests/xml/corp/contact_list.xml +++ b/tests/xml/corp/contact_list.xml @@ -1,13 +1,20 @@ - + + + + - + + + + + From 937cf75ac72fe052c0ca83571ef4ef50a574fcc5 Mon Sep 17 00:00:00 2001 From: Amber Yust Date: Mon, 13 Jul 2015 19:40:06 -0700 Subject: [PATCH 3/3] Add Char.bookmarks and Corp.bookmarks. Closes #222. --- evelink/char.py | 6 +++ evelink/corp.py | 6 +++ evelink/parsing/bookmarks.py | 35 ++++++++++++++++ tests/parsing/test_bookmarks.py | 73 +++++++++++++++++++++++++++++++++ tests/test_char.py | 16 ++++++++ tests/test_corp.py | 16 ++++++++ tests/xml/char/bookmarks.xml | 18 ++++++++ 7 files changed, 170 insertions(+) create mode 100644 evelink/parsing/bookmarks.py create mode 100644 tests/parsing/test_bookmarks.py create mode 100644 tests/xml/char/bookmarks.xml diff --git a/evelink/char.py b/evelink/char.py index 59dd67c..174f295 100644 --- a/evelink/char.py +++ b/evelink/char.py @@ -2,6 +2,7 @@ from evelink import api, constants from evelink.parsing.assets import parse_assets +from evelink.parsing.bookmarks import parse_bookmarks from evelink.parsing.contact_list import parse_contact_list from evelink.parsing.contract_bids import parse_contract_bids from evelink.parsing.contract_items import parse_contract_items @@ -67,6 +68,11 @@ def assets(self, api_result=None): return api.APIResult(parse_assets(api_result.result), api_result.timestamp, api_result.expires) + @auto_call('char/Bookmarks') + def bookmarks(self, api_result=None): + """Retrieves this character's bookmarks.""" + return api.APIResult(parse_bookmarks(api_result.result), api_result.timestamp, api_result.expires) + @auto_call('char/ContractBids') def contract_bids(self, api_result=None): """Lists the latest bids that have been made to any recent auctions.""" diff --git a/evelink/corp.py b/evelink/corp.py index 4e8168d..7b7569e 100644 --- a/evelink/corp.py +++ b/evelink/corp.py @@ -1,5 +1,6 @@ from evelink import api, constants from evelink.parsing.assets import parse_assets +from evelink.parsing.bookmarks import parse_bookmarks from evelink.parsing.contact_list import parse_contact_list from evelink.parsing.contract_bids import parse_contract_bids from evelink.parsing.contract_items import parse_contract_items @@ -215,6 +216,11 @@ def assets(self, api_result=None): return api.APIResult(parse_assets(api_result.result), api_result.timestamp, api_result.expires) + @api.auto_call('corp/Bookmarks') + def bookmarks(self, api_result=None): + """Retrieves this corp's bookmarks.""" + return api.APIResult(parse_bookmarks(api_result.result), api_result.timestamp, api_result.expires) + @api.auto_call('corp/FacWarStats') def faction_warfare_stats(self, api_result=None): """Returns stats from faction warfare if this corp is enrolled. diff --git a/evelink/parsing/bookmarks.py b/evelink/parsing/bookmarks.py new file mode 100644 index 0000000..b69c6a5 --- /dev/null +++ b/evelink/parsing/bookmarks.py @@ -0,0 +1,35 @@ +from evelink import api + +def parse_bookmarks(api_results): + result = {} + folders = api_results.find('rowset') + for row in folders.findall('row'): + a = row.attrib + folder_id = int(a['folderID']) + folder = { + 'id': folder_id, + 'name': a['folderName'], # "" = toplevel + 'creator_id': int(a['creatorID']), + 'bookmarks': {}, + } + bookmarks = row.find('rowset') + for row in bookmarks.findall('row'): + a = row.attrib + bookmark_id = int(a['bookmarkID']) + folder['bookmarks'][bookmark_id] = { + 'id': bookmark_id, + 'name': a['memo'], + 'creator_id': int(a['creatorID']), + 'created_ts': api.parse_ts(a['created']), + 'item_id': int(a['itemID']), + 'type_id': int(a['typeID']), + 'location_id': int(a['locationID']), + 'x': float(a['x']), + 'y': float(a['y']), + 'z': float(a['z']), + 'note': a['note'], + } + result[folder_id] = folder + return result + +# vim: set ts=4 sts=4 sw=4 et: diff --git a/tests/parsing/test_bookmarks.py b/tests/parsing/test_bookmarks.py new file mode 100644 index 0000000..d5801a0 --- /dev/null +++ b/tests/parsing/test_bookmarks.py @@ -0,0 +1,73 @@ +from tests.compat import unittest +from tests.utils import make_api_result + +from evelink.parsing import bookmarks as evelink_b + +class BookmarksTestCase(unittest.TestCase): + + def test_parse_bookmarks(self): + api_result, _, _ = make_api_result("char/bookmarks.xml") + + result = evelink_b.parse_bookmarks(api_result) + + self.assertEqual(result, { + 0: { + 'bookmarks': { + 12: { + 'created_ts': 1436391254, + 'creator_id': 90000001, + 'id': 12, + 'item_id': 60014689, + 'location_id': 30004971, + 'name': 'Home Station', + 'note': 'Our base of residence', + 'type_id': 57, + 'x': 0.0, + 'y': 0.0, + 'z': 0.0, + }, + 13: { + 'created_ts': 1436391307, + 'creator_id': 90000001, + 'id': 13, + 'item_id': 40314792, + 'location_id': 30004971, + 'name': 'Sun', + 'note': '', + 'type_id': 8, + 'x': 0.0, + 'y': 0.0, + 'z': 0.0, + }, + }, + 'creator_id': 0, + 'id': 0, + 'name': '', + }, + 1: { + 'bookmarks': {}, + 'creator_id': 90000001, + 'id': 1, + 'name': 'A lovely empty folder', + }, + 4: { + 'bookmarks': { + 14: { + 'created_ts': 1436391368, + 'creator_id': 90000001, + 'id': 14, + 'item_id': 0, + 'location_id': 30004971, + 'name': 'spot in Duripant solar system', + 'note': '', + 'type_id': 5, + 'x': -373405654941.733, + 'y': 42718621667.0746, + 'z': -1415023302173.46, + }, + }, + 'creator_id': 90000001, + 'id': 4, + 'name': 'Random crap', + }, + }) diff --git a/tests/test_char.py b/tests/test_char.py index 379c224..35fdef4 100644 --- a/tests/test_char.py +++ b/tests/test_char.py @@ -32,6 +32,22 @@ def test_assets(self, mock_parse): self.assertEqual(current, 12345) self.assertEqual(expires, 67890) + @mock.patch('evelink.char.parse_bookmarks') + def test_bookmarks(self, mock_parse): + self.api.get.return_value = API_RESULT_SENTINEL + mock_parse.return_value = mock.sentinel.parsed_bookmarks + + result, current, expires = self.char.bookmarks() + self.assertEqual(result, mock.sentinel.parsed_bookmarks) + self.assertEqual(mock_parse.mock_calls, [ + mock.call(mock.sentinel.api_result), + ]) + self.assertEqual(self.api.mock_calls, [ + mock.call.get('char/Bookmarks', params={'characterID': 1}), + ]) + self.assertEqual(current, 12345) + self.assertEqual(expires, 67890) + @mock.patch('evelink.char.parse_contract_bids') def test_contract_bids(self, mock_parse): self.api.get.return_value = API_RESULT_SENTINEL diff --git a/tests/test_corp.py b/tests/test_corp.py index ce594f8..ddb0bad 100644 --- a/tests/test_corp.py +++ b/tests/test_corp.py @@ -406,6 +406,22 @@ def test_assets(self, mock_parse): self.assertEqual(current, 12345) self.assertEqual(expires, 67890) + @mock.patch('evelink.corp.parse_bookmarks') + def test_bookmarks(self, mock_parse): + self.api.get.return_value = API_RESULT_SENTINEL + mock_parse.return_value = mock.sentinel.parsed_bookmarks + + result, current, expires = self.corp.bookmarks() + self.assertEqual(result, mock.sentinel.parsed_bookmarks) + self.assertEqual(mock_parse.mock_calls, [ + mock.call(mock.sentinel.api_result), + ]) + self.assertEqual(self.api.mock_calls, [ + mock.call.get('corp/Bookmarks', params={}), + ]) + self.assertEqual(current, 12345) + self.assertEqual(expires, 67890) + def test_shareholders(self): self.api.get.return_value = self.make_api_result("corp/shareholders.xml") diff --git a/tests/xml/char/bookmarks.xml b/tests/xml/char/bookmarks.xml new file mode 100644 index 0000000..dda6431 --- /dev/null +++ b/tests/xml/char/bookmarks.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +