Created
August 14, 2012 15:46
-
-
Save sbp/3350409 to your computer and use it in GitHub Desktop.
Services sketch, intended for a phenny-like meta-service
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# remote python execution | |
# wolfram alpha service | |
# remote services? | |
import re, urllib.request, urllib.parse, traceback | |
from html.entities import name2codepoint | |
def error(who, message): | |
output = {"who": who, "message": message} | |
stack = traceback.extract_stack() | |
caller = stack[-2] | |
output["caller"] = caller[0] + ":" + str(caller[1]) | |
return output | |
def web_get(url, data=None, headers=None): | |
output = {} | |
if data is not None: | |
data = urllib.parse.urlencode(data) | |
url = "?".join((url, data)) | |
if headers is None: | |
headers = {} | |
if not "User-Agent" in headers: | |
headers["User-Agent"] = "Mozilla/5.0 (Services)" | |
output["url"] = url | |
request = urllib.request.Request(url, headers=headers) | |
try: response = urllib.request.urlopen(request) | |
except HTTPError as e: | |
output["error"] = error("Server (%s)" % url, "HTTP Error %s" % e.code) | |
except URLError as e: | |
output["error"] = error("Network", "Reason given: %s" % e.reason) | |
else: | |
octets = response.read() | |
response.close() | |
output["octets"] = octets | |
return output | |
web = type("Web", (object,), {"get": web_get}) | |
del web_get | |
services = {} | |
def decode_entities(text): | |
def entity(match): | |
name = match.group(1).lower() | |
if name.startswith("#x"): | |
return chr(int(name[2:], 16)) | |
elif name.startswith("#"): | |
return chr(int(name[1:])) | |
elif name in name2codepoint: | |
return name2codepoint[name] | |
return '[' + value + ']' | |
return re.compile(r'&([^;\s]+);').sub(entity, text) | |
def service(name): | |
def wrapper(service_function): | |
def wrapped_service(input): | |
# try: | |
output = service_function(input, {}) | |
# except Exception as e: | |
# output = {"error": str(e)} | |
return output | |
services[name] = wrapped_service | |
return wrapper | |
@service("Google calculator") | |
def _(input, output): | |
""" | |
"expression": "1 + 2" | |
=> | |
'url': 'http://www.google.com/ig/calculator?q=1+%2B+2', | |
'expression': '1 + 2', | |
'expression_substituted': '1 + 2', | |
'response': "'3'" | |
""" | |
substitutions = { | |
"ϕ": "phi", | |
"π": "pi" | |
} | |
expression = input["expression"] | |
output["expression"] = expression | |
for a, b in substitutions.items(): | |
expression = expression.replace(a, b) | |
output["expression_substituted"] = expression | |
calculator = "http://www.google.com/ig/calculator" | |
response = web.get(calculator, {"q": expression}) | |
output["url"] = response["url"] | |
if "error" in response: | |
output["error"] = response["error"] | |
return output | |
text = response["octets"].decode("utf-8") | |
output["text"] = text | |
def parse(text): | |
text = text.strip("{}") | |
r_entry = re.compile(r"(\w+):\s*\"([^\"]*)\",?\s*") | |
while text: | |
m = r_entry.match(text) | |
if not m: break | |
yield m.groups() | |
text = text[m.end():] | |
fields = dict(parse(text)) | |
output["google_left"] = fields.get("lhs") | |
output["google_right"] = fields.get("rhs") | |
if fields.get("error"): | |
output["error"] = error("Google", "The web service probably considers the input malformed") | |
return output | |
right = fields.get("rhs", "") | |
if right: | |
right = right.encode("iso-8859-1") | |
right = right.decode("unicode-escape") | |
substitutions = { | |
"<sup>": "^(", | |
"</sup>": ")", | |
"\xA0": "," # nbsp | |
} | |
for a, b in substitutions.items(): | |
right = right.replace(a, b) | |
right = decode_entities(right) | |
output["response"] = right | |
else: output["error"] = error("Google", "The response had no 'rhs' field. The input may be malformed") | |
return output | |
del _ | |
print(services["Google calculator"]({"expression": "(5 * 2 km/sec**2) in miles/hr**2\""})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment