Skip to content

Commit bb99de5

Browse files
fix: bump changes and conform to latest syntax
1 parent 1bd6a5a commit bb99de5

37 files changed

Lines changed: 2887 additions & 2229 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ __pycache__/
88
localhost.pem
99
localhost-key.pem
1010
chatbot.db
11-
.coverage
11+
.coverage
12+
.pywire/

.vscode/settings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"files.exclude": {
3+
"**/.git": true,
4+
"**/.svn": true,
5+
"**/.hg": true,
6+
"**/.DS_Store": true,
7+
"**/Thumbs.db": true,
8+
"**/.pywire": true
9+
}
10+
}

demo-app/check_env.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pywire
2+
import os
3+
import sys
4+
5+
print(f"Python Version: {sys.version}")
6+
print(f"Python Executable: {sys.executable}")
7+
print(f"PyWire File: {pywire.__file__}")
8+
print(f"PyWire Path: {os.path.dirname(pywire.__file__)}")
9+
10+
try:
11+
from pywire.runtime.page import BasePage
12+
import inspect
13+
print(f"BasePage File: {inspect.getfile(BasePage)}")
14+
except Exception as e:
15+
print(f"Error loading BasePage: {e}")

demo-app/pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "demo-app"
33
authors = [
4-
{ name="Reece Holmdahl", email="reecelikesramen@duck.com" },
4+
{ name="Reece Holmdahl", email="reece@pywire.dev" },
55
]
66
version = "0.1.0"
77
requires-python = ">=3.11"
@@ -15,5 +15,5 @@ dependencies = [
1515

1616
# This is not a distributable package, just for dependency management
1717

18-
[tool.uv.sources]
19-
pywire = { path = "../../pywire" }
18+
# [tool.uv.sources]
19+
# pywire = { workspace = true }

demo-app/src/pages/basic/counter.wire

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
}
44
!layout "__layout__.wire"
55

6-
count = 0
6+
count = wire(0)
77

88
def increment_count():
99
"""Increment the counter"""
1010

11-
count += 1
11+
$count += 1
12+
13+
--- html ---
1214

13-
---html---
1415
<slot name="title">Counter Example</slot>
1516

1617
<h1>Counter</h1>

demo-app/src/pages/basic/weather.wire

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import datetime
88
import random
99
import asyncio
1010

11-
forecasts = []
12-
is_loading = False
11+
forecasts = wire([])
12+
is_loading = wire(False)
1313

1414
async def on_load():
1515
# Auto-fetch on initial load
@@ -35,7 +35,7 @@ async def refresh_data():
3535
'summary': random.choice(summaries)
3636
})
3737

38-
forecasts = new_forecasts
38+
$forecasts = new_forecasts
3939

4040
---html---
4141
<slot name="title">Weather Forecast</slot>

demo-app/src/pages/forms_test.wire

Lines changed: 60 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,34 @@ from pydantic import BaseModel
55
from typing import Optional
66

77
# State
8-
success_message = ""
9-
form_data = {}
10-
delivery_method = "standard"
11-
has_referral = False
12-
pydantic_success = ""
13-
pydantic_data = None
14-
advanced_success = ""
15-
advanced_data = None
16-
upload_progress = 0.0
8+
success_message = wire("")
9+
form_data = wire({})
10+
delivery_method = wire("standard")
11+
has_referral = wire(False)
12+
pydantic_success = wire("")
13+
pydantic_data = wire(None)
14+
advanced_success = wire("")
15+
advanced_data = wire(None)
16+
upload_progress = wire(0.0)
1717
# Async Task State
18-
task_progress = 0
19-
task_status_text = "Idle"
20-
task_running = False
18+
task_progress = wire(0)
19+
task_status_text = wire("Idle")
20+
task_running = wire(False)
2121

2222
def update_has_referral(event_data):
23-
self.has_referral = bool(event_data.checked)
23+
$has_referral = bool(event_data["checked"])
2424

