Python-to-JavaScript transpiler that enables Python 3 development in web browsers with full DOM integration and standard library support
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Timer functions and animation frame requests for time-based functionality and smooth animations in web applications. Provides Python interfaces to browser timing APIs.
Execute functions after delays or at regular intervals.
def set_timeout(func: Callable, interval: int, *args) -> int:
"""
Execute function after specified delay.
Args:
func: Function to execute
interval: Delay in milliseconds
*args: Arguments to pass to function
Returns:
Timer ID for cancellation
"""
def set_interval(func: Callable, interval: int, *args) -> int:
"""
Execute function repeatedly at specified interval.
Args:
func: Function to execute
interval: Interval in milliseconds
*args: Arguments to pass to function
Returns:
Timer ID for cancellation
"""
def clear_timeout(timer_id: int) -> None:
"""
Cancel scheduled timeout.
Args:
timer_id: Timer ID returned by set_timeout
"""
def clear_interval(timer_id: int) -> None:
"""
Cancel repeating interval.
Args:
timer_id: Timer ID returned by set_interval
"""Usage:
from browser.timer import set_timeout, set_interval, clear_timeout, clear_interval
def delayed_message():
print("This message appears after 2 seconds")
def periodic_update():
print("Updating every 5 seconds...")
# Schedule one-time execution
timeout_id = set_timeout(delayed_message, 2000)
# Schedule repeating execution
interval_id = set_interval(periodic_update, 5000)
# Cancel timers if needed
def cancel_timers():
clear_timeout(timeout_id)
clear_interval(interval_id)
print("All timers cancelled")
# Cancel after 30 seconds
set_timeout(cancel_timers, 30000)Smooth animations synchronized with browser refresh rate.
def request_animation_frame(func: Callable) -> int:
"""
Request function execution on next animation frame.
Args:
func: Animation function to execute
Returns:
Animation frame ID for cancellation
The callback function receives timestamp as parameter.
"""
def cancel_animation_frame(frame_id: int) -> None:
"""
Cancel pending animation frame request.
Args:
frame_id: Frame ID returned by request_animation_frame
"""Usage:
from browser.timer import request_animation_frame, cancel_animation_frame
from browser import document
from browser.html import DIV
# Create animated element
animated_div = DIV("Animated Content", style={
'position': 'absolute',
'left': '0px',
'top': '100px',
'width': '100px',
'height': '100px',
'background': 'blue',
'color': 'white',
'text-align': 'center'
})
document.body <= animated_div
# Animation state
animation_state = {
'x': 0,
'direction': 1,
'running': False,
'frame_id': None
}
def animate_element(timestamp):
"""Animation loop function."""
if not animation_state['running']:
return
# Update position
animation_state['x'] += animation_state['direction'] * 2
# Reverse direction at boundaries
if animation_state['x'] >= 500 or animation_state['x'] <= 0:
animation_state['direction'] *= -1
# Apply position
animated_div.style.left = f"{animation_state['x']}px"
# Continue animation
animation_state['frame_id'] = request_animation_frame(animate_element)
def start_animation():
"""Start the animation."""
if not animation_state['running']:
animation_state['running'] = True
animation_state['frame_id'] = request_animation_frame(animate_element)
def stop_animation():
"""Stop the animation."""
animation_state['running'] = False
if animation_state['frame_id']:
cancel_animation_frame(animation_state['frame_id'])
animation_state['frame_id'] = None
# Control buttons
from browser.html import BUTTON
from browser import bind
start_btn = BUTTON("Start Animation")
stop_btn = BUTTON("Stop Animation")
@bind(start_btn, 'click')
def handle_start(event):
start_animation()
@bind(stop_btn, 'click')
def handle_stop(event):
stop_animation()
document.body <= start_btn
document.body <= stop_btnMonitor and optimize timing performance.
def set_loop_timeout(seconds: int) -> None:
"""
Set maximum execution time for loops to prevent blocking.
Args:
seconds: Maximum execution time in seconds
"""
def get_timestamp() -> float:
"""
Get high-resolution timestamp.
Returns:
Timestamp in milliseconds with microsecond precision
"""Usage:
from browser.timer import set_loop_timeout, get_timestamp
# Set timeout for long-running operations
set_loop_timeout(5) # 5 second limit
def performance_test():
"""Measure function execution time."""
start_time = get_timestamp()
# Simulate work
total = 0
for i in range(1000000):
total += i
end_time = get_timestamp()
execution_time = end_time - start_time
print(f"Execution time: {execution_time:.2f}ms")
print(f"Total: {total}")
performance_test()Complex animations with easing and chaining.
class Animator:
"""
Advanced animation controller.
"""
def __init__(self):
"""Initialize animator."""
def animate(self, element: Element, properties: dict, duration: int,
easing: str = 'linear') -> 'Animation':
"""
Animate element properties.
Args:
element: Target element
properties: Properties to animate with end values
duration: Animation duration in milliseconds
easing: Easing function name
Returns:
Animation object for control
"""
def chain(self, *animations) -> 'AnimationChain':
"""Chain multiple animations in sequence."""
def parallel(self, *animations) -> 'AnimationGroup':
"""Run multiple animations in parallel."""
class Animation:
"""Individual animation instance."""
def start(self) -> None:
"""Start animation."""
def pause(self) -> None:
"""Pause animation."""
def resume(self) -> None:
"""Resume paused animation."""
def stop(self) -> None:
"""Stop animation."""
def on_complete(self, callback: Callable) -> 'Animation':
"""Set completion callback."""Usage:
from browser.timer import Animator
from browser import document
from browser.html import DIV
# Create animator
animator = Animator()
# Create elements to animate
box1 = DIV("Box 1", style={
'position': 'absolute',
'width': '50px',
'height': '50px',
'background': 'red',
'left': '0px',
'top': '200px'
})
box2 = DIV("Box 2", style={
'position': 'absolute',
'width': '50px',
'height': '50px',
'background': 'blue',
'left': '0px',
'top': '260px'
})
document.body <= box1
document.body <= box2
# Create animations
move_right = animator.animate(box1, {
'left': '300px',
'background': 'green'
}, 2000, easing='ease-out')
move_up = animator.animate(box2, {
'top': '100px',
'width': '100px',
'height': '100px'
}, 1500, easing='ease-in-out')
# Chain animations
sequence = animator.chain(move_right, move_up)
# Parallel animations
parallel = animator.parallel(
animator.animate(box1, {'opacity': '0.5'}, 1000),
animator.animate(box2, {'opacity': '0.5'}, 1000)
)
# Start animations with callbacks
move_right.on_complete(lambda: print("Box 1 finished moving"))
sequence.start()
def complex_animation():
"""Complex multi-stage animation."""
# Stage 1: Move elements
stage1 = animator.parallel(
animator.animate(box1, {'left': '200px'}, 1000),
animator.animate(box2, {'left': '200px'}, 1000)
)
# Stage 2: Rotate and scale
stage2 = animator.parallel(
animator.animate(box1, {
'transform': 'rotate(180deg) scale(1.5)',
'background': 'purple'
}, 1500),
animator.animate(box2, {
'transform': 'rotate(-180deg) scale(0.8)',
'background': 'orange'
}, 1500)
)
# Stage 3: Return to original
stage3 = animator.parallel(
animator.animate(box1, {
'left': '0px',
'transform': 'rotate(0deg) scale(1)',
'background': 'red'
}, 2000),
animator.animate(box2, {
'left': '0px',
'transform': 'rotate(0deg) scale(1)',
'background': 'blue'
}, 2000)
)
# Chain all stages
full_sequence = animator.chain(stage1, stage2, stage3)
full_sequence.on_complete(lambda: print("Complex animation complete"))
full_sequence.start()
# Trigger complex animation
from browser.html import BUTTON
from browser import bind
complex_btn = BUTTON("Start Complex Animation")
@bind(complex_btn, 'click')
def handle_complex(event):
complex_animation()
document.body <= complex_btnHelper functions for common timing patterns.
class Timer:
"""
Timer utility class with advanced features.
"""
def __init__(self):
"""Initialize timer."""
def debounce(self, func: Callable, delay: int) -> Callable:
"""
Create debounced function that delays execution.
Args:
func: Function to debounce
delay: Delay in milliseconds
Returns:
Debounced function
"""
def throttle(self, func: Callable, limit: int) -> Callable:
"""
Create throttled function that limits execution rate.
Args:
func: Function to throttle
limit: Minimum interval between calls in milliseconds
Returns:
Throttled function
"""
def countdown(self, seconds: int, callback: Callable,
tick_callback: Callable = None) -> int:
"""
Create countdown timer.
Args:
seconds: Countdown duration
callback: Function to call when complete
tick_callback: Function to call each second (receives remaining time)
Returns:
Timer ID for cancellation
"""
timer_utils = Timer()Usage:
from browser.timer import Timer
from browser import document, bind
from browser.html import INPUT, DIV
timer = Timer()
# Debounced search function
search_results = DIV()
document.body <= search_results
def perform_search(query):
"""Simulate search operation."""
print(f"Searching for: {query}")
search_results.text = f"Results for: {query}"
# Debounce search to avoid excessive API calls
debounced_search = timer.debounce(perform_search, 500) # 500ms delay
search_input = INPUT(placeholder="Type to search...")
@bind(search_input, 'input')
def handle_search_input(event):
query = event.target.value
if query.strip():
debounced_search(query)
document.body <= search_input
# Throttled scroll handler
def handle_scroll():
"""Handle scroll events."""
scroll_position = window.pageYOffset
print(f"Scroll position: {scroll_position}")
# Throttle scroll events to improve performance
throttled_scroll = timer.throttle(handle_scroll, 100) # Max 10 times per second
@bind(window, 'scroll')
def on_scroll(event):
throttled_scroll()
# Countdown timer
countdown_display = DIV()
document.body <= countdown_display
def start_countdown():
"""Start 10-second countdown."""
def on_tick(remaining):
countdown_display.text = f"Countdown: {remaining} seconds"
def on_complete():
countdown_display.text = "Countdown finished!"
print("Timer expired!")
timer.countdown(10, on_complete, on_tick)
from browser.html import BUTTON
countdown_btn = BUTTON("Start 10s Countdown")
@bind(countdown_btn, 'click')
def handle_countdown(event):
start_countdown()
document.body <= countdown_btnBuilt-in easing functions for natural animations.
# Available easing functions
EASING_FUNCTIONS = {
'linear': 'linear progression',
'ease': 'default ease',
'ease-in': 'slow start',
'ease-out': 'slow end',
'ease-in-out': 'slow start and end',
'cubic-bezier': 'custom cubic bezier curve'
}
def create_easing(p1: float, p2: float, p3: float, p4: float) -> str:
"""
Create custom cubic-bezier easing function.
Args:
p1, p2, p3, p4: Bezier curve control points
Returns:
CSS cubic-bezier string
"""This comprehensive timing system enables sophisticated time-based functionality and smooth animations for creating engaging and responsive user interfaces in Brython applications.
Install with Tessl CLI
npx tessl i tessl/pypi-brython