# vim: et sw=4 sts=4 | |
from flask import Flask, escape, redirect | |
app = Flask(__name__) | |
import posixpath | |
import requests | |
from sphinx.util.inventory import InventoryFile | |
from werkzeug.contrib.iterio import IterIO | |
INVENTORIES = { | |
'3': [ | |
('https://docs.python.org/3/', 'https://docs.python.org/3/objects.inv'), | |
], | |
'2': [ | |
('https://docs.python.org/2/', 'https://docs.python.org/2/objects.inv'), | |
], | |
} | |
m = {} | |
for mapping, l in INVENTORIES.items(): | |
d = {} | |
for uri, inv in l: | |
print(f"Getting a {inv!r}") | |
r = requests.get(inv, stream=True) | |
s = IterIO(r.iter_content()) | |
inv = InventoryFile.load(s, uri, posixpath.join) | |
# medium hack: prefer classes and then functions and then other stuff. | |
# when shadowing happens (e.g. 'dict', 'len') this seems to be the order we want | |
types = list(inv.keys()) | |
types.remove('py:class') | |
types.remove('py:function') | |
types = ['py:class', 'py:function'] + types | |
for typ in types: | |
entries = inv[typ] | |
x = {k.casefold(): v for k, v in entries.items()} | |
x.update(d) | |
d = x | |
# this is another loop so shortened names don't ever take priority over full ones | |
for typ in types: | |
entries = inv[typ] | |
x = {k.split('.')[-1].casefold(): v for k, v in entries.items()} | |
x.update(d) | |
d = x | |
m[mapping] = d | |
@app.route("/<string:mapping>/<string:obj_id>") | |
def bounce(mapping, obj_id): | |
try: | |
index = m[mapping] | |
except KeyError: | |
return f"I don't know about {escape(mapping)}.", 404 | |
try: | |
projname, version, location, _ = index[obj_id.casefold()] | |
except KeyError: | |
return f"I don't know about {escape(obj_id)} in {escape(mapping)}", 404 | |
return redirect(location), 307 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment