kopia lustrzana https://github.com/c9/core
98 wiersze
3.7 KiB
Python
Executable File
98 wiersze
3.7 KiB
Python
Executable File
import argparse
|
|
import jedi
|
|
import json
|
|
import sys
|
|
import os
|
|
try: # python 2
|
|
import urlparse
|
|
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
|
except: # python 3
|
|
import urllib.parse as urlparse
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
|
def main(args):
|
|
if args.mode != "daemon":
|
|
print(run(sys.stdin.read(), args.__dict__))
|
|
return
|
|
|
|
jedi.preload_module("os", "sys", "math")
|
|
try:
|
|
server = HTTPServer(("localhost", int(args.port)), Daemon)
|
|
except:
|
|
sys.stderr.write("Daemon unable to listen at :%s\n" % args.port)
|
|
sys.exit(98)
|
|
sys.stderr.write("Daemon " + "listening at :%s\n" % args.port) # concat strings to avoid matching this string in the client
|
|
server.serve_forever()
|
|
|
|
def run(source, args):
|
|
script = jedi.Script(source, int(args.get("row")), int(args.get("column")), args.get("path"))
|
|
try:
|
|
result = getattr(script, args.get("mode"))()
|
|
except:
|
|
result = []
|
|
return json.dumps(result, default=to_json(args.get("mode"), args.get("nodoc")))
|
|
|
|
class Daemon(BaseHTTPRequestHandler):
|
|
def do_POST(self):
|
|
query = urlparse.urlparse(self.path).query
|
|
args = urlparse.parse_qsl(query)
|
|
|
|
length = int(self.headers.get("content-length", 0))
|
|
source = self.rfile.read(length)
|
|
|
|
self.send_response(200)
|
|
self.end_headers()
|
|
self.wfile.write(run(source, dict(args)).encode("utf8"))
|
|
|
|
def log_message(self, format, *args):
|
|
return # log silently
|
|
|
|
def to_json(mode, nodoc):
|
|
include_pos = mode == "goto_definitions"
|
|
def to_json(c):
|
|
try:
|
|
paramList = { p.description for p in c.params }
|
|
params = ", ".join([p for p in paramList if p != None and p != "self"])
|
|
except:
|
|
params = ""
|
|
return remove_nulls({
|
|
"name": c.name + ("(" + params + ")" if c.type == "function" else ""),
|
|
"replaceText": c.name + "(^^)" if c.type == "function" else None,
|
|
"row": c.line if c.line and include_pos else None,
|
|
"column": c.column if c.column and include_pos else None,
|
|
"path": "/" + c.module_path if c.module_path and include_pos else None,
|
|
"doc": abbrev(c.docstring()) if c.type != "module" # module docs dont work
|
|
and c.name[-2:] != "__" # skim on bandwidth
|
|
and not nodoc
|
|
else None,
|
|
"icon": {
|
|
"function": "method",
|
|
"module": "package",
|
|
"class": "property",
|
|
}.get(c.type, None),
|
|
})
|
|
return to_json
|
|
|
|
def remove_nulls(d):
|
|
# iterate over list copy to avoid size change in Python 3
|
|
# http://stackoverflow.com/a/11941855/1797347
|
|
for key, value in list(d.items()):
|
|
if value is None:
|
|
del d[key]
|
|
elif isinstance(value, dict):
|
|
remove_nulls(value)
|
|
return d
|
|
|
|
def abbrev(s):
|
|
return s if len(s) < 2500 else s[:2500] + "..."
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Run jedi functions as a daemon or via stdin")
|
|
parser.add_argument("mode", help="Mode of operation", choices=["daemon", "completions", "goto_definitions", "goto_assignments"])
|
|
parser.add_argument("--row", type=int, help="The row to read from")
|
|
parser.add_argument("--column", type=int, help="The column to read from")
|
|
parser.add_argument("--path", help="The path of the script")
|
|
parser.add_argument("--port", type=int, help="The port for the daemon to listen on")
|
|
parser.add_argument("--nodoc", help="Don't include docstrings in output")
|
|
args = parser.parse_args()
|
|
main(args) |