Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoSign in
Socket

wwwpy

Package Overview
Dependencies
Maintainers
1
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wwwpy - pypi Package Compare versions

Comparing version
0.1.81
to
0.1.82
+86
src/wwwpy/remote/hotkeylib.py
from __future__ import annotations
import asyncio
import logging
from typing import Callable, Optional, Dict, Union, Awaitable
import js
from js import console, window, EventTarget, KeyboardEvent
from pyodide.ffi import create_proxy, to_js
logger = logging.getLogger(__name__)
HotkeyHandler = Union[Callable[['KeyboardEvent'], Optional[bool]], Callable[['KeyboardEvent'], Awaitable[None]]]
class Hotkey:
def __init__(self, element: EventTarget):
self.element = element
self.handlers: Dict[str, HotkeyHandler] = dict()
self.debug = False
self._proxy = create_proxy(self._detect_hotkey)
self.install()
def install(self):
self.element.addEventListener('keydown', self._proxy, False)
def uninstall(self):
self.element.removeEventListener('keydown', self._proxy, False)
# todo this should be called 'set'
def add(self, hotkey: str, handler: HotkeyHandler) -> 'Hotkey':
"""
Registers a hotkey with its corresponding handler.
Adds a key-handler pair to the handlers dictionary, associating the hotkey with
the given handler function or callable.
Parameters
----------
hotkey : str
The key combination that will trigger the handler. Examples: 'CTRL-S', 'Escape', 'META-Backspace'
, 'CTRL-SHIFT-ALT-META-F1', this last example serves to know the order of the modifiers.
handler : HotkeyHandler
A function or callable that will be called when the hotkey is pressed.
"""
self.handlers[hotkey] = handler
return self
@classmethod
def keyboard_event(cls, e):
return js.eval('(e) => e instanceof KeyboardEvent ')(e)
def _detect_hotkey(self, e):
if not self.keyboard_event(e):
return
key = ''
if e.ctrlKey: key += 'CTRL-'
if e.shiftKey: key += 'SHIFT-'
if e.altKey: key += 'ALT-'
if e.metaKey: key += 'META-'
upc: str = e.key
if len(upc) == 1: upc = upc.upper()
key += upc
if self.debug:
console.log(key, to_js(e))
logger.debug(f'key = `{key}`')
handle = self.handlers.get(key, None)
if handle is None:
return
e.hotkey = key # add the hotkey attribute to the event
if asyncio.iscoroutinefunction(handle):
e.preventDefault()
e.stopPropagation()
asyncio.create_task(handle(e))
return
res = handle(e)
if not res:
return
console.log(f'prevent default for {key}')
e.preventDefault()
e.stopPropagation()
+2
-2
Metadata-Version: 2.4
Name: wwwpy
Version: 0.1.81
Version: 0.1.82
Summary: Build Powerful Web Applications: Simple, Scalable, and Fully Customizable

@@ -228,3 +228,3 @@ Author-email: Simone Giacomelli <simone.giacomelli@gmail.com>

Requires-Dist: tornado==6.4.2
Requires-Dist: watchdog==4.0.2
Requires-Dist: watchdog==6.0.0
Requires-Dist: webtypy

@@ -231,0 +231,0 @@ Provides-Extra: test

# https://packaging.python.org/en/latest/tutorials/packaging-projects/
[project]
name = "wwwpy"
version = "0.1.81"
version = "0.1.82"

@@ -14,3 +14,3 @@ # todo

authors = [{ name = "Simone Giacomelli", email = "simone.giacomelli@gmail.com" }]
dependencies = ["tornado==6.4.2", "watchdog==4.0.2", "webtypy"]
dependencies = ["tornado==6.4.2", "watchdog==6.0.0", "webtypy"]
requires-python = ">=3.9"

@@ -17,0 +17,0 @@ keywords = ["wwwpy", "wasm", "pyodide", "web", "development", "dom", "html", "javascript"]

Metadata-Version: 2.4
Name: wwwpy
Version: 0.1.81
Version: 0.1.82
Summary: Build Powerful Web Applications: Simple, Scalable, and Fully Customizable