2525
def update_delivery_method(event_data):
26-
self.delivery_method = event_data.value
26+
$delivery_method = event_data["value"]
2727

2828
errors = {} # BasePage has self.errors, but we can explicitly define for local ref if needed?
29-
errors = {} # BasePage has self.errors, but we can explicitly define for local ref if needed?
30-
# Actually BasePage.errors is auto-populated.
29+
# actually BasePage.errors is auto-populated.
3130
# The template uses `errors.get('key')`, which accesses self.errors.
3231

3332
async def handle_submit(data):
3433
# This handler is only called if validation passes!
35-
self.success_message = f"Form submitted successfully! Validated data: {json.dumps(data)}"
36-
self.form_data = data
34+
$success_message = f"Form submitted successfully! Validated data: {json.dumps(data)}"
35+
$form_data = data
3736
# self.errors is automatically cleared by the wrapper before calling this if valid?
3837
# Current implementation of wrapper:
3938
# self.errors = form_validator.validate...
@@ -46,24 +45,26 @@ async def handle_submit(data):
4645
# The form will hide because of $if={not success_message}
4746

4847
async def reset_form():
49-
self.success_message = ""
50-
self.form_data = {}
51-
self.has_referral = False
52-
self.errors = {}
53-
self.pydantic_success = ""
54-
self.pydantic_data = None
55-
self.advanced_success = ""
56-
self.advanced_data = None
48+
$success_message = ""
49+
$form_data = {}
50+
$has_referral = False
51+
# self.errors = {} # errors is on the instance, not a wire variable here?
52+
# If errors is implicit, we might not be able to reset it easily via wire syntax unless usage changes.
53+
# But usually re-rendering clears it or new submission.
54+
$pydantic_success = ""
55+
$pydantic_data = None
56+
$advanced_success = ""
57+
$advanced_data = None
5758

5859
import asyncio
5960

6061
async def run_long_task(event_data):
61-
if self.task_running:
62+
if task_running:
6263
return
6364

64-
self.task_running = True
65-
self.task_progress = 0
66-
self.task_status_text = "Initializing task..."
65+
$task_running = True
66+
$task_progress = 0
67+
$task_status_text = "Initializing task..."
6768
await self.push_state()
6869

6970
# Simulate processing steps
@@ -73,16 +74,16 @@ async def run_long_task(event_data):
7374
await asyncio.sleep(0.05)
7475

7576
# Update progress
76-
self.task_progress = (i / total_steps) * 100
77-
self.task_status_text = f"Processing item {i} of {total_steps}..."
77+
$task_progress = (i / total_steps) * 100
78+
$task_status_text = f"Processing item {i} of {total_steps}..."
7879

7980
# Push updates to UI periodically (every 5 steps or so to avoid flooding)
8081
if i % 2 == 0:
8182
await self.push_state()
8283

83-
self.task_status_text = "Task Completed Successfully!"
84-
self.task_progress = 100
85-
self.task_running = False
84+
$task_status_text = "Task Completed Successfully!"
85+
$task_progress = 100
86+
$task_running = False
8687
# Final state update happens automatically on return, but explicit doesn't hurt
8788

8889

@@ -115,37 +116,47 @@ class AdvancedUser(BaseModel):
115116

116117
async def handle_advanced(user: AdvancedUser):
117118
import base64
118-
self.advanced_success = f"Advanced Valid! Name: {user.full_name}, Role: {user.role}, File: {user.profile_pic.filename if user.profile_pic else 'None'}"
119+
$advanced_success = f"Advanced Valid! Name: {user.full_name}, Role: {user.role}, File: {user.profile_pic.filename if user.profile_pic else 'None'}"
119120
print(user)
120121

121122
if user.profile_pic:
122123
b64_data = base64.b64encode(user.profile_pic.content).decode('utf-8')
123124
mime_type = user.profile_pic.content_type
124-
self.image_preview = f"data:{mime_type};base64,{b64_data}"
125+
$image_preview = f"data:{mime_type};base64,{b64_data}"
125126
else:
126-
self.image_preview = None
127+
$image_preview = None
127128

