Commit acb536fa authored by murtaugh's avatar murtaugh

argparse for makefile, urlparse for path separation

parent e84884ae
from aiohttp import web
import sys, os, asyncio
import sys, os, asyncio, json
from asyncio import create_subprocess_exec
from urllib.parse import unquote as urlunquote, quote as urlquote
from urllib.parse import urlparse, unquote as urlunquote, quote as urlquote
import argparse
"""
Todo: use proper http error responses for errors, see aiohttp/http_exceptions.py
"""
async def is_makeable (path, cwd=".", makefile="makefile"):
# print ("make_question {0} {1}".format(path, docroot))
# make --question return codes: 0 : file is up to date, 1 : file needs remaking, 2 : file is not makeable
rpath = os.path.relpath(path, cwd)
# print ("*make_question {0} {1} {2}".format(path, cwd, r))
p = await create_subprocess_exec("make", "--question", "-f", makefile, rpath, cwd = cwd)
# retcode 0=file is up to date, 1=file needs remaking, 2=file is not makeable
ret = await p.wait() == 1
print (f"is_makeable {ret}", file=sys.stderr)
# print (f"is_makeable {path}: {ret}", file=sys.stderr)
return ret
async def make (path, cwd=".", makefile="makefile"):
# print ("make_question {0} {1}".format(path, docroot))
# make --question return codes: 0 : file is up to date, 1 : file needs remaking, 2 : file is not makeable
rpath = os.path.relpath(path, cwd)
# print ("*make_question {0} {1} {2}".format(path, cwd, r))
p = await create_subprocess_exec("make", "-f", makefile, rpath, cwd = cwd)
ret = await p.wait() == 0
print (f"make {ret}", file=sys.stderr)
# print (f"make {path}: {ret}", file=sys.stderr)
return ret
async def do_route(request):
# return FileResponse(filepath, chunk_size=self._chunk_size)
path = urlunquote(request.rel_url.raw_path.lstrip("/"))
print ("do_route", path, file=sys.stderr)
if path == '':
path = '.'
if path and await is_makeable(path):
await make(path)
if os.path.exists(path):
if os.path.isdir(path):
return web.Response(text=directory_as_html(path, '', ''), content_type="text/html")
else:
return web.FileResponse(path, chunk_size=256*1024)
else:
return web.Response(text=f"404 on path {path}")
# Following web_urldispatcher.py#line=551
# try:
# ret = Response(text=self._directory_as_html(filepath),
# content_type="text/html")
# except PermissionError:
# raise HTTPForbidden()
# From aiohttp/web_urldispatcher.py
def directory_as_html(filepath, directory, prefix):
# returns directory's index as html
......@@ -85,8 +63,43 @@ def directory_as_html(filepath, directory, prefix):
return html
async def route_get (request):
# return FileResponse(filepath, chunk_size=self._chunk_size)
path = urlunquote(urlparse(request.rel_url.raw_path.lstrip("/")).path)
print ("route_get", path, file=sys.stderr)
if path == '':
path = '.'
if path and await is_makeable(path, makefile=request.app['makefile']):
await make(path, makefile=request.app['makefile'])
if os.path.exists(path):
if os.path.isdir(path):
return web.Response(text=directory_as_html(path, '', ''), content_type="text/html")
else:
return web.FileResponse(path, chunk_size=256*1024)
else:
return web.Response(text=f"404 on path {path}")
async def route_post (request):
""" write posted text value to file """
path = urlunquote(urlparse(request.rel_url.raw_path.lstrip("/")).path)
print ("route_post", path, file=sys.stderr)
if os.path.exists(path) and os.path.isfile(path):
data = await request.post()
if 'text' in data:
text = data['text']
# doing file io inline here is not strictly speaking very async ;)
with open(path, "w") as f:
f.write(text)
return web.Response(text=json.dumps({"response": "ok"}), content_type="application/json")
else:
return web.Response(text=f"no text")
else:
return web.Response(text=f"post not allowed on {path}")
def main ():
ap = argparse.ArgumentParser("make & serve")
ap.add_argument("--makefile", default="makefile")
args = ap.parse_args()
if sys.platform == 'win32':
# Folowing: https://docs.python.org/3/library/asyncio-subprocess.html
# On Windows, the default event loop is SelectorEventLoop which does not support subprocesses.
......@@ -94,8 +107,11 @@ def main ():
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
app = web.Application()
app.add_routes([web.get('/{make:.*}', do_route)])
app['makefile'] = args.makefile
app.add_routes([web.get('/{make:.*}', route_get)])
app.add_routes([web.post('/{make:.*}', route_post)])
web.run_app(app)
if __name__ == "__main__":
main()
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment