Source

misc / pycall

Nick Coghlan 979b96a 





















































#!/usr/bin/env python
import json
import sys
try:
    import builtins
except ImportError:
    import __builtin__ as builtins

def _getattr_or_import(name):
    # Inspired by zope.dottedname, we should
    # probably have this in importlib.util
    mod_name, sep, rest = name.partition(".")
    if not mod_name:
        raise ValueError("Relative imports are not supported")
    mod = None
    try:
        obj = globals()[mod_name]
    except KeyError:
        try:
            obj = getattr(builtins, mod_name)
        except AttributeError:
            mod = obj = __import__(mod_name)
    if rest:
        for part in rest.split("."):
            if not part:
                raise ValueError("The empty string is not a valid name fragment")
            try:
                obj = getattr(obj, part)
            except AttributeError:
                if obj is not mod:
                    raise
                mod_name = mod_name + "." + part
                __import__(mod_name)
                mod = obj = getattr(mod, part)
    return obj
    

def json_call(name, input_stream=None, output_stream=None):
    if input_stream is None:
        input_stream = sys.stdin
    if output_stream is None:
        output_stream = sys.stdout
    f = _getattr_or_import(name)
    input_data = json.load(input_stream)
    if isinstance(input_data, dict):
        output_data = f(**input_data)
    elif isinstance(input_data, list):
        output_data = f(*input_data)
    else:
        output_data = f(input_data)
    json.dump(output_data, output_stream)
    return output_data

if __name__ == "__main__":
    json_call(sys.argv[1])