diff options
Diffstat (limited to 'gamelocker')
| -rw-r--r-- | gamelocker/api.py | 19 | ||||
| -rw-r--r-- | gamelocker/datatypes.py | 16 | ||||
| -rw-r--r-- | gamelocker/janus.py | 4 | ||||
| -rw-r--r-- | gamelocker/strings.py | 242 |
4 files changed, 272 insertions, 9 deletions
diff --git a/gamelocker/api.py b/gamelocker/api.py index 6857eba..c1383d6 100644 --- a/gamelocker/api.py +++ b/gamelocker/api.py @@ -3,7 +3,7 @@ # TODO: generate documentation """ -requests.api +gamelocker.api This module implements the Gamelocker API. """ @@ -11,6 +11,7 @@ This module implements the Gamelocker API. import datetime import requests import gamelocker.datatypes +import gamelocker.strings class Gamelocker(object): @@ -157,12 +158,18 @@ class Gamelocker(object): :return: List of matches. :rtype: list of dict """ + max_limit = 50 # as set by the API + params = dict() # TODO: deprecate by ?limit=x&offset=y soon if limit: params["page[limit]"] = limit + else: + limit = max_limit if offset: params["page[offset]"] = offset + else: + offset = 0 if sort: # TODO make this nice and usable params["sort"] = sort if player: @@ -178,4 +185,12 @@ class Gamelocker(object): createdAtEnd = createdAtEnd.isoformat() params["filter[createdAt-end]"] = createdAtEnd - return self._get("matches", params=params) + # split request to batches of 50 + matches = [] + for batch in range(0, limit, max_limit): + params["page[limit]"] = min(limit, max_limit) + params["page[offset]"] = batch*max_limit+offset + matches += self._get("matches", params=params) + limit -= max_limit + + return matches diff --git a/gamelocker/datatypes.py b/gamelocker/datatypes.py index cf89fad..74ce965 100644 --- a/gamelocker/datatypes.py +++ b/gamelocker/datatypes.py @@ -1,9 +1,15 @@ #!/usr/bin/python # -*- coding: utf-8 -*- # pylint: disable=missing-docstring +""" +gamelocker.datatypes + +Classes and utility functions to map API responses to objects. +""" import inspect import sys +import gamelocker.strings from gamelocker.janus import DataMessage, Attribute @@ -38,15 +44,15 @@ class Player(DataMessage): key_id = attr(str, "id") name = attr(str, "name") - stats = attr(dict, "stats") + stats = attr(gamelocker.strings.Stats, "stats") class Participant(DataMessage): type_name = "participant" key_id = attr(str, "id") - actor = attr(str, "actor") - stats = attr(dict, "stats") + actor = attr(gamelocker.strings.Hero, "actor") + stats = attr(gamelocker.strings.Stats, "stats") player = rel(Player, "player") @@ -62,7 +68,7 @@ class Roster(DataMessage): type_name = "roster" key_id = attr(str, "id") - stats = attr(dict, "stats") + stats = attr(gamelocker.strings.Stats, "stats") participants = rel(Participant, "participants") team = rel(Team, "team") @@ -77,7 +83,7 @@ class Match(DataMessage): gameMode = attr(str, "gameMode") patchVersion = attr(str, "patchVersion") region = attr(str, "region") - stats = attr(dict, "stats") + stats = attr(gamelocker.strings.Stats, "stats") rosters = rel(Roster, "rosters") diff --git a/gamelocker/janus.py b/gamelocker/janus.py index c4fd384..99c0a57 100644 --- a/gamelocker/janus.py +++ b/gamelocker/janus.py @@ -267,7 +267,7 @@ class Attribute(object): #Attribute Class to map Data from input Object to Messa transformation to json. """ - __primitive_types = (str,str,int,int,float,bool) #all allowed types for attribute values. (lists and dicts are also allowed, but treated differently) + __primitive_types = (str,int,float,bool) #all allowed types for attribute values. (lists and dicts are also allowed, but treated differently) value = None #holds the actual value of this attribute once it is set. @@ -289,7 +289,7 @@ class Attribute(object): #Attribute Class to map Data from input Object to Messa sets all needed configurations and checks if value is a primitive type or list or dict. """ - if value_type in self.__primitive_types or value_type == list or value_type == dict or issubclass(value_type,DataMessage): + if issubclass(value_type, self.__primitive_types + (list, dict)) or issubclass(value_type,DataMessage): self.value_type = value_type self.name = name self.required = required diff --git a/gamelocker/strings.py b/gamelocker/strings.py new file mode 100644 index 0000000..2df2647 --- /dev/null +++ b/gamelocker/strings.py @@ -0,0 +1,242 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# pylint: disable=invalid-name,missing-docstring +""" +gamelocker.strings + +A collection of mappings between strings returned by the API +and their common names. +""" + + +# this is quite of a hack. +class Stats(dict): + """A hybrid between `dict` and `object` + that types :class:`LazyObject`'s to strings.""" + def __typeit(self, obj): + if isinstance(obj, (tuple, list)): + l = [] + for o in obj: + l.append(self.__typeit(o)) + return l + if isinstance(obj, dict): + return Stats(obj) + if isinstance(obj, str): + return LazyObject(obj) + return obj + + def __get(self, name): + if name in self: + return self.__typeit(self[name]) + else: + raise AttributeError("No such attribute: " + name) + + def __getattr__(self, name): + return self.__get(name) + + def __setattr__(self, name, value): + self[name] = value + + def __delattr__(self, name): + if name in self: + del self[name] + else: + raise AttributeError("No such attribute: " + name) + + @property + def items(self): + return self.__get("items") + +class LazyObject(str): + """Can be both :class:`Hero` or :class:`Item`.""" + def pretty(self): + for cls in (Hero, Item): + prettystr = cls(self).pretty() + if prettystr != self: + return prettystr + return self + + +class Hero(str): + heroes = { + "*Adagio*": "Adagio", + "*Alpha*": "Alpha", + "*Ardan*": "Ardan", + "*Baron*": "Baron", + "*Blackfeather*": "Blackfeather", + "*Catherine*": "Catherine", + "*Celeste*": "Celeste", + "*Flicker*": "Flicker", + "*Fortress*": "Fortress", + "*Glaive*": "Glaive", + "*Gwen*": "Gwen", + "*Hero009*": "Krul", + "*Hero010*": "Skaarf", + "*Hero016*": "Rona", + "*Idris*": "Idris", + "*Joule*": "Joule", + "*Kestrel*": "Kestrel", + "*Koshka*": "Koshka", + "*Lance*": "Lance", + "*Lyra*": "Lyra", + "*Ozo*": "Ozo", + "*Petal*": "Petal", + "*Phinn*": "Phinn", + "*Reim*": "Reim", + "*Ringo*": "Ringo", + "*Samuel*": "Samuel", + "*SAW*": "SAW", + "*Sayoc*": "Taka", + "*Skye*": "Skye", + "*Vox*": "Vox" + } + + def pretty(self): + if self in self.heroes: + return self.heroes[self] + return self + + +class Item(str): + items = { + "Aftershock": "Aftershock", + "Armor2": "Coat of Plates", + "Armor3": "Metal Jacket", + "Armor Shredder": "Bonesaw", + "Atlas Pauldron": "Atlas Pauldron", + "AttackSpeed1": "Swift Shooter", + "AttackSpeed2": "Blazing Salvo", + "BarbedNeedle": "Barbed Needle", + "Boots1": "Sprint Boots", + "Boots2": "Travel Boots", + "Boots3": "Journey Boots", + "BreakingPoint": "Breaking Point", + "Broken Myth": "Broken Myth", + "Clockwork": "Clockwork", + "Cogwheel": "Chronograph", + "Contraption": "Contraption", + "Cooldown1": "Hourglass", + "Critical": "Tyrant's Monocle", + "Crucible": "Crucible", + "Crystal1": "Crystal Bit", + "Crystal2": "Eclipse Prism", + "Crystal3": "Shatterglass", + "Crystal Matrix": "Alternating Current", + "Echo": "Echo", + "EveOfHarvest": "Eve of Harvest", + "Flare": "Flare", + "Flaregun": "Flare Gun", + "Fountain of Renewal": "Fountain of Renewal", + "Frostburn": "Frostburn", + "Halcyon Chargers": "Halcyon Chargers", + "Health2": "Dragonheart", + "Heavy Prism": "Heavy Prism", + "Heavy Steel": "Heavy Steel", + "IronguardContract": "Ironguard Contract", + "Lifewell": "Lifespring", + "Light Armor": "Light Armor", + "Light Shield": "Light Shield", + "LuckyStrike": "Lucky Strike", + "Minion Candy": "Minion Candy", + "MinionsFoot": "Minion's Foot", + "Mulled Wine": "Halcyon Potion", + "NullwaveGauntlet": "Nullwave Gauntlet", + "Oakheart": "Oakheart", + "PiercingShard": "Piercing Shard", + "PiercingSpear": "Piercing Spear", + "PoisonedShiv": "Poisoned Shiv", + "Protector Contract": "Protector Contract", + "Reflex Block": "Reflex Block", + "Scout Trap": "Scout Trap", + "Serpent Mask": "Serpent Mask", + "Shield 2": "Kinetic Shield", + "Shiversteel": "Shiversteel", + "Six Sins": "Six Sins", + "SlumberingHusk": "Slumbering Husk", + "Steam Battery": "Energy Battery", + "Stormcrown": "Stormcrown", + "StormguardBanner": "Stormguard Banner", + "Tension Bow": "Tension Bow", + "Tornado Trigger": "Tornado Trigger", + "Void Battery": "Void Battery", + "War Treads": "War Treads", + "Weapon3": "Sorrowblade", + "Weapon Blade": "Weapon Blade" + } + + item_ids = { + "*1000_Item_HalcyonPotion*": "Halcyon Potion", + "*1002_Item_WeaponBlade*": "Weapon Blade", + "*1003_Item_CrystalBit*": "Crystal Bit", + "*1004_Item_SwiftShooter*": "Swift Shooter", + "*1005_Item_SixSins*": "Six Sins", + "*1009_Item_EclipsePrism*": "Eclipse Prism", + "*1010_Item_BlazingSalvo*": " Blazing Salvo", + "*1012_Item_Sorrowblade*": "Sorrowblade", + "*1013_Item_Shatterglass*": "Shatterglass", + "*1014_Item_TornadoTrigger*": "Tornado Trigger", + "*1015_Item_Oakheart*": "Oakheart", + "*1016_Item_Dragonheart*": "Dragonheart", + "*1017_Item_LightArmor*": "Light Armor", + "*1022_Item_CoatOfPlates*": "Coat of Plates", + "*1024_Item_MetalJacket*": "Metal Jacket", + "*1025_Item_EnergyBattery*": "Energy Battery", + "*1026_Item_Hourglass*": "Hourglass", + "*1027_Item_VoidBattery*": "Void Battery", + "*1028_Item_Chronograph*": "Chronograph", + "*1029_Item_Clockwork*": "Clockwork", + "*1030_Item_SprintBoots*": "Sprint Boots", + "*1032_Item_TravelBoots*": "Travel Boots", + "*1034_Item_SerpentMask*": "Serpent Mask", + "*1035_Item_TensionBow*": "Tension Bow", + "*1038_Item_Flare*": "Flare", + "*1039_Item_Bonesaw*": "Bonesaw", + "*1041_Item_MinionCandy*": "Minion Candy", + "*1042_Item_Shiversteel*": "Shiversteel", + "*1043_Item_ReflexBlock*": "Reflex Block", + "*1044_Item_Frostburn*": "Frostburn", + "*1045_Item_FountainOfRenewal*": "Fountain of Renewal", + "*1046_Item_Crucible*": "Crucible", + "*1047_Item_JourneyBoots*": "Journey Boots", + "*1049_Item_TyrantsMonocle*": "Tyrant's Monocle", + "*1050_Item_Aftershock*": "Aftershock", + "*1052_Item_WeaponInfusion*": "Weapon Infusion", + "*1053_Item_CrystalInfusion*": "Crystal Infusion", + "*1054_Item_ScoutTrap*": "Scout Trap", + "*1055_Item_BrokenMyth*": "Broken Myth", + "*1056_Item_WarTreads*": "War Treads", + "*1057_Item_AtlasPauldron*": "Atlas Pauldron", + "*1059_Item_BookOfEulogies*": "Book of Eulogies", + "*1060_Item_BarbedNeedle*": "Barbed Needle", + "*1061_Item_LightShield*": "Light Shield", + "*1062_Item_KineticShield*": "Kinetic Shield", + "*1063_Item_Aegis*": "Aegis", + "*1064_Item_Lifespring*": "Lifespring", + "*1065_Item_HeavySteel*": "Heavy Steel", + "*1066_Item_PiercingSpear*": "Piercing Spear", + "*1067_Item_BreakingPoint*": "Breaking Point", + "*1068_Item_LuckyStrike*": "Lucky Strike", + "*1069_Item_AlternatingCurrent*": "Alternating Current", + "*1070_Item_PiercingShard*": "Piercing Shard", + "*1071_Item_EveOfHarvest*": "Eve of Harvest", + "*1072_Item_HeavyPrism*": "Heavy Prism", + "*1073_Item_IronguardContract*": "Ironguard Contract", + "*1074_Item_StormguardBanner*": "Stormguard Banner", + "*1079_Item_Contraption*": "Contraption", + "*1080_Item_MinionsFoot*": "Minion's Foot", + "*1084_Item_ProtectorContract*": "Protector Contract", + "*1087_Item_HalcyonChargers*": "Halcyon Chargers", + "*1088_Item_Flaregun*": "Flare Gun", + "*1090_Item_Stormcrown*": "Stormcrown", + "*1092_Item_PoisonedShiv*": "Poisoned Shiv", + "*1095_Item_NullwaveGauntlet*": "Nullwave Gauntlet", + "*1097_Item_Echo*": "Echo", + "*1105_Item_SlumberingHusk*": "Slumbering Husk" + } + + def pretty(self): + if self in self.items: + return self.items[self] + if self in self.item_ids: + return self.item_ids[self] + return self |
