webview-python 0.99.15__py3-none-any.whl

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.
webview/__init__.py ADDED
File without changes
@@ -0,0 +1,134 @@
1
+ import ctypes
2
+ import sys
3
+ import os
4
+ import platform
5
+ import urllib.request
6
+ from pathlib import Path
7
+ from ctypes import c_int, c_char_p, c_void_p, CFUNCTYPE
8
+ import ctypes.util
9
+
10
+ def _encode_c_string(s: str) -> bytes:
11
+ return s.encode("utf-8")
12
+
13
+ def _get_webview_version():
14
+ """Get webview version from environment variable or use default"""
15
+ return os.getenv("WEBVIEW_VERSION", "0.8.1")
16
+
17
+ def _get_lib_names():
18
+ """Get platform-specific library names."""
19
+ system = platform.system().lower()
20
+ machine = platform.machine().lower()
21
+
22
+ if system == "windows":
23
+ if machine == "amd64" or machine == "x86_64":
24
+ return ["webview.dll", "WebView2Loader.dll"]
25
+ elif machine == "arm64":
26
+ raise Exception("arm64 is not supported on Windows")
27
+ elif system == "darwin":
28
+ if machine == "arm64":
29
+ return ["libwebview.aarch64.dylib"]
30
+ else:
31
+ return ["libwebview.x86_64.dylib"]
32
+ else: # linux
33
+ return ["libwebview.so"]
34
+
35
+ def _get_download_urls():
36
+ """Get the appropriate download URLs based on the platform."""
37
+ version = _get_webview_version()
38
+ return [f"https://github.com/webview/webview_deno/releases/download/{version}/{lib_name}"
39
+ for lib_name in _get_lib_names()]
40
+
41
+ def _be_sure_libraries():
42
+ """Ensure libraries exist and return paths."""
43
+ if getattr(sys, 'frozen', False):
44
+ if hasattr(sys, '_MEIPASS'):
45
+ base_dir = Path(sys._MEIPASS)
46
+ else:
47
+ base_dir = Path(sys.executable).parent / '_internal'
48
+ else:
49
+ base_dir = Path(__file__).parent
50
+
51
+ lib_dir = base_dir / "lib"
52
+ lib_names = _get_lib_names()
53
+ lib_paths = [lib_dir / lib_name for lib_name in lib_names]
54
+
55
+ # Check if any library is missing
56
+ missing_libs = [path for path in lib_paths if not path.exists()]
57
+ if not missing_libs:
58
+ return lib_paths
59
+
60
+ # Download missing libraries
61
+ download_urls = _get_download_urls()
62
+ system = platform.system().lower()
63
+
64
+ lib_dir.mkdir(parents=True, exist_ok=True)
65
+
66
+ for url, lib_path in zip(download_urls, lib_paths):
67
+ if lib_path.exists():
68
+ continue
69
+
70
+ print(f"Downloading library from {url}")
71
+ try:
72
+ req = urllib.request.Request(
73
+ url,
74
+ headers={'User-Agent': 'Mozilla/5.0'}
75
+ )
76
+ with urllib.request.urlopen(req) as response, open(lib_path, 'wb') as out_file:
77
+ out_file.write(response.read())
78
+ except Exception as e:
79
+ raise RuntimeError(f"Failed to download library: {e}")
80
+
81
+ return lib_paths
82
+
83
+ class _WebviewLibrary:
84
+ def __init__(self):
85
+ lib_names=_get_lib_names()
86
+ try:
87
+ library_path = ctypes.util.find_library(lib_names[0])
88
+ if not library_path:
89
+ library_paths = _be_sure_libraries()
90
+ self.lib = ctypes.cdll.LoadLibrary(str(library_paths[0]))
91
+ except Exception as e:
92
+ print(f"Failed to load webview library: {e}")
93
+ raise
94
+ # Define FFI functions
95
+ self.webview_create = self.lib.webview_create
96
+ self.webview_create.argtypes = [c_int, c_void_p]
97
+ self.webview_create.restype = c_void_p
98
+
99
+ self.webview_destroy = self.lib.webview_destroy
100
+ self.webview_destroy.argtypes = [c_void_p]
101
+
102
+ self.webview_run = self.lib.webview_run
103
+ self.webview_run.argtypes = [c_void_p]
104
+
105
+ self.webview_terminate = self.lib.webview_terminate
106
+ self.webview_terminate.argtypes = [c_void_p]
107
+
108
+ self.webview_set_title = self.lib.webview_set_title
109
+ self.webview_set_title.argtypes = [c_void_p, c_char_p]
110
+
111
+ self.webview_set_size = self.lib.webview_set_size
112
+ self.webview_set_size.argtypes = [c_void_p, c_int, c_int, c_int]
113
+
114
+ self.webview_navigate = self.lib.webview_navigate
115
+ self.webview_navigate.argtypes = [c_void_p, c_char_p]
116
+
117
+ self.webview_init = self.lib.webview_init
118
+ self.webview_init.argtypes = [c_void_p, c_char_p]
119
+
120
+ self.webview_eval = self.lib.webview_eval
121
+ self.webview_eval.argtypes = [c_void_p, c_char_p]
122
+
123
+ self.webview_bind = self.lib.webview_bind
124
+ self.webview_bind.argtypes = [c_void_p, c_char_p, c_void_p, c_void_p]
125
+
126
+ self.webview_unbind = self.lib.webview_unbind
127
+ self.webview_unbind.argtypes = [c_void_p, c_char_p]
128
+
129
+ self.webview_return = self.lib.webview_return
130
+ self.webview_return.argtypes = [c_void_p, c_char_p, c_int, c_char_p]
131
+
132
+ self.CFUNCTYPE = CFUNCTYPE
133
+
134
+ _webview_lib = _WebviewLibrary()
webview/webview.py ADDED
@@ -0,0 +1,92 @@
1
+ from enum import IntEnum
2
+ from typing import Optional, Callable, Any
3
+ import json
4
+ import ctypes
5
+ from ._webview_ffi import _webview_lib, _encode_c_string
6
+
7
+ class SizeHint(IntEnum):
8
+ NONE = 0
9
+ MIN = 1
10
+ MAX = 2
11
+ FIXED = 3
12
+
13
+ class Size:
14
+ def __init__(self, width: int, height: int, hint: SizeHint):
15
+ self.width = width
16
+ self.height = height
17
+ self.hint = hint
18
+
19
+ class Webview:
20
+ def __init__(self, debug: bool = False, size: Optional[Size] = None, window: Optional[int] = None):
21
+ self._handle = _webview_lib.webview_create(int(debug), window)
22
+ self._callbacks = {}
23
+
24
+ if size:
25
+ self.size = size
26
+
27
+ @property
28
+ def size(self) -> Size:
29
+ return self._size
30
+
31
+ @size.setter
32
+ def size(self, value: Size):
33
+ _webview_lib.webview_set_size(self._handle, value.width, value.height, value.hint)
34
+ self._size = value
35
+
36
+ @property
37
+ def title(self) -> str:
38
+ return self._title
39
+
40
+ @title.setter
41
+ def title(self, value: str):
42
+ _webview_lib.webview_set_title(self._handle, _encode_c_string(value))
43
+ self._title = value
44
+
45
+ def destroy(self):
46
+ for name in list(self._callbacks.keys()):
47
+ self.unbind(name)
48
+ _webview_lib.webview_terminate(self._handle)
49
+ _webview_lib.webview_destroy(self._handle)
50
+ self._handle = None
51
+
52
+ def navigate(self, url: str):
53
+ _webview_lib.webview_navigate(self._handle, _encode_c_string(url))
54
+
55
+ def run(self):
56
+ _webview_lib.webview_run(self._handle)
57
+ self.destroy()
58
+
59
+ def bind(self, name: str, callback: Callable[..., Any]):
60
+ def wrapper(seq: bytes, req: bytes, arg: int):
61
+ args = json.loads(req.decode())
62
+ try:
63
+ result = callback(*args)
64
+ success = True
65
+ except Exception as e:
66
+ result = str(e)
67
+ success = False
68
+ self.return_(seq.decode(), 0 if success else 1, json.dumps(result))
69
+
70
+ c_callback = _webview_lib.CFUNCTYPE(None, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p)(wrapper)
71
+ self._callbacks[name] = c_callback
72
+ _webview_lib.webview_bind(self._handle, _encode_c_string(name), c_callback, None)
73
+
74
+ def unbind(self, name: str):
75
+ if name in self._callbacks:
76
+ _webview_lib.webview_unbind(self._handle, _encode_c_string(name))
77
+ del self._callbacks[name]
78
+
79
+ def return_(self, seq: str, status: int, result: str):
80
+ _webview_lib.webview_return(self._handle, _encode_c_string(seq), status, _encode_c_string(result))
81
+
82
+ def eval(self, source: str):
83
+ _webview_lib.webview_eval(self._handle, _encode_c_string(source))
84
+
85
+ def init(self, source: str):
86
+ _webview_lib.webview_init(self._handle, _encode_c_string(source))
87
+
88
+ if __name__ == "__main__":
89
+ wv = Webview()
90
+ wv.title = "Hello, World!"
91
+ wv.navigate("https://www.google.com")
92
+ wv.run()
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Python Webview Contributors
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,292 @@
1
+ Metadata-Version: 2.1
2
+ Name: webview_python
3
+ Version: 0.99.15
4
+ Summary: Python bindings for the webview library, which completely follow deno_webview design and principles
5
+ License: MIT License
6
+
7
+ Copyright (c) 2024 Python Webview Contributors
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+
27
+ Project-URL: Homepage, https://github.com/congzhangzh/webview_python
28
+ Project-URL: Repository, https://github.com/congzhangzh/webview_python.git
29
+ Project-URL: Bug Tracker, https://github.com/congzhangzh/webview_python/issues
30
+ Keywords: webview,gui,desktop,application,html,web
31
+ Classifier: Development Status :: 3 - Alpha
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Classifier: Programming Language :: Python
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.8
38
+ Classifier: Programming Language :: Python :: 3.9
39
+ Classifier: Programming Language :: Python :: 3.10
40
+ Classifier: Programming Language :: Python :: 3.11
41
+ Classifier: Programming Language :: Python :: 3.12
42
+ Classifier: Programming Language :: Python :: Implementation :: CPython
43
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
44
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
+ Classifier: Topic :: Software Development :: User Interfaces
46
+ Requires-Python: >=3.8
47
+ Description-Content-Type: text/markdown
48
+ License-File: LICENSE
49
+
50
+ # Webview Python
51
+
52
+ [![Test - Windows](https://github.com/congzhangzh/webview_python/actions/workflows/test.yml/badge.svg?branch=main&event=push&label=Windows)](https://github.com/congzhangzh/webview_python/actions/workflows/test.yml)
53
+ [![Test - Linux](https://github.com/congzhangzh/webview_python/actions/workflows/test.yml/badge.svg?branch=main&event=push&label=Linux)](https://github.com/congzhangzh/webview_python/actions/workflows/test.yml)
54
+ [![Test - macOS](https://github.com/congzhangzh/webview_python/actions/workflows/test.yml/badge.svg?branch=main&event=push&label=macOS)](https://github.com/congzhangzh/webview_python/actions/workflows/test.yml)
55
+ [![PyPI version](https://badge.fury.io/py/webview_python.svg)](https://badge.fury.io/py/webview_python)
56
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
57
+ [![Python Version](https://img.shields.io/pypi/pyversions/webview_python.svg)](https://pypi.org/project/webview_python/)
58
+
59
+ Python bindings for the webview library, allowing you to create desktop applications with web technologies.
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ pip install webview_python
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ ### Display Inline HTML:
70
+
71
+ ```python
72
+ from webview.webview import Webview
73
+ from urllib.parse import quote
74
+
75
+ html = """
76
+ <html>
77
+ <body>
78
+ <h1>Hello from Python Webview!</h1>
79
+ </body>
80
+ </html>
81
+ """
82
+ webview = Webview()
83
+ webview.navigate(f"data:text/html,{quote(html)}")
84
+ webview.run()
85
+ ```
86
+
87
+ ### Load Local HTML File:
88
+
89
+ ```python
90
+ from webview.webview import Webview
91
+ import os
92
+
93
+ webview = Webview()
94
+ current_dir = os.path.dirname(os.path.abspath(__file__))
95
+ html_path = os.path.join(current_dir, 'local.html')
96
+ webview.navigate(f"file://{html_path}")
97
+ webview.run()
98
+ ```
99
+
100
+ ### Load Remote URL:
101
+
102
+ ```python
103
+ from webview.webview import Webview
104
+ webview = Webview()
105
+ webview.navigate("https://www.python.org")
106
+ webview.run()
107
+ ```
108
+
109
+ ### Python-JavaScript Bindings:
110
+
111
+ ```python
112
+ from webview.webview import Webview, Size, SizeHint
113
+ from urllib.parse import quote
114
+
115
+ webview = Webview(debug=True)
116
+
117
+ # Python functions that can be called from JavaScript
118
+ def hello():
119
+ webview.eval("updateFromPython('Hello from Python!')")
120
+ return "Hello from Python!"
121
+
122
+ def add(a, b):
123
+ return a + b
124
+
125
+ # Bind Python functions
126
+ webview.bind("hello", hello)
127
+ webview.bind("add", add)
128
+
129
+ # Configure window
130
+ webview.title = "Python-JavaScript Binding Demo"
131
+ webview.size = Size(640, 480, SizeHint.FIXED)
132
+
133
+ # Load HTML with JavaScript
134
+ html = """
135
+ <html>
136
+ <head>
137
+ <title>Python-JavaScript Binding Demo</title>
138
+ <script>
139
+ async function callPython() {
140
+ const result = await hello();
141
+ document.getElementById('result').innerHTML = result;
142
+ }
143
+
144
+ async function callPythonWithArgs() {
145
+ const result = await add(40, 2);
146
+ document.getElementById('result').innerHTML = `Result: ${result}`;
147
+ }
148
+
149
+ function updateFromPython(message) {
150
+ document.getElementById('result').innerHTML = `Python says: ${message}`;
151
+ }
152
+ </script>
153
+ </head>
154
+ <body>
155
+ <h1>Python-JavaScript Binding Demo</h1>
156
+ <button onclick="callPython()">Call Python</button>
157
+ <button onclick="callPythonWithArgs()">Call Python with Args</button>
158
+ <div id="result"></div>
159
+ </body>
160
+ </html>
161
+ """
162
+
163
+ webview.navigate(f"data:text/html,{quote(html)}")
164
+ webview.run()
165
+ ```
166
+
167
+ ## Features
168
+
169
+ - Create desktop applications using HTML, CSS, and JavaScript
170
+ - Load local HTML files or remote URLs
171
+ - Bidirectional Python-JavaScript communication
172
+ - Window size and title customization
173
+ - Debug mode for development
174
+ - Cross-platform support (Windows, macOS, Linux)
175
+
176
+ ## Development
177
+
178
+ ### Setup Development Environment
179
+
180
+ ```bash
181
+ # Install Python build tools
182
+ pip install --upgrade pip build twine
183
+
184
+ # Install GitHub CLI (choose one based on your OS):
185
+ # macOS
186
+ brew install gh
187
+
188
+ # Windows
189
+ winget install GitHub.cli
190
+ # or
191
+ choco install gh
192
+
193
+ # Linux (Debian/Ubuntu)
194
+ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
195
+ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
196
+ && sudo apt update \
197
+ && sudo apt install gh
198
+ ```
199
+
200
+ ### Running Tests
201
+
202
+ ```bash
203
+ python -m unittest discover tests
204
+ ```
205
+
206
+ ### Project Structure
207
+
208
+ ```
209
+ webview_python/
210
+ ├── src/
211
+ │ ├── webview.py # Main webview implementation
212
+ │ └── ffi.py # Foreign Function Interface
213
+ ├── examples/ # Example applications
214
+ ├── tests/ # Unit tests
215
+ └── README.md # Documentation
216
+ ```
217
+
218
+ ### Release Process
219
+
220
+ For maintainers who want to release a new version:
221
+ 1. **Test**
222
+ ```bash
223
+ # Install dependencies if not installed
224
+ pip install -r requirements.txt
225
+
226
+ # Run tests
227
+ pytest
228
+
229
+ # Build wheels
230
+ python -m build -n -w
231
+ ```
232
+
233
+ 2. **Update Version**
234
+ ```bash
235
+ # Ensure you have the latest code
236
+ git pull origin main
237
+
238
+ # Update version in pyproject.toml
239
+ # Edit version = "x.y.z" to new version number
240
+ ```
241
+
242
+ 3. **Create Release**
243
+ ```bash
244
+ # Commit changes
245
+ old_version=0.99.0
246
+ new_version=0.99.1
247
+ git add pyproject.toml
248
+ git commit -m "Bump version to ${new_version}"
249
+ git push origin main
250
+
251
+ # Create and push tag
252
+ git tag v${new_version}
253
+ git push origin v${new_version}
254
+
255
+ # Create GitHub release
256
+ gh release create v${new_version} --title "${new_version}" \
257
+ --notes "Full Changelog: https://github.com/congzhangzh/webview_python/compare/v${old_version}...v${new_version}"
258
+ ```
259
+
260
+ 4. **Monitor Release**
261
+ - Check GitHub Actions progress in the Actions tab
262
+ - Verify package on PyPI after workflow completion
263
+
264
+ ### First-time Release Setup
265
+
266
+ 1. **PyPI Setup**
267
+ - Create account: https://pypi.org/account/register/
268
+ - Generate API token: https://pypi.org/manage/account/token/
269
+
270
+ 2. **GitHub Setup**
271
+ - Repository Settings → Secrets and variables → Actions
272
+ - Add new secret: `PYPI_API_TOKEN` with PyPI token value
273
+
274
+ ## Roadmap
275
+
276
+ - [ ] Publish to PyPI
277
+ - [ ] Setup GitHub Actions for CI/CD
278
+ - [ ] Add preact example
279
+ - [ ] Add three.js example
280
+ - [ ] Add three.js fiber example
281
+ - [ ] Add screen saver 4 window example
282
+ - [ ] Add MRI principle demo example by three.js fiber
283
+ - [ ] Add screen saver 4 windows with MRI principle demo example by three.js fiber
284
+
285
+ ## References
286
+
287
+ - [Webview](https://github.com/webview/webview)
288
+ - [webview_deno](https://github.com/eliassjogreen/webview_deno)
289
+
290
+ # License
291
+
292
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,8 @@
1
+ webview/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ webview/_webview_ffi.py,sha256=xe3-MVoA7f-ZdhaNa3c_XBT35jQMDC7yKr80YXBvo60,4616
3
+ webview/webview.py,sha256=AlW5SnasXeWS4skhwu30b0Upfr90SobVKU37MUZVTqc,2931
4
+ webview_python-0.99.15.dist-info/LICENSE,sha256=I4hXdAjGE4JH-VoHpo4KKCdxNskzk_ECEhBjwP70xSU,1084
5
+ webview_python-0.99.15.dist-info/METADATA,sha256=mabkhCU3vWyiGMhiqWjKhEsLPMM_BR-TjYMtJIXXu88,9223
6
+ webview_python-0.99.15.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
7
+ webview_python-0.99.15.dist-info/top_level.txt,sha256=d5SpaV1yBkWk3tar-VrEOX-bBM9jXPlVdVNpN5FQrxA,8
8
+ webview_python-0.99.15.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.3.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ webview