pythonista-wkapp 0.1.0__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pythonista_wkapp-0.1.0 → pythonista_wkapp-0.1.2}/PKG-INFO +3 -2
- {pythonista_wkapp-0.1.0 → pythonista_wkapp-0.1.2}/pyproject.toml +6 -2
- pythonista_wkapp-0.1.2/wkapp/LICENSE +21 -0
- pythonista_wkapp-0.1.2/wkapp/README.md +105 -0
- pythonista_wkapp-0.1.2/wkapp/__init__.py +24 -0
- pythonista_wkapp-0.1.2/wkapp/__init__.pye +24 -0
- pythonista_wkapp-0.1.2/wkapp/docs/README.md +135 -0
- pythonista_wkapp-0.1.2/wkapp/docs/placeholder.html +210 -0
- pythonista_wkapp-0.1.2/wkapp/pyproject.toml +35 -0
- pythonista_wkapp-0.1.2/wkapp/requirements.txt +3 -0
- pythonista_wkapp-0.1.2/wkapp/static/bootstrap.bundle.min.js +7 -0
- pythonista_wkapp-0.1.2/wkapp/static/bootstrap.min.css +6 -0
- pythonista_wkapp-0.1.2/wkapp/static/jquery.min.js +2 -0
- pythonista_wkapp-0.1.2/wkapp/static/wkapp.css +1 -0
- pythonista_wkapp-0.1.2/wkapp/static/wkapp.js +37 -0
- pythonista_wkapp-0.1.2/wkapp/test/views/base/layout.html +5 -0
- pythonista_wkapp-0.1.2/wkapp/test/views/first_view.html +43 -0
- pythonista_wkapp-0.1.2/wkapp/test/views/index.html +52 -0
- pythonista_wkapp-0.1.2/wkapp/test/views/test_view.html +30 -0
- pythonista_wkapp-0.1.2/wkapp/test/views/web_asm.html +90 -0
- pythonista_wkapp-0.1.2/wkapp/views/app.css +1 -0
- pythonista_wkapp-0.1.2/wkapp/views/app.js +1 -0
- pythonista_wkapp-0.1.2/wkapp/views/base/app.html +23 -0
- pythonista_wkapp-0.1.2/wkapp/views/base/layout.html +2 -0
- pythonista_wkapp-0.1.2/wkapp/views/base/view.html +2 -0
- pythonista_wkapp-0.1.2/wkapp/views/index.html +100 -0
- pythonista_wkapp-0.1.2/wkapp/views/view.html +2 -0
- {pythonista_wkapp-0.1.0 → pythonista_wkapp-0.1.2/wkapp}/wkapp.py +3 -3
- pythonista_wkapp-0.1.2/wkapp/wkapp.pye +787 -0
- pythonista_wkapp-0.1.2/wkapp/wkapp.pyui +33 -0
- pythonista_wkapp-0.1.2/wkapp/wkwebview.py +1354 -0
- {pythonista_wkapp-0.1.0 → pythonista_wkapp-0.1.2}/LICENSE +0 -0
- {pythonista_wkapp-0.1.0 → pythonista_wkapp-0.1.2}/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonista-wkapp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: WKApp - A modern HTML5 UI framework for building iOS apps with Pythonista 3 and WebKit
|
|
5
5
|
Author-email: M4nw3l <63550247+M4nw3l@users.noreply.github.com>
|
|
6
6
|
Requires-Python: >= 3.10
|
|
@@ -13,8 +13,9 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
14
14
|
Classifier: Topic :: Software Development :: User Interfaces
|
|
15
15
|
License-File: LICENSE
|
|
16
|
-
Requires-Dist: bottle
|
|
16
|
+
Requires-Dist: bottle >= 0.13.4
|
|
17
17
|
Requires-Dist: Mako
|
|
18
|
+
Requires-Dist: requests
|
|
18
19
|
Project-URL: Homepage, https://github.com/m4nw3l/pythonista-wkapp
|
|
19
20
|
|
|
20
21
|
# pythonista-wkapp
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
name = "pythonista-wkapp"
|
|
3
3
|
requires-python = ">= 3.10"
|
|
4
4
|
dependencies = [
|
|
5
|
-
"bottle",
|
|
6
|
-
"Mako"
|
|
5
|
+
"bottle >= 0.13.4",
|
|
6
|
+
"Mako",
|
|
7
|
+
"requests"
|
|
7
8
|
]
|
|
8
9
|
authors = [
|
|
9
10
|
{name = "M4nw3l", email = "63550247+M4nw3l@users.noreply.github.com"},
|
|
@@ -26,6 +27,9 @@ Homepage = "https://github.com/m4nw3l/pythonista-wkapp"
|
|
|
26
27
|
[tool.flit.module]
|
|
27
28
|
name = "wkapp"
|
|
28
29
|
|
|
30
|
+
[tool.flit.sdist]
|
|
31
|
+
exclude = ["**/.*/"]
|
|
32
|
+
|
|
29
33
|
[build-system]
|
|
30
34
|
requires = ["flit_core >=3.11,<4"]
|
|
31
35
|
build-backend = "flit_core.buildapi"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 M4nw3l
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# pythonista-wkapp
|
|
2
|
+
## WKApp - A modern HTML5 UI framework for building iOS apps with Pythonista 3 and WebKit
|
|
3
|
+
|
|
4
|
+
WKApp is a modern, lightweight and minimal application framework for developing Python applications with desktop-class HTML 5 based user interfaces on Apple iOS devices in the [Pythonista 3 IDE](https://omz-software.com/pythonista/) for iOS.
|
|
5
|
+
It is a comprehensive and fully featured alternative to Pythonista's native app `ui` library, allowing user interfaces to be created with standard web technologies. Using powerful Python templating for dynamic HTML5/CSS/JavaScript views rendering with Mako, simple instanced view state binding supporting auto-wiring GET/POST values and two way Python/JavaScript interop via JSON over thread-safe message handlers.
|
|
6
|
+
|
|
7
|
+
Creating user interfaces for Python Apps in Pythonista becomes as simple as adding new .html view template files into your project. Which are then served locally from a Bottle.py HTTP/WSGI server and shown in a native WKWebView browser component. WKApp supports creating user interfaces with anything supported by modern web browsers using HTML5, CSS, JavaScript or even WebAssembly and browser based 2D/3D graphics!
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## Getting started
|
|
11
|
+
Pip is the recommended installation method for WKApp.
|
|
12
|
+
Install [StaSh](https://github.com/ywangd/stash) for Pythonista 3 using the installation instructions from its README first.
|
|
13
|
+
Then install the `pythonista-wkapp` module with pip.
|
|
14
|
+
```
|
|
15
|
+
pip install pythonista-wkapp
|
|
16
|
+
```
|
|
17
|
+
Alternatively you can also clone or download a zip of this repository and copy/extract the project files into `site-packages/wkapp`.
|
|
18
|
+
|
|
19
|
+
To create an app, simply add a folder somewhere containing an `app.py` file as follows.
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
|
|
23
|
+
from wkapp import *
|
|
24
|
+
|
|
25
|
+
app = WKApp(__file__)
|
|
26
|
+
app.run()
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Run this file and you should see a fullscreen browser control and the main view index.html placeholder page shown.
|
|
31
|
+
You can then start making your own views straight away!
|
|
32
|
+
|
|
33
|
+
To replace the initial main view / index.html placeholder page:
|
|
34
|
+
- Create a `views` folder in the same folder as your `app.py` file.
|
|
35
|
+
- Create a file `views/index.html`.
|
|
36
|
+
- Then add your html and setup a `view_class` mixin definition like as below.
|
|
37
|
+
- An instance of this class will be maintained with your view which can be used to store state, bind/manipulate elements, provide functions to be called from Javascript and evaluate Javascript from Python in the view to inspect and alter the DOM or backend state.
|
|
38
|
+
|
|
39
|
+
A simple `views/index.html` view example:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
<%!
|
|
43
|
+
|
|
44
|
+
class ViewClass:
|
|
45
|
+
def on_init(self):
|
|
46
|
+
self.name = ''
|
|
47
|
+
|
|
48
|
+
def view_action(self, text,*args):
|
|
49
|
+
print(text,args)
|
|
50
|
+
self.element('header').set('text',f'hello javascript! text was {text} args were {args}')
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
view_class = ViewClass
|
|
54
|
+
|
|
55
|
+
%>
|
|
56
|
+
```
|
|
57
|
+
```html
|
|
58
|
+
<!-- inherit from the view.html template to render the views content inside the apps customisable base layout and structure -->
|
|
59
|
+
<%inherit file="view.html"/>
|
|
60
|
+
<!-- Your page content goes here -->
|
|
61
|
+
<script type="text/javascript">
|
|
62
|
+
function invoke_view_action() {
|
|
63
|
+
view.invoke('view_action', 'hello python!',
|
|
64
|
+
{pass:'any',json:['compatible'], args:{ints:1}, floats:0.5},
|
|
65
|
+
['lists',{},1,2.2],
|
|
66
|
+
'strings',
|
|
67
|
+
'numbers',1,1.5
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
<button onclick="invoke_view_action()">Call Python</button>
|
|
72
|
+
<button onclick="app.exit()">Exit Application</button>
|
|
73
|
+
<div>
|
|
74
|
+
<h1 id="header">Hello World!</h1>
|
|
75
|
+
<form method="POST">
|
|
76
|
+
<label>Enter your name:</label>
|
|
77
|
+
<input name="name" type="text" value="${view.name}" />
|
|
78
|
+
<br />
|
|
79
|
+
<input type="submit" value="Submit" />
|
|
80
|
+
</form>
|
|
81
|
+
% if view.name != '':
|
|
82
|
+
<h2> Hello ${view.name}! </h2>
|
|
83
|
+
% endif
|
|
84
|
+
</div>
|
|
85
|
+
```
|
|
86
|
+
Note: Code above is one file, it is just shown in two parts here for code highlighting purposes.
|
|
87
|
+
|
|
88
|
+
### Dependencies
|
|
89
|
+
WKApp requires the Pythonista 3 app on iOS to run but otherwise uses a minimal set of dependencies:
|
|
90
|
+
|
|
91
|
+
- [Bottle.py 0.13.4](https://github.com/bottlepy/bottle)
|
|
92
|
+
- [Mako 1.13.10](https://github.com/sqlalchemy/mako)
|
|
93
|
+
- pythonista-wkwebview 1.2 (Bundled)
|
|
94
|
+
- 1.2 is an extended version for WKApp, updated with fixes and new features for using the native WKWebView from UIKit on iOS. Including a WKURLSchemeHandler implementation allowing creating custom url schemes with a single handler in a subclass, simplified javascript handlers threading concerns with a Dispatcher, arbitrary arguments passing from javascript to python via json.
|
|
95
|
+
- 1.1 [Gist (@sbbosco)](https://gist.github.com/sbbosco/1290f59d79c6963e62bb678f0f05b035)
|
|
96
|
+
- 1.0 [Github (@mikaelho)](https://github.com/mikaelho/pythonista-webview)
|
|
97
|
+
|
|
98
|
+
### Bundled Web frontend libraries:
|
|
99
|
+
The base app html template bundles with it Bootstrap and JQuery to offer a way to just start developing apps rapidly right away straight out of the box.
|
|
100
|
+
However if you prefer other frameworks the `base/app.html` template can also be customised.
|
|
101
|
+
Simply create a copy of `views/base/app.html` from the repository and add it to your `views` folder in the same structure `views/base/app.html`.
|
|
102
|
+
Any base template file may be replaced in this same way.
|
|
103
|
+
|
|
104
|
+
- [Bootstrap 5.3.8](https://getbootstrap.com/docs/5.3/getting-started/introduction/)
|
|
105
|
+
- [JQuery 3.7.1](https://jquery.com)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'''
|
|
2
|
+
WKApp - A modern HTML5 UI framework for building iOS apps with Pythonista 3 and WebKit
|
|
3
|
+
|
|
4
|
+
https://github.com/M4nw3l/pythonista-wkapp
|
|
5
|
+
'''
|
|
6
|
+
__version__ = '0.1.2'
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from .wkwebview import *
|
|
10
|
+
from .wkapp import *
|
|
11
|
+
except:
|
|
12
|
+
from wkwebview import *
|
|
13
|
+
from wkapp import *
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# mostly convenience includes for bottle
|
|
17
|
+
# besides its implementation specific includes for the mako templating integration
|
|
18
|
+
from bottle import (
|
|
19
|
+
request,
|
|
20
|
+
response,
|
|
21
|
+
route,
|
|
22
|
+
static_file,
|
|
23
|
+
)
|
|
24
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'''
|
|
2
|
+
WKApp - A modern HTML5 UI framework for building iOS apps with Pythonista 3 and WebKit
|
|
3
|
+
|
|
4
|
+
https://github.com/M4nw3l/pythonista-wkapp
|
|
5
|
+
'''
|
|
6
|
+
__version__ = '0.0.1'
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from .wkwebview import *
|
|
10
|
+
from .wkapp import *
|
|
11
|
+
except:
|
|
12
|
+
from wkwebview import *
|
|
13
|
+
from wkapp import *
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# mostly convenience includes for bottle
|
|
17
|
+
# besides its implementation specific includes for the mako templating integration
|
|
18
|
+
from bottle import (
|
|
19
|
+
request,
|
|
20
|
+
response,
|
|
21
|
+
route,
|
|
22
|
+
static_file,
|
|
23
|
+
)
|
|
24
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# WKApp Pythonista Development Guide
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
- Overview
|
|
5
|
+
- Setup
|
|
6
|
+
- Views
|
|
7
|
+
- Overview
|
|
8
|
+
- View classes
|
|
9
|
+
- Form data and query string parameter binding
|
|
10
|
+
- Accessing Elements and evaluating JavaScript
|
|
11
|
+
- Lifecycle Events
|
|
12
|
+
- Templates
|
|
13
|
+
- Expresion escaping
|
|
14
|
+
- Base application template
|
|
15
|
+
- base/app.html
|
|
16
|
+
- base/layout.html
|
|
17
|
+
- base/view.html
|
|
18
|
+
- app.css
|
|
19
|
+
- app.js
|
|
20
|
+
- view.html
|
|
21
|
+
- index.html
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Overview
|
|
25
|
+
WKApp is an application framework for Pythonista to easily create iOS apps with rich desktop-class HTML5 user interfaces completely within Pythonista's environment. It is intended to completely replace the default `ui` library with web based user interface, while also not being too overly restrictive or opinionated about how the app itself is developed otherwise. Providing a minimal infrastructure for creating HTML5 frontend view templates with interweaved Python for rendering, auto-wireup of Python backend model instances and javascript integration.
|
|
26
|
+
|
|
27
|
+
The entire application is displayed using a fullscreen WKWebView WebKit browser control, showing HTML5 views rendered through a Bottle.py http/WSGI server and Mako templating. Aiming to be as simple as possible to get started, requiring only a single pip package with few dependencies to install, and just three lines of code to run and show the app on the screen.
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from wkapp import *
|
|
31
|
+
|
|
32
|
+
app = WKApp(__file__)
|
|
33
|
+
app.run()
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Views are then created in the project by simply adding html file templates inside a `views` root folder and navigated between as normal with interactions such as clicking links, scripted actions and redirection. Mako's templating allows Python alongside any of it its powerful templating syntax to be interweaved into the same HTML files as well as any other served text resources such as CSS and Javascript/TypeScript scripts. Enabling programatic generation and injection of scripts and styles dynamically.
|
|
37
|
+
|
|
38
|
+
As views simply end up as Python modules through Mako, a view class can be created inline in a templates module header or assigned to a view template from another module elsewhere. Instances will be created and injected into the template automatically allowing custom variables and state to be stored, accessed and rendered as well as functions which can be called from the page.
|
|
39
|
+
|
|
40
|
+
View class instances are also combined with a mixin base class which allows page elements to be manipulated as well as general JavaScript evaluation. A straighforward mechanism for Javascript to Python inter-communication is provided, allowing for JavaScript to cross-invoke function calls with arbitrary parameter passing to Python via message handlers and json, alongside full JavaScript access, calling and DOM manipulation capabilities from Python via JavaScript evalution and a loose jQuery wrapping.
|
|
41
|
+
|
|
42
|
+
## Setup
|
|
43
|
+
|
|
44
|
+
Getting started is as simple as outlined in the main README.md in the repository root.
|
|
45
|
+
Install [StaSh](https://github.com/ywangd/stash) for Pythonista 3 using the installation instructions from its README first.
|
|
46
|
+
Then open a StaSh terminal and install the `pythonista-wkapp` module with pip.
|
|
47
|
+
```
|
|
48
|
+
pip install pythonista-wkapp # DRAFT package is not published yet!
|
|
49
|
+
```
|
|
50
|
+
Then to create the basis of an app, simply create the root folder somewhere and add an `app.py` file as follows.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from wkapp import *
|
|
54
|
+
|
|
55
|
+
app = WKApp(__file__)
|
|
56
|
+
app.run()
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Run this file and you should see a fullscreen browser control and placeholder page shown.
|
|
60
|
+
|
|
61
|
+
## Views
|
|
62
|
+
### Overview
|
|
63
|
+
All HTML5 application views are placed inside a `views` folder relative to the `app.py` file. A base set of templates allow just the views HTML5 content to be written into the views html page template. The surrounding static html structure, headers and footers etc are all handled by the base template found in the pythonista-wkapp modules `views` and `views/base` folders.
|
|
64
|
+
|
|
65
|
+
The basic structure of a view consists of a view class and a Mako template with mixed HTML, CSS, JavaScript and Python in Mako template syntax as follows, contained in an single .html file.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
<%!
|
|
69
|
+
|
|
70
|
+
class ViewClass:
|
|
71
|
+
def on_init(self):
|
|
72
|
+
self.name = ''
|
|
73
|
+
|
|
74
|
+
def view_action(self, text, *args):
|
|
75
|
+
print(text,args)
|
|
76
|
+
self.element('header').set('text',f'hello javascript! text was {text} args were {args}')
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
view_class = ViewClass
|
|
80
|
+
|
|
81
|
+
%>
|
|
82
|
+
```
|
|
83
|
+
```html
|
|
84
|
+
<!-- inherit from the view.html template to render the views content inside the apps customisable base layout and structure -->
|
|
85
|
+
<%inherit file="view.html"/>
|
|
86
|
+
|
|
87
|
+
<!-- Your page content goes here -->
|
|
88
|
+
<script type="text/javascript">
|
|
89
|
+
function invoke_view_action() {
|
|
90
|
+
view.invoke('view_action', 'hello python!',
|
|
91
|
+
{pass:'any',json:['compatible'], args:{ints:1}, floats:0.5},
|
|
92
|
+
['lists',{},1,2.2],
|
|
93
|
+
'strings',
|
|
94
|
+
'numbers',1,1.5
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
</script>
|
|
98
|
+
<button onclick="invoke_view_action()">Call Python</button>
|
|
99
|
+
<button onclick="app.exit()">Exit Application</button>
|
|
100
|
+
<div>
|
|
101
|
+
<h1 id="header">Hello World!</h1>
|
|
102
|
+
<form method="POST">
|
|
103
|
+
<label>Enter your name:</label>
|
|
104
|
+
<input name="name" type="text" value="${view.name}" />
|
|
105
|
+
<br />
|
|
106
|
+
<input type="submit" value="Submit" />
|
|
107
|
+
</form>
|
|
108
|
+
% if view.name != '':
|
|
109
|
+
<h2> Hello ${view.name}! </h2>
|
|
110
|
+
% endif
|
|
111
|
+
</div>
|
|
112
|
+
```
|
|
113
|
+
The apps views folder is effectively the `wwwRoot` folder it is shown in combination with the modules views folder such that
|
|
114
|
+
the modules views folder acts as base. WKApp provides default routes to serve templates from the views folder and
|
|
115
|
+
static content from `static` folder relative to `app.py`.
|
|
116
|
+
Any file template served/rendered from the views folder via default routes or `app.template` is considered a view and can have a backing python class which can be assigned by specifying it as the `view_class` member in the templates module header. Then the first time a view is shown it will be instantiated before rendering and the same instance is then subsequently passed through each time the template is rendered as a template variable named `view`.
|
|
117
|
+
|
|
118
|
+
### View classes
|
|
119
|
+
View classes are in essence just plain Python classes, which when instantiated are created with a base view class mixin. Providing an element accessors and javascript evalution functions.
|
|
120
|
+
|
|
121
|
+
- `element('any_jquery_selector')`
|
|
122
|
+
- `elements('any_jquery_selector')`
|
|
123
|
+
- `eval_js('any_javascript')`
|
|
124
|
+
|
|
125
|
+
#### Form data and query string parameter binding
|
|
126
|
+
|
|
127
|
+
Any form values and query string parameters are automatically assigned from the request into in view class instances for both GET and POST if attributes of the same name exist in the Python backend view class.
|
|
128
|
+
|
|
129
|
+
### Templates
|
|
130
|
+
|
|
131
|
+
#### Expressions Escaping
|
|
132
|
+
A slighly customised lexer for Mako is used to offer better integration and escaping options for Mako's standard `${}` expression, as JavaScript now too supports this notation. Additionaly adding a `$${}` escaped expression which renders the entire expression as a literal `${}`, as if typed in html/js, and an equivalent alternative expression construct `%{}` which feels like an oversight from Makos general definition consistently using `%` elsewhere for other constructs. A `%%{}` literal escape for `%{}` is additionaly included for completeness.
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
<%!
|
|
2
|
+
|
|
3
|
+
class IndexPlaceHolderView:
|
|
4
|
+
def on_init(self):
|
|
5
|
+
#print("View initialise")
|
|
6
|
+
# automatically called once when the view is created and after view is assigned initial vars
|
|
7
|
+
self.editor = self.element("editor")
|
|
8
|
+
|
|
9
|
+
#def on_prepare(self):
|
|
10
|
+
#print("View preparing")
|
|
11
|
+
# automatically called before this view is served allowing state
|
|
12
|
+
# to be modified before rendering the page template
|
|
13
|
+
|
|
14
|
+
#def on_loading(self):
|
|
15
|
+
#print("View loading")
|
|
16
|
+
# automatically called just after view is served but before fully loaded by browser
|
|
17
|
+
# can be used to start async tasks while loading ui etc
|
|
18
|
+
|
|
19
|
+
#def on_loaded(self):
|
|
20
|
+
#print("View loaded") # automatically called once view is fully loaded by browser control
|
|
21
|
+
|
|
22
|
+
def test_action(self, text):
|
|
23
|
+
print(text)
|
|
24
|
+
|
|
25
|
+
def hello_world_action(self, text):
|
|
26
|
+
print(text)
|
|
27
|
+
cur = self.editor.get('text')
|
|
28
|
+
print(cur)
|
|
29
|
+
self.editor.set('text',cur + text)
|
|
30
|
+
|
|
31
|
+
view_class = IndexPlaceHolderView
|
|
32
|
+
|
|
33
|
+
%>
|
|
34
|
+
|
|
35
|
+
<%inherit file="view.html"/>
|
|
36
|
+
<div class="pt-2">
|
|
37
|
+
<h4 class="pt-1">WKApp index.html placeholder</h3>
|
|
38
|
+
<a href="/first_view.html">First view</a>
|
|
39
|
+
<a href="/test_view.html">Test View</a>
|
|
40
|
+
<button onclick="app.exit()">Exit Application</button>
|
|
41
|
+
<h5 class="pt-1">Overview</h5>
|
|
42
|
+
<p>
|
|
43
|
+
WKApp is a modern, lightweight and minimal application framework for
|
|
44
|
+
developing Python applications with desktop-class HTML 5 user interfaces on Apple iOS devices
|
|
45
|
+
in the <a href="https://omz-software.com/pythonista/">Pythonista 3 IDE</a>.
|
|
46
|
+
It provides a simple basis to start creating browser based applications in Pythonista quickly while offering wide customisability capable of developing from simple single page applications through to sophisticated multi-view mobile applications supporting anything you can do in HTML 5 with WebKit support including canvases, browser gaming, media playback, file editing and more. Use any Python libraries from the pip ecosysten that can be installed and supported by Pythonista. And/or use any WebKit/Safafi in browser compatible javascript for client side functionality too. Supporting bi-directional and asyncronous interop between both, Python and JavaScript can work together to produce compelling experiences. Handling styling of your application and concerns like device orientation, screen size and scaling in the same way as any other responsive website using css's powerful, mature and well known feature set. Web frontend libraries Bootstrap 5, for out of the box responsive styling, and JQuery, to ease, extend and perform DOM manipulation, are bundled to help streamline, and give options focused on rapidly developing apps, instead of getting lost down areas such as drawing an apps ui more traditionally for example. The whole of the included base app ui templates and static files are however also customiable and replacable too, so these may be overriden, removed or expanded with plugins etc depending on your applications requirements and needs.
|
|
47
|
+
</p>
|
|
48
|
+
<p>
|
|
49
|
+
Python Dependencies
|
|
50
|
+
<ul>
|
|
51
|
+
<li><a href="https://github.com/bottlepy/bottle">Bottle.py 0.13.4</a></li>
|
|
52
|
+
<li><a href="https://github.com/sqlalchemy/mako">Mako 1.13.10</a></li>
|
|
53
|
+
<li>WKWebView 1.2 (Bundled)
|
|
54
|
+
<ul>
|
|
55
|
+
<li>1.2 is a customised extended version which has been updated for WKApp, to implement displaying apps in UIKits WKWebView WebKit browser control. Changes consist mostly of fixes, improvments to reliability, simplifying threading concerns, avoiding/removing the odd crash and deadlock in handling objective-c, python, js interactions here and there and adding a few more helper methods.
|
|
56
|
+
</li>
|
|
57
|
+
<li>1.1 - <a href="https://gist.github.com/sbbosco/1290f59d79c6963e62bb678f0f05b035">Gist (@sbbosco)</a></li>
|
|
58
|
+
<li>1.0 - <a href="https://github.com/mikaelho/pythonista-webview">Github (@mikaelho)</a></li>
|
|
59
|
+
</ul>
|
|
60
|
+
</li>
|
|
61
|
+
</ul>
|
|
62
|
+
</p>
|
|
63
|
+
<p>
|
|
64
|
+
Bundled Web frontend libraries:
|
|
65
|
+
<ul>
|
|
66
|
+
<li><a href="https://jquery.com">JQuery 3.7.1</a></li>
|
|
67
|
+
<li><a href="https://getbootstrap.com/docs/5.3/getting-started/introduction/">Bootstrap 5.3.8</a></li>
|
|
68
|
+
</ul>
|
|
69
|
+
|
|
70
|
+
</p>
|
|
71
|
+
<h5 class="pt-1">Getting started</h5>
|
|
72
|
+
<p>First, create your app.py file, the bare minimum code to setup, run and display a WKApp is just three lines as follows.
|
|
73
|
+
|
|
74
|
+
app.py
|
|
75
|
+
${codeblock('''
|
|
76
|
+
from wkapp import *
|
|
77
|
+
|
|
78
|
+
app = WKApp(__file__)
|
|
79
|
+
app.run()
|
|
80
|
+
''')}
|
|
81
|
+
</p>
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
<p>
|
|
85
|
+
When you run this file in Pythonista you should see this page! To create your own make a new file views/index.html, which will then replace this document as the placeholder being shown in your apps main view and re-run:
|
|
86
|
+
|
|
87
|
+
${codeblock('''
|
|
88
|
+
<!-- inherit from the view.html template to render the views content inside the apps customisable base layout and structure -->
|
|
89
|
+
<%inherit file="view.html"/>
|
|
90
|
+
<!-- Your page content goes here -->
|
|
91
|
+
<div>
|
|
92
|
+
<h1>Hello World!</h1>
|
|
93
|
+
</div>
|
|
94
|
+
''')}
|
|
95
|
+
|
|
96
|
+
Congratulations! You've just created a WKApp HTML 5 browser based app on your iOS device.
|
|
97
|
+
Now, you may already be wanting to try some more things out, go right ahead any html/css/javascript should just work. The following is a small overview of some of WKApp features and how they are integrated with Bottle.py as for hosting the WSGI web server for the app and the Mako template engine for rendering pages, components and content from templates with a rich, comprehensive syntax using interweaved Python which can generate html markup, styles and even javascript dynamically.
|
|
98
|
+
</p>
|
|
99
|
+
|
|
100
|
+
<h6 class="pt-1">Features</h6>
|
|
101
|
+
|
|
102
|
+
<p>
|
|
103
|
+
Views are served automatically without wire-up and can be navigated as normal web pages, just drop in html templates into the `./views` folder.
|
|
104
|
+
${codeblock('''
|
|
105
|
+
<!-- index.html -->
|
|
106
|
+
<%inherit file="view.html"/>
|
|
107
|
+
<div>
|
|
108
|
+
<h1>Hello World!</h1>
|
|
109
|
+
<a href="/goodbye.html">Goodbye</a>
|
|
110
|
+
<a href="/index.html">Index</a>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<!-- goodbye.html -->
|
|
114
|
+
<%inherit file="view.html"/>
|
|
115
|
+
<div>
|
|
116
|
+
<h1>Goodbye World!</h1>
|
|
117
|
+
<a href="/hello.html">Hello</a>
|
|
118
|
+
<a href="/index.html">Index</a>
|
|
119
|
+
</div>
|
|
120
|
+
''')}
|
|
121
|
+
|
|
122
|
+
Add python behavior to views with inline class mixins, manipulate elements, receive lifecycle events and hold custom page state.
|
|
123
|
+
|
|
124
|
+
${codeblock('''
|
|
125
|
+
<%!
|
|
126
|
+
|
|
127
|
+
class IndexView:
|
|
128
|
+
def on_init(self):
|
|
129
|
+
self.editor = self.element('editor')
|
|
130
|
+
|
|
131
|
+
def hello_world_action(self, text):
|
|
132
|
+
print(text)
|
|
133
|
+
cur = self.editor.get('text')
|
|
134
|
+
print(cur)
|
|
135
|
+
self.editor.set('text',cur + text)
|
|
136
|
+
|
|
137
|
+
view_class = IndexView
|
|
138
|
+
|
|
139
|
+
%>
|
|
140
|
+
<%inherit file="view.html"/>
|
|
141
|
+
|
|
142
|
+
<style type="text/css">
|
|
143
|
+
textarea.editor {
|
|
144
|
+
width : 95%;
|
|
145
|
+
height : 80vh;
|
|
146
|
+
overflow : auto;
|
|
147
|
+
font-style : monospace;
|
|
148
|
+
font-size : 10pt;
|
|
149
|
+
font-color : #808080;
|
|
150
|
+
}
|
|
151
|
+
</style>
|
|
152
|
+
|
|
153
|
+
<div class="p-1">
|
|
154
|
+
<button onclick="view.invoke('hello_world_action', 'Hello World\n')">Say Hello (again)</button>
|
|
155
|
+
</div>
|
|
156
|
+
<div>
|
|
157
|
+
<textarea id="editor" class="form-control editor" readonly></textarea>
|
|
158
|
+
</div>
|
|
159
|
+
''')}
|
|
160
|
+
|
|
161
|
+
<div class="p-1">
|
|
162
|
+
<button onclick="view.invoke('hello_world_action', 'Hello World\n')">Say Hello (again)</button>
|
|
163
|
+
</div>
|
|
164
|
+
<div>
|
|
165
|
+
<textarea id="editor" class="form-control editor" readonly></textarea>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
You can define any scheme and custom routes, middleware and handlers may also be added with any constructs supported by Bottle.py.
|
|
170
|
+
|
|
171
|
+
app.py
|
|
172
|
+
${codeblock('''
|
|
173
|
+
from wkapp import *
|
|
174
|
+
|
|
175
|
+
app = WKApp(__file__)
|
|
176
|
+
app.run()
|
|
177
|
+
|
|
178
|
+
# see https://bottlepy.org/docs/dev/tutorial.html#generating-content for more examples
|
|
179
|
+
@route('/my/route')
|
|
180
|
+
def my_route():
|
|
181
|
+
return "Hello World!"
|
|
182
|
+
''')}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
</p>
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
<style>
|
|
190
|
+
textarea.code {
|
|
191
|
+
display: block;
|
|
192
|
+
width: 90%;
|
|
193
|
+
font-family: monospace;
|
|
194
|
+
border: 1px solid #bbb;
|
|
195
|
+
white-space:pre-wrap;
|
|
196
|
+
text-align:left;
|
|
197
|
+
field-sizing: content;
|
|
198
|
+
}
|
|
199
|
+
</style>
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
<%def name="codeblock(text, rows=0)">
|
|
203
|
+
<%
|
|
204
|
+
if rows == 0:
|
|
205
|
+
rows = text.count("\n")+1
|
|
206
|
+
%>
|
|
207
|
+
<textarea class="code" contenteditable="true" spellcheck="false" aria-label='Code Sample' rows="${rows}" readonly>
|
|
208
|
+
${text}
|
|
209
|
+
</textarea>
|
|
210
|
+
</%def>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pythonista-wkapp"
|
|
3
|
+
requires-python = ">= 3.10"
|
|
4
|
+
dependencies = [
|
|
5
|
+
"bottle >= 0.13.4",
|
|
6
|
+
"Mako",
|
|
7
|
+
"requests"
|
|
8
|
+
]
|
|
9
|
+
authors = [
|
|
10
|
+
{name = "M4nw3l", email = "63550247+M4nw3l@users.noreply.github.com"},
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Operating System :: iOS",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
20
|
+
"Topic :: Software Development :: User Interfaces"
|
|
21
|
+
]
|
|
22
|
+
dynamic = ["version", "description"]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/m4nw3l/pythonista-wkapp"
|
|
26
|
+
|
|
27
|
+
[tool.flit.module]
|
|
28
|
+
name = "wkapp"
|
|
29
|
+
|
|
30
|
+
[tool.flit.sdist]
|
|
31
|
+
exclude = ["**/.*/"]
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["flit_core >=3.11,<4"]
|
|
35
|
+
build-backend = "flit_core.buildapi"
|