@@ -228,3 +228,3 @@ Author-email: Simone Giacomelli <simone.giacomelli@gmail.com>

Requires-Dist: tornado==6.4.2
Requires-Dist: watchdog==4.0.2
Requires-Dist: watchdog==6.0.0
Requires-Dist: webtypy

@@ -231,0 +231,0 @@ Provides-Extra: test

tornado==6.4.2
watchdog==4.0.2
watchdog==6.0.0
webtypy

@@ -4,0 +4,0 @@

@@ -132,2 +132,3 @@ LICENSE

src/wwwpy/remote/hotkey.py
src/wwwpy/remote/hotkeylib.py
src/wwwpy/remote/idbfs.py

@@ -134,0 +135,0 @@ src/wwwpy/remote/jslib.py

@@ -5,5 +5,7 @@ try:

__version__ = _build_meta.__version__
__banner__ = f'wwwpy v{__version__}'
except:
__version__ = 'unknown'
__banner__ = 'wwwpy version unknown'
__all__ = ['__version__']

@@ -1,3 +0,3 @@

__version__ = "0.1.81"
git_hash_short = "76bfe48"
git_hash = "76bfe48af6490bdfa59badd84f990eb6a29d9184"
__version__ = "0.1.82"
git_hash_short = "a26531e"
git_hash = "a26531eca4cdf1870bdc45098ee7dde970471ce5"

@@ -28,2 +28,10 @@ from __future__ import annotations

def remove_class_attribute(source_code: str, class_name: str, attr_name: str) -> str:
source_code_imp = ensure_imports(source_code)
module = cst.parse_module(source_code_imp)
transformer = _RemoveFieldFromClassTransformer(class_name, attr_name)
modified_tree = module.visit(transformer)
return modified_tree.code
def rename_class_attribute(source_code: str, class_name: str, old_attr_name: str, new_attr_name: str):

@@ -229,2 +237,27 @@ source_code_imp = ensure_imports(source_code)

class _RemoveFieldFromClassTransformer(cst.CSTTransformer):
def __init__(self, class_name, field_name):
super().__init__()
self.class_name = class_name
self.field_name = field_name
def leave_ClassDef(self, original_node, updated_node):
if original_node.name.value != self.class_name:
return original_node
new_body = []
for item in updated_node.body.body:
# Check if this is an annotated assignment with the target field name
if (isinstance(item, cst.SimpleStatementLine) and
isinstance(item.body[0], cst.AnnAssign) and
isinstance(item.body[0].target, cst.Name) and
item.body[0].target.value == self.field_name):
# Skip this item to remove it
continue
else:
new_body.append(item)
return updated_node.with_changes(body=updated_node.body.with_changes(body=new_body))
def add_method(source_code: str, class_name: str, method_name: str, method_args: str,

@@ -231,0 +264,0 @@ instructions: str = 'pass') -> str:

@@ -102,2 +102,7 @@ from __future__ import annotations

def __init__(self, element_path: ep.ElementPath, element_def: el.ElementDef):
self.element_path = element_path
self.element_def = element_def
self._init()
def _init(self):
self.attributes: ListMap[AttributeEditor] = ListMap(key_func=lambda attr: attr.definition.name)

@@ -108,4 +113,2 @@ """One AttributeEditor for each attribute defined in the ElementDef."""

self.element_path = element_path
self.element_def = element_def
self._fill_events()

@@ -196,2 +199,5 @@ self._fill_attrs()

def _data_name_set_value(self, attribute_editor: AttributeEditor, value: str | None = ''):
if value == '':
self._attribute_remove(attribute_editor)
return
old_value = attribute_editor.value

@@ -233,3 +239,10 @@ if self._node.content and old_value == self._node.content:

if attribute_editor.definition is _ad_data_name:
src = self.current_python_source()
src = code_edit.remove_class_attribute(src, self.element_path.class_name, attribute_editor.value)
self._write_source(src)
self._init()
# Create a translation table for the specified characters

