qseweb 1.0.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.
- qseweb-1.0.2/LICENSE +21 -0
- qseweb-1.0.2/PKG-INFO +157 -0
- qseweb-1.0.2/README.md +131 -0
- qseweb-1.0.2/pyproject.toml +37 -0
- qseweb-1.0.2/qseweb/__init__.py +147 -0
- qseweb-1.0.2/qseweb/_qseweb_core.pyd +0 -0
- qseweb-1.0.2/qseweb.egg-info/PKG-INFO +157 -0
- qseweb-1.0.2/qseweb.egg-info/SOURCES.txt +9 -0
- qseweb-1.0.2/qseweb.egg-info/dependency_links.txt +1 -0
- qseweb-1.0.2/qseweb.egg-info/top_level.txt +1 -0
- qseweb-1.0.2/setup.cfg +4 -0
qseweb-1.0.2/LICENSE
ADDED
|
@@ -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.
|
qseweb-1.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qseweb
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: High-performance Flask-like web framework with C++ backend
|
|
5
|
+
Author: Qarvexium
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: web,framework,http,server,flask,async,performance,c++
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: C++
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
22
|
+
Requires-Python: >=3.7
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# QSEWeb
|
|
28
|
+
|
|
29
|
+
High-performance web framework with C++ backend. Call Python from JavaScript easily.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install qseweb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Example
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import qseweb
|
|
41
|
+
|
|
42
|
+
app = qseweb.QSEWeb()
|
|
43
|
+
|
|
44
|
+
@app.assign("Btn")
|
|
45
|
+
def button():
|
|
46
|
+
print("Button clicked")
|
|
47
|
+
return "success"
|
|
48
|
+
|
|
49
|
+
@app.serve("/")
|
|
50
|
+
def main():
|
|
51
|
+
return """
|
|
52
|
+
<html>
|
|
53
|
+
<body>
|
|
54
|
+
<h1>Click the button</h1>
|
|
55
|
+
<button onclick="button()">Click me</button>
|
|
56
|
+
|
|
57
|
+
<script>
|
|
58
|
+
async function button() {
|
|
59
|
+
const response = await qse.Btn();
|
|
60
|
+
alert(response);
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
print("Starting server on http://localhost:5000")
|
|
68
|
+
app.run()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's it! Run it and click the button.
|
|
72
|
+
|
|
73
|
+
## How it works
|
|
74
|
+
|
|
75
|
+
1. Use `@app.assign("name")` to expose Python functions
|
|
76
|
+
2. Call them from JavaScript with `await qse.name()`
|
|
77
|
+
3. Python function runs, returns result to JavaScript
|
|
78
|
+
|
|
79
|
+
## API
|
|
80
|
+
|
|
81
|
+
### Create app
|
|
82
|
+
```python
|
|
83
|
+
app = qseweb.QSEWeb() # Default: 0.0.0.0:5000
|
|
84
|
+
app = qseweb.QSEWeb(port=8080) # Custom port
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Make routes
|
|
88
|
+
```python
|
|
89
|
+
@app.serve("/")
|
|
90
|
+
def home():
|
|
91
|
+
return "<h1>Hello</h1>"
|
|
92
|
+
|
|
93
|
+
@app.serve("/about")
|
|
94
|
+
def about():
|
|
95
|
+
return "<h1>About page</h1>"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Call Python from JavaScript
|
|
99
|
+
```python
|
|
100
|
+
@app.assign("greet")
|
|
101
|
+
def greet(name):
|
|
102
|
+
return f"Hello {name}!"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
const msg = await qse.greet("World"); // "Hello World!"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Get request data
|
|
110
|
+
```python
|
|
111
|
+
@app.serve("/api")
|
|
112
|
+
def api(request):
|
|
113
|
+
user_id = request['query'].get('id') # Query params
|
|
114
|
+
method = request['method'] # GET, POST, etc
|
|
115
|
+
path = request['path'] # URL path
|
|
116
|
+
body = request.get('body', '') # Request body
|
|
117
|
+
return f"User: {user_id}"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Stop server
|
|
121
|
+
```python
|
|
122
|
+
app.stop()
|
|
123
|
+
|
|
124
|
+
# Or from web:
|
|
125
|
+
@app.serve("/shutdown")
|
|
126
|
+
def shutdown():
|
|
127
|
+
import threading
|
|
128
|
+
threading.Thread(target=app.stop, daemon=True).start()
|
|
129
|
+
return "Stopping..."
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Examples
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
python examples/basic.py # Hello world
|
|
136
|
+
python examples/javascript_bridge.py # JS ↔ Python
|
|
137
|
+
python examples/server_control.py # Start/stop
|
|
138
|
+
python examples/advanced.py # Full demo
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Features
|
|
142
|
+
|
|
143
|
+
- ✅ Flask-like API
|
|
144
|
+
- ✅ Call Python from JavaScript (`qse.function()`)
|
|
145
|
+
- ✅ Multi-threaded C++ backend
|
|
146
|
+
- ✅ Fast routing
|
|
147
|
+
- ✅ Async with Ctrl+C support
|
|
148
|
+
- ✅ Pre-compiled (no build needed)
|
|
149
|
+
|
|
150
|
+
## Requirements
|
|
151
|
+
|
|
152
|
+
- Python 3.7+
|
|
153
|
+
- Windows (pre-compiled .pyd included)
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
qseweb-1.0.2/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# QSEWeb
|
|
2
|
+
|
|
3
|
+
High-performance web framework with C++ backend. Call Python from JavaScript easily.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install qseweb
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import qseweb
|
|
15
|
+
|
|
16
|
+
app = qseweb.QSEWeb()
|
|
17
|
+
|
|
18
|
+
@app.assign("Btn")
|
|
19
|
+
def button():
|
|
20
|
+
print("Button clicked")
|
|
21
|
+
return "success"
|
|
22
|
+
|
|
23
|
+
@app.serve("/")
|
|
24
|
+
def main():
|
|
25
|
+
return """
|
|
26
|
+
<html>
|
|
27
|
+
<body>
|
|
28
|
+
<h1>Click the button</h1>
|
|
29
|
+
<button onclick="button()">Click me</button>
|
|
30
|
+
|
|
31
|
+
<script>
|
|
32
|
+
async function button() {
|
|
33
|
+
const response = await qse.Btn();
|
|
34
|
+
alert(response);
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
</body>
|
|
38
|
+
</html>
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
print("Starting server on http://localhost:5000")
|
|
42
|
+
app.run()
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
That's it! Run it and click the button.
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
|
|
49
|
+
1. Use `@app.assign("name")` to expose Python functions
|
|
50
|
+
2. Call them from JavaScript with `await qse.name()`
|
|
51
|
+
3. Python function runs, returns result to JavaScript
|
|
52
|
+
|
|
53
|
+
## API
|
|
54
|
+
|
|
55
|
+
### Create app
|
|
56
|
+
```python
|
|
57
|
+
app = qseweb.QSEWeb() # Default: 0.0.0.0:5000
|
|
58
|
+
app = qseweb.QSEWeb(port=8080) # Custom port
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Make routes
|
|
62
|
+
```python
|
|
63
|
+
@app.serve("/")
|
|
64
|
+
def home():
|
|
65
|
+
return "<h1>Hello</h1>"
|
|
66
|
+
|
|
67
|
+
@app.serve("/about")
|
|
68
|
+
def about():
|
|
69
|
+
return "<h1>About page</h1>"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Call Python from JavaScript
|
|
73
|
+
```python
|
|
74
|
+
@app.assign("greet")
|
|
75
|
+
def greet(name):
|
|
76
|
+
return f"Hello {name}!"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
const msg = await qse.greet("World"); // "Hello World!"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Get request data
|
|
84
|
+
```python
|
|
85
|
+
@app.serve("/api")
|
|
86
|
+
def api(request):
|
|
87
|
+
user_id = request['query'].get('id') # Query params
|
|
88
|
+
method = request['method'] # GET, POST, etc
|
|
89
|
+
path = request['path'] # URL path
|
|
90
|
+
body = request.get('body', '') # Request body
|
|
91
|
+
return f"User: {user_id}"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Stop server
|
|
95
|
+
```python
|
|
96
|
+
app.stop()
|
|
97
|
+
|
|
98
|
+
# Or from web:
|
|
99
|
+
@app.serve("/shutdown")
|
|
100
|
+
def shutdown():
|
|
101
|
+
import threading
|
|
102
|
+
threading.Thread(target=app.stop, daemon=True).start()
|
|
103
|
+
return "Stopping..."
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Examples
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
python examples/basic.py # Hello world
|
|
110
|
+
python examples/javascript_bridge.py # JS ↔ Python
|
|
111
|
+
python examples/server_control.py # Start/stop
|
|
112
|
+
python examples/advanced.py # Full demo
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Features
|
|
116
|
+
|
|
117
|
+
- ✅ Flask-like API
|
|
118
|
+
- ✅ Call Python from JavaScript (`qse.function()`)
|
|
119
|
+
- ✅ Multi-threaded C++ backend
|
|
120
|
+
- ✅ Fast routing
|
|
121
|
+
- ✅ Async with Ctrl+C support
|
|
122
|
+
- ✅ Pre-compiled (no build needed)
|
|
123
|
+
|
|
124
|
+
## Requirements
|
|
125
|
+
|
|
126
|
+
- Python 3.7+
|
|
127
|
+
- Windows (pre-compiled .pyd included)
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=45", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "qseweb"
|
|
7
|
+
version = "1.0.2"
|
|
8
|
+
description = "High-performance Flask-like web framework with C++ backend"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.7"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Qarvexium"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["web", "framework", "http", "server", "flask", "async", "performance", "c++"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.7",
|
|
22
|
+
"Programming Language :: Python :: 3.8",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Programming Language :: C++",
|
|
29
|
+
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
|
30
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[tool.setuptools]
|
|
34
|
+
packages = ["qseweb"]
|
|
35
|
+
|
|
36
|
+
[tool.setuptools.package-data]
|
|
37
|
+
qseweb = ["*.pyd", "*.so", "*.dll"]
|
|
@@ -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,157 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qseweb
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: High-performance Flask-like web framework with C++ backend
|
|
5
|
+
Author: Qarvexium
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: web,framework,http,server,flask,async,performance,c++
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: C++
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
22
|
+
Requires-Python: >=3.7
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# QSEWeb
|
|
28
|
+
|
|
29
|
+
High-performance web framework with C++ backend. Call Python from JavaScript easily.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install qseweb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Example
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import qseweb
|
|
41
|
+
|
|
42
|
+
app = qseweb.QSEWeb()
|
|
43
|
+
|
|
44
|
+
@app.assign("Btn")
|
|
45
|
+
def button():
|
|
46
|
+
print("Button clicked")
|
|
47
|
+
return "success"
|
|
48
|
+
|
|
49
|
+
@app.serve("/")
|
|
50
|
+
def main():
|
|
51
|
+
return """
|
|
52
|
+
<html>
|
|
53
|
+
<body>
|
|
54
|
+
<h1>Click the button</h1>
|
|
55
|
+
<button onclick="button()">Click me</button>
|
|
56
|
+
|
|
57
|
+
<script>
|
|
58
|
+
async function button() {
|
|
59
|
+
const response = await qse.Btn();
|
|
60
|
+
alert(response);
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
print("Starting server on http://localhost:5000")
|
|
68
|
+
app.run()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's it! Run it and click the button.
|
|
72
|
+
|
|
73
|
+
## How it works
|
|
74
|
+
|
|
75
|
+
1. Use `@app.assign("name")` to expose Python functions
|
|
76
|
+
2. Call them from JavaScript with `await qse.name()`
|
|
77
|
+
3. Python function runs, returns result to JavaScript
|
|
78
|
+
|
|
79
|
+
## API
|
|
80
|
+
|
|
81
|
+
### Create app
|
|
82
|
+
```python
|
|
83
|
+
app = qseweb.QSEWeb() # Default: 0.0.0.0:5000
|
|
84
|
+
app = qseweb.QSEWeb(port=8080) # Custom port
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Make routes
|
|
88
|
+
```python
|
|
89
|
+
@app.serve("/")
|
|
90
|
+
def home():
|
|
91
|
+
return "<h1>Hello</h1>"
|
|
92
|
+
|
|
93
|
+
@app.serve("/about")
|
|
94
|
+
def about():
|
|
95
|
+
return "<h1>About page</h1>"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Call Python from JavaScript
|
|
99
|
+
```python
|
|
100
|
+
@app.assign("greet")
|
|
101
|
+
def greet(name):
|
|
102
|
+
return f"Hello {name}!"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
const msg = await qse.greet("World"); // "Hello World!"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Get request data
|
|
110
|
+
```python
|
|
111
|
+
@app.serve("/api")
|
|
112
|
+
def api(request):
|
|
113
|
+
user_id = request['query'].get('id') # Query params
|
|
114
|
+
method = request['method'] # GET, POST, etc
|
|
115
|
+
path = request['path'] # URL path
|
|
116
|
+
body = request.get('body', '') # Request body
|
|
117
|
+
return f"User: {user_id}"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Stop server
|
|
121
|
+
```python
|
|
122
|
+
app.stop()
|
|
123
|
+
|
|
124
|
+
# Or from web:
|
|
125
|
+
@app.serve("/shutdown")
|
|
126
|
+
def shutdown():
|
|
127
|
+
import threading
|
|
128
|
+
threading.Thread(target=app.stop, daemon=True).start()
|
|
129
|
+
return "Stopping..."
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Examples
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
python examples/basic.py # Hello world
|
|
136
|
+
python examples/javascript_bridge.py # JS ↔ Python
|
|
137
|
+
python examples/server_control.py # Start/stop
|
|
138
|
+
python examples/advanced.py # Full demo
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Features
|
|
142
|
+
|
|
143
|
+
- ✅ Flask-like API
|
|
144
|
+
- ✅ Call Python from JavaScript (`qse.function()`)
|
|
145
|
+
- ✅ Multi-threaded C++ backend
|
|
146
|
+
- ✅ Fast routing
|
|
147
|
+
- ✅ Async with Ctrl+C support
|
|
148
|
+
- ✅ Pre-compiled (no build needed)
|
|
149
|
+
|
|
150
|
+
## Requirements
|
|
151
|
+
|
|
152
|
+
- Python 3.7+
|
|
153
|
+
- Windows (pre-compiled .pyd included)
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
qseweb
|
qseweb-1.0.2/setup.cfg
ADDED