Compare commits

..

No commits in common. "134afe24f76931b163f2b885dc92ce9f53a77e87" and "f7e31d9387c163480b9c32bd7c183d87cc67104e" have entirely different histories.

9 changed files with 50 additions and 105 deletions

View file

@ -2,5 +2,3 @@ flake8 == 7.0.0
mypy == 1.9.0
pyinstaller == 6.3.0
watchdog == 4.0.0
typing_extensions >= 4.10.0; python_version < '3.11.0'

View file

@ -45,7 +45,7 @@ def get_csp(request: web.Request) -> str:
"img-src 'self'",
"object-src 'none'",
"frame-ancestors 'none'",
f"manifest-src 'self' https://{request.app['config'].domain}"
f"manifest-src 'self' https://{request.app.config.domain}"
]
return '; '.join(data) + ';'

View file

@ -13,13 +13,7 @@ from platformdirs import user_config_dir
from .misc import IS_DOCKER
if typing.TYPE_CHECKING:
from typing import Any
try:
from typing import Self
except ImportError:
from typing_extensions import Self
from typing import Any, Self
if platform.system() == 'Windows':

View file

@ -10,13 +10,7 @@ from ..misc import boolean
if typing.TYPE_CHECKING:
from bsql import Row
from collections.abc import Callable, Sequence
from typing import Any
try:
from typing import Self
except ImportError:
from typing_extensions import Self
from typing import Any, Self
THEMES = {

View file

@ -4,10 +4,9 @@ import subprocess
import sys
import time
from datetime import datetime, timedelta
from datetime import datetime
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Sequence
from . import __version__
from . import logger as logging
@ -48,24 +47,14 @@ def cli_install():
@cli.command('lint')
@click.argument('path', required = False, default = 'relay')
@click.option('--strict', '-s', is_flag = True, help = 'Enable strict mode for mypy')
@click.option('--watch', '-w', is_flag = True,
help = 'Automatically, re-run the linters on source change')
def cli_lint(path: str, strict: bool, watch: bool) -> None:
flake8 = [sys.executable, '-m', 'flake8', path]
mypy = [sys.executable, '-m', 'mypy', path]
def cli_lint(path: str, strict: bool) -> None:
cmd: list[str] = [sys.executable, '-m', 'mypy']
if strict:
mypy.append('--strict')
cmd.append('--strict')
if watch:
handle_run_watcher(mypy, flake8, wait = True)
return
click.echo('----- flake8 -----')
subprocess.run(flake8)
click.echo('\n\n----- mypy -----')
subprocess.run(mypy)
subprocess.run([*cmd, path], check = False)
subprocess.run([sys.executable, '-m', 'flake8', path])
@cli.command('build')
@ -102,17 +91,8 @@ def cli_build():
def cli_run(dev: bool):
print('Starting process watcher')
cmd = [sys.executable, '-m', 'relay', 'run']
if dev:
cmd.append('-d')
handle_run_watcher(cmd)
def handle_run_watcher(*commands: Sequence[str], wait: bool = False):
handler = WatchHandler(*commands, wait = wait)
handler.run_procs()
handler = WatchHandler(dev)
handler.run_proc()
watcher = Observer()
watcher.schedule(handler, str(SCRIPT), recursive=True)
@ -120,12 +100,13 @@ def handle_run_watcher(*commands: Sequence[str], wait: bool = False):
try:
while True:
time.sleep(1)
handler.proc.stdin.write(sys.stdin.read().encode('UTF-8')) # type: ignore
handler.proc.stdin.flush() # type: ignore
except KeyboardInterrupt:
pass
handler.kill_procs()
handler.kill_proc()
watcher.stop()
watcher.join()
@ -133,65 +114,61 @@ def handle_run_watcher(*commands: Sequence[str], wait: bool = False):
class WatchHandler(PatternMatchingEventHandler):
patterns = ['*.py']
cmd = [sys.executable, '-m', 'relay', 'run']
def __init__(self, *commands: Sequence[str], wait: bool = False):
def __init__(self, dev: bool):
PatternMatchingEventHandler.__init__(self)
self.commands: Sequence[Sequence[str]] = commands
self.wait: bool = wait
self.procs: list[subprocess.Popen] = []
self.last_restart: datetime = datetime.now()
self.dev: bool = dev
self.proc: subprocess.Popen | None = None
self.last_restart: datetime | None = None
def kill_procs(self):
for proc in self.procs:
if proc.poll() is not None:
continue
def kill_proc(self):
if not self.proc or self.proc.poll() is not None:
return
logging.info(f'Terminating process {proc.pid}')
proc.terminate()
sec = 0.0
logging.info(f'Terminating process {self.proc.pid}')
self.proc.terminate()
sec = 0.0
while proc.poll() is None:
time.sleep(0.1)
sec += 0.1
while self.proc.poll() is None:
time.sleep(0.1)
sec += 0.1
if sec >= 5:
logging.error('Failed to terminate. Killing process...')
proc.kill()
break
if sec >= 5:
logging.error('Failed to terminate. Killing process...')
self.proc.kill()
break
logging.info('Process terminated')
logging.info('Process terminated')
def run_procs(self, restart: bool = False):
if restart:
if datetime.now() - timedelta(seconds = 3) < self.last_restart:
def run_proc(self, restart=False):
timestamp = datetime.timestamp(datetime.now())
self.last_restart = timestamp if not self.last_restart else 0
if restart and self.proc.pid != '':
if timestamp - 3 < self.last_restart:
return
self.kill_procs()
self.kill_proc()
self.last_restart = datetime.now()
cmd = [*self.cmd, '-d'] if self.dev else self.cmd
if self.wait:
self.procs = []
self.proc = subprocess.Popen(cmd, stdin = subprocess.PIPE)
self.last_restart = timestamp
for cmd in self.commands:
logging.info('Running command: %s', ' '.join(cmd))
subprocess.run(cmd)
else:
self.procs = list(subprocess.Popen(cmd) for cmd in self.commands)
pids = (str(proc.pid) for proc in self.procs)
logging.info('Started processes with PIDs: %s', ', '.join(pids))
logging.info('Started process with PID %i', self.proc.pid)
logging.info('Command: %s', ' '.join(cmd))
def on_any_event(self, event):
if event.event_type not in ['modified', 'created', 'deleted']:
return
self.run_procs(restart = True)
self.run_proc(restart = True)
if __name__ == '__main__':

View file

@ -9,13 +9,7 @@ from pathlib import Path
if typing.TYPE_CHECKING:
from collections.abc import Callable
from typing import Any
try:
from typing import Self
except ImportError:
from typing_extensions import Self
from typing import Any, Self
class LogLevel(IntEnum):

View file

@ -18,15 +18,9 @@ except ImportError:
from importlib_resources import files as pkgfiles # type: ignore
if typing.TYPE_CHECKING:
from typing import Any
from typing import Any, Self
from .application import Application
try:
from typing import Self
except ImportError:
from typing_extensions import Self
T = typing.TypeVar('T')
ResponseType = typing.TypedDict('ResponseType', {

View file

@ -16,19 +16,13 @@ if typing.TYPE_CHECKING:
from aiohttp.web import Request
from collections.abc import Callable, Generator, Sequence, Mapping
from bsql import Database
from typing import Any
from typing import Any, Self
from ..application import Application
from ..cache import Cache
from ..config import Config
from ..http_client import HttpClient
from ..template import Template
try:
from typing import Self
except ImportError:
from typing_extensions import Self
VIEWS: list[tuple[str, type[View]]] = []

View file

@ -1,4 +1,4 @@
activitypub-utils == 0.2.1
activitypub-utils == 0.2.0
aiohttp >= 3.9.1
aiohttp-swagger[performance] == 1.0.16
argon2-cffi == 23.1.0