128-
self.advanced_data = str(user)
129+
$advanced_data = str(user)
129130

130131

131132
async def handle_pydantic_submit(user: User):
132133
# This handler receives a Pydantic model instance!
133-
self.pydantic_success = f"Pydantic Form Valid! User: {user.username}, Age: {user.age}, Active: {user.is_active}"
134-
self.pydantic_data = user.dict()
134+
$pydantic_success = f"Pydantic Form Valid! User: {user.username}, Age: {user.age}, Active: {user.is_active}"
135+
$pydantic_data = user.dict()
135136
# errors are cleared automatically
136137

137138
from datetime import date, timedelta
138-
tomorrow = (date.today() + timedelta(days=1)).isoformat()
139-
shipment_success = ""
140-
shipment_data = None
141-
delivery_method = 'standard'
142-
image_preview = None
139+
tomorrow = wire((date.today() + timedelta(days=1)).isoformat())
140+
shipment_success = wire("")
141+
shipment_data = wire(None)
142+
# delivery_method was already defined effectively shadowed? No, python scoping.
143+
# But delivery_method is defined at top level. Redefining it here?
144+
# Ah, the previous one was top level. This one seems to be redefining/shadowing or just initializing again?
145+
# The example has duplicate variable names. Let's fix this.
146+
# top level: delivery_method = "standard"
147+
# here: delivery_method = 'standard'
148+
# It seems the file has a bit of a mess.
149+
# I'll stick to the top definition and remove this one if it's redundant.
150+
# unique vars: shipment_success, shipment_data, image_preview.
151+
152+
# image_preview was not defined at top.
153+
image_preview = wire(None)
143154

144155
async def create_shipment(data):
145-
self.shipment_success = f"Shipment Created! Method: {data.get('delivery_method')}, Address: {data.get('street')}, Date: {data.get('delivery_date')}"
146-
self.shipment_data = data
156+
$shipment_success = f"Shipment Created! Method: {data.get('delivery_method')}, Address: {data.get('street')}, Date: {data.get('delivery_date')}"
157+
$shipment_data = data
147158
# Reset for demo
148-
self.delivery_method = 'standard'
159+
$delivery_method = 'standard'
149160

150161
---html---
151162
<!DOCTYPE html>

demo-app/src/pages/test.wire

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
!path "/test-1.7"
2+
3+
count = wire(3)
4+
other_count = 0
5+
6+
def increment():
7+
count.value += 1
8+
9+
def test():
10+
other_count += 1
11+
12+
my_list = wire([
13+
"Melon",
14+
"Lemon",
15+
"test",
16+
"Pancake",
17+
])
18+
19+
my_dict = wire({
20+
'0001': 'Crabapple',
21+
'0002': 'Scrabble',
22+
'0003': 'Tapple',
23+
'0004': 'Grapple'
24+
})
25+
26+
27+
---html---
28+
<p>Count: {count}</p>
29+
<button @click={increment}>Increment</button>
30+
<hr />
31+
<p>Count: {other_count}</p>
32+
<button @click={test}>Other Increment</button>
33+
{$if count > 5}
34+
<p>Test</p>
35+
{/if}
36+
37+
<ul>
38+
{$for idx, item in enumerate(my_list.value), key=idx}
39+
<li>
40+
<span>{item}</span>
41+
<button @click={my_list.value.pop(idx)}>Del</button>
42+
</li>
43+
{/for}
44+
</ul>
45+
46+
<hr />
47+
48+
<ul>
49+
{$for key, value in my_dict.value.items(), key=key}
50+
<li>
51+
<span>{value}</span>
52+
<button @click={del my_dict.value[key]}>Del</button>
53+
</li>
54+
{/for}
55+
</ul>

0 commit comments

Comments
 (0)