chore: rename project coven → hack-house ⛧
Rebrand the Rust client crate (coven/ → hh/, package+binary "hack-house"), README, CLI strings, and branch (coven → hack-house). Gitea repo renamed cmd-chat → hack-house to match. Crypto/server logic unchanged; selftest + golden-vector test still green, binary is now `hack-house`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
from .meta import TouchUpMeta
|
||||
from .service import TouchUp
|
||||
|
||||
|
||||
__all__ = (
|
||||
"TouchUp",
|
||||
"TouchUpMeta",
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
from sanic.base.meta import SanicMeta
|
||||
from sanic.exceptions import SanicException
|
||||
|
||||
from .service import TouchUp
|
||||
|
||||
|
||||
class TouchUpMeta(SanicMeta):
|
||||
def __new__(cls, name, bases, attrs, **kwargs):
|
||||
gen_class = super().__new__(cls, name, bases, attrs, **kwargs)
|
||||
|
||||
methods = attrs.get("__touchup__")
|
||||
attrs["__touched__"] = False
|
||||
if methods:
|
||||
for method in methods:
|
||||
if method not in attrs:
|
||||
raise SanicException(
|
||||
"Cannot perform touchup on non-existent method: "
|
||||
f"{name}.{method}"
|
||||
)
|
||||
TouchUp.register(gen_class, method)
|
||||
|
||||
return gen_class
|
||||
@@ -0,0 +1,6 @@
|
||||
from .altsvc import AltSvcCheck # noqa
|
||||
from .base import BaseScheme
|
||||
from .ode import OptionalDispatchEvent # noqa
|
||||
|
||||
|
||||
__all__ = ("BaseScheme",)
|
||||
@@ -0,0 +1,56 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from ast import Assign, Constant, NodeTransformer, Subscript
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from sanic.http.constants import HTTP
|
||||
|
||||
from .base import BaseScheme
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sanic import Sanic
|
||||
|
||||
|
||||
class AltSvcCheck(BaseScheme):
|
||||
ident = "ALTSVC"
|
||||
|
||||
def visitors(self) -> list[NodeTransformer]:
|
||||
return [RemoveAltSvc(self.app, self.app.state.verbosity)]
|
||||
|
||||
|
||||
class RemoveAltSvc(NodeTransformer):
|
||||
def __init__(self, app: Sanic, verbosity: int = 0) -> None:
|
||||
self._app = app
|
||||
self._verbosity = verbosity
|
||||
self._versions = {
|
||||
info.settings["version"] for info in app.state.server_info
|
||||
}
|
||||
|
||||
def visit_Assign(self, node: Assign) -> Any:
|
||||
if any(self._matches(target) for target in node.targets):
|
||||
if self._should_remove():
|
||||
return None
|
||||
assert isinstance(node.value, Constant)
|
||||
node.value.value = self.value()
|
||||
return node
|
||||
|
||||
def _should_remove(self) -> bool:
|
||||
return len(self._versions) == 1
|
||||
|
||||
@staticmethod
|
||||
def _matches(node) -> bool:
|
||||
return (
|
||||
isinstance(node, Subscript)
|
||||
and isinstance(node.slice, Constant)
|
||||
and node.slice.value == "alt-svc"
|
||||
)
|
||||
|
||||
def value(self):
|
||||
values = []
|
||||
for info in self._app.state.server_info:
|
||||
port = info.settings["port"]
|
||||
version = info.settings["version"]
|
||||
if version is HTTP.VERSION_3:
|
||||
values.append(f'h3=":{port}"')
|
||||
return ", ".join(values)
|
||||
@@ -0,0 +1,37 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from ast import NodeTransformer, parse
|
||||
from inspect import getsource
|
||||
from textwrap import dedent
|
||||
from typing import Any
|
||||
|
||||
|
||||
class BaseScheme(ABC):
|
||||
ident: str
|
||||
_registry: set[type] = set()
|
||||
|
||||
def __init__(self, app) -> None:
|
||||
self.app = app
|
||||
|
||||
@abstractmethod
|
||||
def visitors(self) -> list[NodeTransformer]: ...
|
||||
|
||||
def __init_subclass__(cls):
|
||||
BaseScheme._registry.add(cls)
|
||||
|
||||
def __call__(self):
|
||||
return self.visitors()
|
||||
|
||||
@classmethod
|
||||
def build(cls, method, module_globals, app):
|
||||
raw_source = getsource(method)
|
||||
src = dedent(raw_source)
|
||||
node = parse(src)
|
||||
|
||||
for scheme in cls._registry:
|
||||
for visitor in scheme(app)():
|
||||
node = visitor.visit(node)
|
||||
|
||||
compiled_src = compile(node, method.__name__, "exec")
|
||||
exec_locals: dict[str, Any] = {}
|
||||
exec(compiled_src, module_globals, exec_locals) # nosec
|
||||
return exec_locals[method.__name__]
|
||||
@@ -0,0 +1,90 @@
|
||||
from ast import Attribute, Await, Expr, NodeTransformer
|
||||
from typing import Any
|
||||
|
||||
from sanic.log import logger
|
||||
|
||||
from .base import BaseScheme
|
||||
|
||||
|
||||
class OptionalDispatchEvent(BaseScheme):
|
||||
ident = "ODE"
|
||||
SYNC_SIGNAL_NAMESPACES = "http."
|
||||
|
||||
def __init__(self, app) -> None:
|
||||
super().__init__(app)
|
||||
|
||||
self._sync_events()
|
||||
self._registered_events = [
|
||||
signal.name for signal in app.signal_router.routes
|
||||
]
|
||||
|
||||
def visitors(self) -> list[NodeTransformer]:
|
||||
return [RemoveDispatch(self._registered_events)]
|
||||
|
||||
def _sync_events(self):
|
||||
all_events = set()
|
||||
app_events = {}
|
||||
for app in self.app.__class__._app_registry.values():
|
||||
if app.state.server_info:
|
||||
app_events[app] = {
|
||||
signal.name for signal in app.signal_router.routes
|
||||
}
|
||||
all_events.update(app_events[app])
|
||||
|
||||
for app, events in app_events.items():
|
||||
missing = {
|
||||
x
|
||||
for x in all_events.difference(events)
|
||||
if any(x.startswith(y) for y in self.SYNC_SIGNAL_NAMESPACES)
|
||||
}
|
||||
if missing:
|
||||
was_finalized = app.signal_router.finalized
|
||||
if was_finalized: # no cov
|
||||
app.signal_router.reset()
|
||||
for event in missing:
|
||||
app.signal(event)(self.noop)
|
||||
if was_finalized: # no cov
|
||||
app.signal_router.finalize()
|
||||
|
||||
@staticmethod
|
||||
async def noop(**_): # no cov
|
||||
...
|
||||
|
||||
|
||||
class RemoveDispatch(NodeTransformer):
|
||||
def __init__(self, registered_events) -> None:
|
||||
self._registered_events = registered_events
|
||||
|
||||
def visit_Expr(self, node: Expr) -> Any:
|
||||
call = node.value
|
||||
if isinstance(call, Await):
|
||||
call = call.value
|
||||
|
||||
func = getattr(call, "func", None)
|
||||
args = getattr(call, "args", None)
|
||||
if not func or not args:
|
||||
return node
|
||||
|
||||
if isinstance(func, Attribute) and func.attr == "dispatch":
|
||||
event = args[0]
|
||||
if event_name := getattr(event, "value", None):
|
||||
if self._not_registered(event_name):
|
||||
logger.debug(
|
||||
f"Disabling event: {event_name}",
|
||||
extra={"verbosity": 2},
|
||||
)
|
||||
return None
|
||||
return node
|
||||
|
||||
def _not_registered(self, event_name):
|
||||
dynamic = []
|
||||
for event in self._registered_events:
|
||||
if event.endswith(">"):
|
||||
namespace_concern, _ = event.rsplit(".", 1)
|
||||
dynamic.append(namespace_concern)
|
||||
|
||||
namespace_concern, _ = event_name.rsplit(".", 1)
|
||||
return (
|
||||
event_name not in self._registered_events
|
||||
and namespace_concern not in dynamic
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
from inspect import getmembers, getmodule
|
||||
|
||||
from .schemes import BaseScheme
|
||||
|
||||
|
||||
class TouchUp:
|
||||
_registry: set[tuple[type, str]] = set()
|
||||
|
||||
@classmethod
|
||||
def run(cls, app):
|
||||
for target, method_name in cls._registry:
|
||||
method = getattr(target, method_name)
|
||||
|
||||
if app.test_mode:
|
||||
placeholder = f"_{method_name}"
|
||||
if hasattr(target, placeholder):
|
||||
method = getattr(target, placeholder)
|
||||
else:
|
||||
setattr(target, placeholder, method)
|
||||
|
||||
module = getmodule(target)
|
||||
module_globals = dict(getmembers(module))
|
||||
modified = BaseScheme.build(method, module_globals, app)
|
||||
setattr(target, method_name, modified)
|
||||
|
||||
target.__touched__ = True
|
||||
|
||||
@classmethod
|
||||
def register(cls, target, method_name):
|
||||
cls._registry.add((target, method_name))
|
||||
Reference in New Issue
Block a user