update: tweaks on APIs

This commit is contained in:
2026-07-10 15:22:59 +08:00
parent 534778c562
commit a48a850db0
6 changed files with 35 additions and 30 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "common"
description = "Commonly reusable code"
version = "0.1.17"
version = "0.1.18"
requires-python = ">=3.13"
authors = [
{ name="BreakerBear", email="breakerbear@autistic.men" },
+16 -8
View File
@@ -21,14 +21,17 @@ class ActionFlow:
self.actions: list[type[Action]] = []
self.on: list[bool] = []
def queue(self, action: type[Action]):
name = action.__name__
index = self.indices.get(name)
assert index is not None, "Action '%s' is not registered" % name
def __getitem__(self, key):
index = self.indices[key]
state = self.on[index]
if self.on[index]: raise Unavailable(name)
if self.on[index] is None: raise NotAllowed(name)
self.on[index] = bool(self.actions[index].prepare())
def inner(*args, **kwargs):
self.on[index] = self.actions[index].prepare(*args, **kwargs)
return self.on[index]
if state: raise Unavailable(key)
if state is None: raise NotAllowed(key)
return inner
def react(self, *stage: type[Action]):
for Props in stage:
@@ -39,7 +42,7 @@ class ActionFlow:
for index in self.indices.values():
if (self.on[index]):
self.on[index] = None
self.on[index] = bool(self.actions[index].perform())
self.on[index] = self.actions[index].perform()
def index(self, action: type[Action]) -> int:
name = action.__name__
@@ -51,9 +54,14 @@ class ActionFlow:
index = self.index(action)
self.on[index] = False if value else None
def stage(self, *preset: type[Action]):
for Props in preset:
self.append(Props)
def append(self, action: type[Action]):
name = action.__name__
index = len(self.indices)
assert name not in self.indices, "Action '%s' is already registered" % name
self.indices[name] = index
self.actions.insert(index, action)
+4 -7
View File
@@ -20,19 +20,16 @@ export const LogRecord = {
};
export const Rpc2 = {
notify: async (method, ...args) => {
let request = { method };
if (args.length > 0) request.params = args;
notify: async (method, options) => {
let request = { ...options, method };
let body = JSON.stringify(request);
if (!navigator.sendBeacon('/', body)) {
throw new Error('Data transmission failed');
}
},
invoke: async (method, ...args) => {
invoke: async (method, options) => {
let id = Math.floor(Math.random() * 1000000000);
let request = { method, id };
if (args.length > 0) request.params = args;
let request = { ...options, method, id };
let body = JSON.stringify(request);
let response = await fetch('/', { method: 'POST', body });
let json = await response.json();
+1 -1
View File
@@ -41,7 +41,7 @@ class Request[T]:
if args.keys() != set(argnames): raise self.ParamsError(args)
return handler(**args)
raise self.Invalid('Arguments unacceptable')
raise self.Invalid(type(args))
class Response[T]:
def __init__(self, id: str|int|None, inner: T):
+2 -2
View File
@@ -3,7 +3,7 @@ from common.utils.selenium import (
sleep,
locate,
click,
short,
identity,
setup,
)
@@ -12,6 +12,6 @@ __all__ = [
'sleep',
'locate',
'click',
'short',
'identity',
'setup',
]
+8 -8
View File
@@ -10,7 +10,7 @@ from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import StaleElementReferenceException, NoAlertPresentException, TimeoutException
driver: WebDriver|None = None
identity, parameters = None, dict()
unique, parameters = None, dict()
def until(condition: typing.Callable[[WebDriver], bool], watch=True):
try:
@@ -50,10 +50,10 @@ def click(selector: str|WebElement, wait=True, condition=False):
error = False
element = locate(selector, wait, predicate) if isinstance(selector, str) else selector
counter = lambda: int(element.get_attribute(identity) or '0')
counter = lambda: int(element.get_attribute(unique) or '0')
value = counter()
driver.execute_script("window.__%s__ = () => { arguments[0].setAttribute('%s', arguments[1] + 1) };" % ((identity,) * 2), element, value)
driver.execute_script("arguments[0].addEventListener('click', __%s__);" % identity, element)
driver.execute_script("window.__%s__ = () => { arguments[0].setAttribute('%s', arguments[1] + 1) };" % ((unique,) * 2), element, value)
driver.execute_script("arguments[0].addEventListener('click', __%s__);" % unique, element)
for _ in range(parameters.get('attempts', 0)):
try:
@@ -70,14 +70,14 @@ def click(selector: str|WebElement, wait=True, condition=False):
except TimeoutException: continue
except: break
try: driver.execute_script("arguments[0].removeEventListener('click', __%s__);" % identity, element)
try: driver.execute_script("arguments[0].removeEventListener('click', __%s__);" % unique, element)
except: pass
def short():
def identity():
return ''.join(random.choices(string.digits + string.ascii_uppercase + string.ascii_lowercase, k=8))
def setup(a: WebDriver, b: dict):
global identity, driver
identity = short()
global unique, driver
unique = identity()
driver = a
parameters.update(b)