@@ -236,0 +249,0 @@ escape_table = str.maketrans({

import dataclasses
import shutil
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Dict, Iterable, Union, Optional
from typing import List, Dict, Iterable, Optional
from wwwpy.common import tree
from wwwpy.common.filesystem.sync import Event
from dataclasses import dataclass, field

@@ -108,9 +108,12 @@

c = event.content
func = None
if isinstance(c, str):
path.write_text(c)
func = path.write_text
elif isinstance(c, bytes):
path.write_bytes(c)
func = path.write_bytes
else:
raise ValueError(f"Unsupported content type: {type(c)}")
path.parent.mkdir(parents=True, exist_ok=True)
func(c)

@@ -117,0 +120,0 @@ def _get_content(path: Path):

@@ -85,4 +85,4 @@ from __future__ import annotations

for f in b.body:
fqn = b.name + '.' + f.name
if isinstance(f, FunctionDef):
fqn = b.name + '.' + f.name
if len(f.args.args) > 1: # beyond self

@@ -89,0 +89,0 @@ args = ', ' + ', '.join([a.arg for a in f.args.args[1:]])

@@ -7,2 +7,4 @@ import base64

import re
import sys
import types
import typing

@@ -28,3 +30,4 @@ from dataclasses import is_dataclass

origin = typing.get_origin(cls)
if origin is typing.Union:
# if origin is typing.Union or origin is types.UnionType:
if _is_union_type(origin):
args = set(get_args(cls))

@@ -100,3 +103,4 @@ obj_type = type(obj)

origin = get_origin(cls)
if origin is typing.Union:
# if origin is typing.Union:
if _is_union_type(origin):
args = set(get_args(cls))

@@ -202,1 +206,12 @@ obj_type = _get_type_from_string(data[0])

raise ValueError(f"Expected object of type Result got {typ}")
def _is_union_type_3_10(origin):
return origin is typing.Union or origin is types.UnionType
def _is_union_type_3_9(origin):
return origin is typing.Union
_is_union_type = _is_union_type_3_10 if sys.version_info >= (3, 10) else _is_union_type_3_9

@@ -23,3 +23,4 @@ from __future__ import annotations

# print_tree('/wwwpy_bundle')
import wwwpy
console.log(wwwpy.__banner__)
await setup_websocket()

@@ -26,0 +27,0 @@ dm.set_active(dev_mode)

@@ -67,2 +67,3 @@ from __future__ import annotations

class ToolboxComponent(wpc.Component, tag_name='wwwpy-toolbox'):
_title: js.HTMLDivElement = wpc.element()
body: HTMLElement = wpc.element()

@@ -104,3 +105,3 @@ inputSearch: js.HTMLInputElement = wpc.element()

<wwwpy-window data-name='_window'>
<div slot='title' style='text-align: center'>wwwpy - toolbox</div>
<div slot='title' data-name="_title" style='text-align: center'></div>
<div style="text-align: center; padding: 8px">

@@ -115,2 +116,4 @@ <button data-name="_select_element_btn">Select element...</button>

"""
import wwwpy
self._title.innerText = f'toolbox - {wwwpy.__banner__}'

@@ -117,0 +120,0 @@ def connectedCallback(self):

@@ -7,8 +7,9 @@ import threading

from watchdog.events import FileSystemEvent
from wwwpy.common.filesystem.sync import new_tmp_path
from wwwpy.common.filesystem.sync.event import Event
from wwwpy.server.filesystem_sync.any_observer import AnyObserver
from wwwpy.server.filesystem_sync.debouncer import Debouncer
from wwwpy.server.filesystem_sync.debouncer_thread import DebouncerThread
from wwwpy.common.filesystem.sync.event import Event
from watchdog.events import FileSystemEvent

@@ -20,10 +21,8 @@

self._debouncer = Debouncer(window)
self.skip_synthetic = True
self.skip_opened = True
super().__init__(self._debouncer, callback)
def skip_open(event: FileSystemEvent):
if event.event_type == 'opened' and self.skip_opened:
if event.event_type == 'opened' or event.event_type == 'closed_no_write':
return
if event.is_synthetic and self.skip_synthetic:
if event.is_synthetic:
return

@@ -30,0 +29,0 @@