Files
ToastyFS/app/app.py
T
2025-11-23 11:33:30 +01:00

129 lines
3.6 KiB
Python

import asyncio
import logging
from pathlib import Path
from aiohttp import (
ClientSession,
TraceConfig,
TraceRequestEndParams,
TraceRequestStartParams,
)
from watchfiles import Change, awatch
local_root = "."
remote_root = f"http://127.0.0.1:8090/"
logging.basicConfig(
level=logging.INFO,
format="%(message)s", # No timestamp prefix for curl-like output
)
logger = logging.getLogger(__name__)
async def on_request_start(session, context, params: TraceRequestStartParams):
logger.info(f"> {params.method} {params.url.path_qs} HTTP/1.1")
logger.info(f"> Host: {params.url.host}")
for name, value in params.headers.items():
logger.info(f"> {name}: {value}")
logger.info(">")
async def on_request_end(session, context, params: TraceRequestEndParams):
response = params.response
logger.info(f"< HTTP/1.1 {response.status} {response.reason}")
for name, value in response.headers.items():
logger.info(f"< {name}: {value}")
logger.info("<")
# Optionally log response body
# body = await response.text()
# if body:
# logger.info(body)
trace_config = TraceConfig()
trace_config.on_request_start.append(on_request_start)
trace_config.on_request_end.append(on_request_end)
async def main():
async for changes in awatch(local_root):
for change_type, filepath in changes:
await process_change(change_type, filepath)
async def process_change(change_type, filepath):
if change_type == Change.added:
await process_change_added(filepath)
elif change_type == Change.modified:
await process_change_modified(filepath)
elif change_type == Change.deleted:
await process_change_deleted(filepath)
else:
raise "Unexpected change type"
def make_relative_path(root, target):
root = Path(root).resolve()
target = Path(target).resolve()
return str(target.relative_to(root))
def endpoint_from_local_path(local_target):
relative_path = make_relative_path(local_root, local_target)
relative_path = relative_path.replace("\\", "/")
remote_target = remote_root + relative_path
assert remote_target[-1] != "/"
if Path(local_target).is_dir():
remote_target += "/"
return remote_target
async def process_change_added(local_target):
async with ClientSession(trace_configs=[trace_config]) as session:
# Determine the endpoint the file should be
# uploaded to.
remote_target = endpoint_from_local_path(local_target)
# Read its contents
with open(local_target, "rb") as f:
data = f.read()
# Upload
async with session.put(remote_target, data=data) as response:
pass # TODO
async def process_change_modified(local_target):
async with ClientSession(trace_configs=[trace_config]) as session:
# Determine the endpoint the file should be
# uploaded to.
remote_target = endpoint_from_local_path(local_target)
# Read its contents
with open(local_target, "rb") as f:
data = f.read()
# Upload
async with session.put(remote_target, data=data) as response:
pass # TODO
async def process_change_deleted(local_target):
async with ClientSession(trace_configs=[trace_config]) as session:
# Determine the endpoint that should be deleted
remote_target = endpoint_from_local_path(local_target)
# Delete
async with session.delete(remote_target) as response:
pass # TODO
try:
asyncio.run(main())
except KeyboardInterrupt:
pass