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