Source code for diggrtoolbox.unified_api.diggr_api
import requests
from collections import OrderedDict
from requests.compat import urljoin
MOBYGAMES = "mobygames"
GAMEFAQS = "gamefaqs"
MEDIAARTDB = "mediaartdb"
[docs]class DiggrAPI:
"""
This class provides easy access to the diggr unified API.
On initialization you have to provide the address of your desired unified API endpoint.
You can now set the dataset and filters, which are persistent until reset.
This allows you to iterate over a dataset without having to apply a filter each time.
The get() method will do some magic to determine the correct way of creating the directory
string depending on the content and dataset selected. I.e. prepend a "/slug", if the identifier
is a slug and not an id, or replace slashes in gamefaqs ids.
:Example:
>>> d = DiggrAPI("http://localhost:6660").dataset("mobygames").filter("companies")
>>> result = d.item("1").get()
For the sake of readability you may want to execute the query immediately after the item is set.
>>> d = DiggrAPI("http://localhost:6660", get_on_item=True)
>>> d.dataset("mobygames").filter("companies")
>>> results = []
>>> for i in range(10):
>>> results.append(d.item(i))
"""
DATASETS = (MOBYGAMES, GAMEFAQS, MEDIAARTDB)
FILTERS = ("companies", "links", "cluster")
def __init__(self, base_url, get_on_item=False, raw=False):
self.base_url = base_url
self.get_on_item = get_on_item
self.raw = raw
self.session = requests.Session()
self.query = OrderedDict([
("dataset", None),
("item", ""),
("filter", ""),
])
[docs] def get(self):
"""
Runs the query and returns the result.
"""
result = self.session.get(urljoin(self.base_url, self.directory))
if result.ok:
data = result.json()
if self.raw:
return data
if not self.query["item"]:
return data["ids"]
else:
if self.query["filter"] == "links":
return data["links"]
else:
return data.get("entry", None)
else:
raise RuntimeError("Malformed Request")
[docs] def dataset(self, dataset):
"""
Selects a dataset.
"""
if dataset not in self.DATASETS:
raise ValueError("{dataset} must be in {d for d in self.DATASETS}")
self.query["dataset"] = dataset
return self
[docs] def item(self, id_or_slug):
"""
Selects an item, can be given a numeric id or a slug.
Returns self or the result of the query if get_on_item is set.
"""
if isinstance(id_or_slug, int):
self.query["item"] = str(id_or_slug)
elif id_or_slug.isdigit():
self.query["item"] = id_or_slug
else:
if self.query["dataset"] == MOBYGAMES:
self.query["item"] = f"slug/{id_or_slug}"
if self.query["dataset"] == GAMEFAQS:
self.query["item"] = id_or_slug.replace("/", "__")
else:
self.query["item"] = id_or_slug
if self.get_on_item:
return self.get()
else:
return self
[docs] def filter(self, filterstring):
"""
Applies a filter. Must be in self.FILTERS.
"""
if filterstring not in self.FILTERS:
raise ValueError("{dataset} must be in {d for d in self.DATASETS}")
self.query["filter"] = filterstring
return self
@property
def directory(self):
"""
Returns the directory string from self.query.
Raises ValueError if no dataset or item is set.
"""
if not self.query["dataset"]:
raise ValueError("At least a dataset must be selected")
if not self.query["filter"]:
if self.query["item"]:
return "{}/{}".format(self.query["dataset"], self.query["item"])
else:
return self.query["dataset"]
else:
if not self.query["item"]:
raise ValueError("You cannot set a filter without selecting an item")
else:
return "{}/{}/{}".format(*self.query.values())