qseweb 1.0.0__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.
qseweb/__init__.py ADDED
@@ -0,0 +1,147 @@
1
+ from . import _qseweb_core
2
+ import functools
3
+ from typing import Callable, Any
4
+ import json
5
+
6
+ __version__ = "1.0.0"
7
+
8
+ class QSEWeb:
9
+
10
+ def __init__(self, host: str = "0.0.0.0", port: int = 5000):
11
+ self.host = host
12
+ self.port = port
13
+ self._initialized = False
14
+ self._js_functions = {}
15
+
16
+ def _ensure_initialized(self):
17
+ if not self._initialized:
18
+ _qseweb_core.init(self.host, self.port)
19
+ self._initialized = True
20
+ self._register_js_bridge()
21
+
22
+ def _register_js_bridge(self):
23
+ @self.serve("/__qseweb_call__")
24
+ def js_bridge():
25
+ return '{"status":"error","message":"Not implemented yet"}'
26
+
27
+ def serve(self, path: str, methods: list = None):
28
+ if methods is None:
29
+ methods = ["GET"]
30
+
31
+ def decorator(func: Callable) -> Callable:
32
+ self._ensure_initialized()
33
+ original_func = func
34
+
35
+ @functools.wraps(func)
36
+ def wrapper(request=None):
37
+ import inspect
38
+ sig = inspect.signature(original_func)
39
+ if len(sig.parameters) > 0:
40
+ result = original_func(request)
41
+ else:
42
+ result = original_func()
43
+
44
+ if isinstance(result, str) and '<html' in result.lower() and self._js_functions:
45
+ result = self._inject_js_bridge(result)
46
+ return result
47
+
48
+ for method in methods:
49
+ _qseweb_core.add_route(path, method, wrapper)
50
+
51
+ return wrapper
52
+
53
+ return decorator
54
+
55
+ def _inject_js_bridge(self, html: str) -> str:
56
+ bridge_code = """
57
+ <script>
58
+ (function() {
59
+ window.qse = window.qse || {};
60
+ const functions = """ + json.dumps(list(self._js_functions.keys())) + """;
61
+
62
+ functions.forEach(funcName => {
63
+ window.qse[funcName] = async function(...args) {
64
+ try {
65
+ const response = await fetch('/__qseweb_call__/' + funcName + '?' +
66
+ args.map((arg, i) => 'arg' + i + '=' + encodeURIComponent(arg)).join('&'));
67
+ const data = await response.json();
68
+ if (data.status === 'success') {
69
+ return data.result;
70
+ } else {
71
+ console.error('QSEWeb error:', data.message);
72
+ return null;
73
+ }
74
+ } catch (error) {
75
+ console.error('QSEWeb call failed:', error);
76
+ return null;
77
+ }
78
+ };
79
+ });
80
+
81
+ console.log('✅ QSEWeb bridge loaded. Available functions:', functions);
82
+ })();
83
+ </script>
84
+ """
85
+ if '</body>' in html:
86
+ html = html.replace('</body>', bridge_code + '</body>')
87
+ elif '</head>' in html:
88
+ html = html.replace('</head>', bridge_code + '</head>')
89
+ else:
90
+ html = html + bridge_code
91
+
92
+ return html
93
+
94
+ def assign(self, name: str):
95
+ def decorator(func: Callable) -> Callable:
96
+ self._ensure_initialized()
97
+ _qseweb_core.assign_function(name, func)
98
+ self._js_functions[name] = func
99
+ route_path = f"/__qseweb_call__/{name}"
100
+
101
+ @self.serve(route_path)
102
+ def js_handler(request=None):
103
+ if request and 'query' in request:
104
+ args = []
105
+ i = 0
106
+ while f'arg{i}' in request['query']:
107
+ args.append(request['query'][f'arg{i}'])
108
+ i += 1
109
+
110
+ try:
111
+ result = func(*args)
112
+ return json.dumps({"status": "success", "result": str(result)})
113
+ except Exception as e:
114
+ return json.dumps({"status": "error", "message": str(e)})
115
+ else:
116
+ return json.dumps({"status": "error", "message": "No request data"})
117
+
118
+ @functools.wraps(func)
119
+ def wrapper(*args, **kwargs):
120
+ return func(*args, **kwargs)
121
+
122
+ return wrapper
123
+
124
+ return decorator
125
+
126
+ def run(self):
127
+ self._ensure_initialized()
128
+ print(f" * Running on http://{self.host}:{self.port}")
129
+ print(" * Press Ctrl+C to quit")
130
+
131
+ try:
132
+ _qseweb_core.run()
133
+ except KeyboardInterrupt:
134
+ print("\n⚠️ Interrupted by Ctrl+C")
135
+ print("🛑 Shutting down server...")
136
+ _qseweb_core.stop()
137
+ print("✅ Server stopped\n")
138
+
139
+ def stop(self):
140
+ _qseweb_core.stop()
141
+
142
+
143
+ def create_app(host: str = "0.0.0.0", port: int = 5000) -> QSEWeb:
144
+ return QSEWeb(host=host, port=port)
145
+
146
+
147
+ __all__ = ["QSEWeb", "create_app"]
Binary file
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: qseweb
3
+ Version: 1.0.0
4
+ Summary: High-performance Flask-like web framework with C++ backend
5
+ Author: QSEWeb Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/qseweb
8
+ Project-URL: Documentation, https://github.com/yourusername/qseweb#readme
9
+ Project-URL: Repository, https://github.com/yourusername/qseweb
10
+ Project-URL: Issues, https://github.com/yourusername/qseweb/issues
11
+ Keywords: web,framework,http,server,flask,async,performance,c++
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: C++
24
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
25
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
26
+ Requires-Python: >=3.7
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Dynamic: license-file
30
+
31
+ # QSEWeb
32
+
33
+ High-performance web framework with C++ backend. Call Python from JavaScript easily.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install qseweb
39
+ ```
40
+
41
+ ## Example
42
+
43
+ ```python
44
+ import qseweb
45
+
46
+ app = qseweb.QSEWeb()
47
+
48
+ @app.assign("Btn")
49
+ def button():
50
+ print("Button clicked")
51
+ return "success"
52
+
53
+ @app.serve("/")
54
+ def main():
55
+ return """
56
+ <html>
57
+ <body>
58
+ <h1>Click the button</h1>
59
+ <button onclick="button()">Click me</button>
60
+
61
+ <script>
62
+ async function button() {
63
+ const response = await qse.Btn();
64
+ alert(response);
65
+ }
66
+ </script>
67
+ </body>
68
+ </html>
69
+ """
70
+
71
+ print("Starting server on http://localhost:5000")
72
+ app.run()
73
+ ```
74
+
75
+ That's it! Run it and click the button.
76
+
77
+ ## How it works
78
+
79
+ 1. Use `@app.assign("name")` to expose Python functions
80
+ 2. Call them from JavaScript with `await qse.name()`
81
+ 3. Python function runs, returns result to JavaScript
82
+
83
+ ## API
84
+
85
+ ### Create app
86
+ ```python
87
+ app = qseweb.QSEWeb() # Default: 0.0.0.0:5000
88
+ app = qseweb.QSEWeb(port=8080) # Custom port
89
+ ```
90
+
91
+ ### Make routes
92
+ ```python
93
+ @app.serve("/")
94
+ def home():
95
+ return "<h1>Hello</h1>"
96
+
97
+ @app.serve("/about")
98
+ def about():
99
+ return "<h1>About page</h1>"
100
+ ```
101
+
102
+ ### Call Python from JavaScript
103
+ ```python
104
+ @app.assign("greet")
105
+ def greet(name):
106
+ return f"Hello {name}!"
107
+ ```
108
+
109
+ ```javascript
110
+ const msg = await qse.greet("World"); // "Hello World!"
111
+ ```
112
+
113
+ ### Get request data
114
+ ```python
115
+ @app.serve("/api")
116
+ def api(request):
117
+ user_id = request['query'].get('id') # Query params
118
+ method = request['method'] # GET, POST, etc
119
+ path = request['path'] # URL path
120
+ body = request.get('body', '') # Request body
121
+ return f"User: {user_id}"
122
+ ```
123
+
124
+ ### Stop server
125
+ ```python
126
+ app.stop()
127
+
128
+ # Or from web:
129
+ @app.serve("/shutdown")
130
+ def shutdown():
131
+ import threading
132
+ threading.Thread(target=app.stop, daemon=True).start()
133
+ return "Stopping..."
134
+ ```
135
+
136
+ ## Examples
137
+
138
+ ```bash
139
+ python examples/basic.py # Hello world
140
+ python examples/javascript_bridge.py # JS ↔ Python
141
+ python examples/server_control.py # Start/stop
142
+ python examples/advanced.py # Full demo
143
+ ```
144
+
145
+ ## Features
146
+
147
+ - ✅ Flask-like API
148
+ - ✅ Call Python from JavaScript (`qse.function()`)
149
+ - ✅ Multi-threaded C++ backend
150
+ - ✅ Fast routing
151
+ - ✅ Async with Ctrl+C support
152
+ - ✅ Pre-compiled (no build needed)
153
+
154
+ ## Requirements
155
+
156
+ - Python 3.7+
157
+ - Windows (pre-compiled .pyd included)
158
+
159
+ ## License
160
+
161
+ MIT
@@ -0,0 +1,7 @@
1
+ qseweb/__init__.py,sha256=G414h8PpQtQ7h0681Y3gKyyn2i8K3QaFlJVV7d5XgIE,5036
2
+ qseweb/_qseweb_core.pyd,sha256=vUbJIjZUJGvG2eSSU84sOaslZq-wD5qofKwWjjYiW-M,142848
3
+ qseweb-1.0.0.dist-info/licenses/LICENSE,sha256=W8WcgqYeS9lGBqmCiqIlbglbjgF3OrlFQAEaK9KLDn8,1097
4
+ qseweb-1.0.0.dist-info/METADATA,sha256=5nbo57VcAz1yjEEStc7gZx6JBJcmmfm_xtSjH7OQh9Y,3955
5
+ qseweb-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
6
+ qseweb-1.0.0.dist-info/top_level.txt,sha256=OnOqpc3fbNFMKBV4DEjzjuEPdz82jhF1Glm6dsxDOqU,7
7
+ qseweb-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 QSEWeb 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 @@
1
+ qseweb