wesktop 0.1.1__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.
- wesktop-0.1.1/.claude/settings.json +3 -0
- wesktop-0.1.1/.github/workflows/ci.yml +20 -0
- wesktop-0.1.1/.github/workflows/publish.yml +18 -0
- wesktop-0.1.1/.gitignore +24 -0
- wesktop-0.1.1/.rlsbl/bases/.claude/settings.json +3 -0
- wesktop-0.1.1/.rlsbl/bases/.github/workflows/ci.yml +21 -0
- wesktop-0.1.1/.rlsbl/bases/.github/workflows/publish.yml +18 -0
- wesktop-0.1.1/.rlsbl/bases/.gitignore +15 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/changes/unreleased.jsonl +0 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/hooks/post-release.sh +8 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/hooks/pre-checks.sh +5 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/hooks/pre-release.sh +8 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/lint/go.toml +17 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/lint/npm.toml +19 -0
- wesktop-0.1.1/.rlsbl/bases/.rlsbl/lint/python.toml +25 -0
- wesktop-0.1.1/.rlsbl/bases/CHANGELOG.md +5 -0
- wesktop-0.1.1/.rlsbl/bases/CLAUDE.md +20 -0
- wesktop-0.1.1/.rlsbl/bases/LICENSE +21 -0
- wesktop-0.1.1/.rlsbl/changes/.validated +1 -0
- wesktop-0.1.1/.rlsbl/changes/0.1.0.jsonl +11 -0
- wesktop-0.1.1/.rlsbl/changes/0.1.0.md +7 -0
- wesktop-0.1.1/.rlsbl/changes/0.1.1.jsonl +1 -0
- wesktop-0.1.1/.rlsbl/changes/0.1.1.md +3 -0
- wesktop-0.1.1/.rlsbl/changes/unreleased.jsonl +0 -0
- wesktop-0.1.1/.rlsbl/config.json +5 -0
- wesktop-0.1.1/.rlsbl/hashes.json +15 -0
- wesktop-0.1.1/.rlsbl/hooks/post-release.sh +8 -0
- wesktop-0.1.1/.rlsbl/hooks/pre-checks.sh +5 -0
- wesktop-0.1.1/.rlsbl/hooks/pre-release.sh +8 -0
- wesktop-0.1.1/.rlsbl/lint/go.toml +17 -0
- wesktop-0.1.1/.rlsbl/lint/npm.toml +19 -0
- wesktop-0.1.1/.rlsbl/lint/python.toml +25 -0
- wesktop-0.1.1/.rlsbl/version +1 -0
- wesktop-0.1.1/.selfdoc/hashes/hashes.json +10 -0
- wesktop-0.1.1/CHANGELOG.md +15 -0
- wesktop-0.1.1/CLAUDE.md +77 -0
- wesktop-0.1.1/LICENSE +21 -0
- wesktop-0.1.1/PKG-INFO +12 -0
- wesktop-0.1.1/README.md +1 -0
- wesktop-0.1.1/bin/cli.js +16 -0
- wesktop-0.1.1/docs/api.md +138 -0
- wesktop-0.1.1/docs/index.md +97 -0
- wesktop-0.1.1/package.json +29 -0
- wesktop-0.1.1/pyproject.toml +26 -0
- wesktop-0.1.1/selfdoc.json +7 -0
- wesktop-0.1.1/src/wesktop/__init__.py +86 -0
- wesktop-0.1.1/src/wesktop/asgi.py +404 -0
- wesktop-0.1.1/src/wesktop/desktop.py +39 -0
- wesktop-0.1.1/src/wesktop/entries.py +297 -0
- wesktop-0.1.1/src/wesktop/server.py +167 -0
- wesktop-0.1.1/src/wesktop/sse.py +119 -0
- wesktop-0.1.1/tests/__init__.py +0 -0
- wesktop-0.1.1/tests/test_asgi.py +841 -0
- wesktop-0.1.1/tests/test_desktop.py +108 -0
- wesktop-0.1.1/tests/test_entries.py +193 -0
- wesktop-0.1.1/tests/test_import.py +2 -0
- wesktop-0.1.1/tests/test_server.py +87 -0
- wesktop-0.1.1/tests/test_sse.py +261 -0
- wesktop-0.1.1/uv.lock +515 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: astral-sh/setup-uv@v7
|
|
18
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
19
|
+
- run: uv sync
|
|
20
|
+
- run: uv run python -c "import wesktop"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: astral-sh/setup-uv@v7
|
|
17
|
+
- run: uv build
|
|
18
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
wesktop-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.venv/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
*.egg
|
|
10
|
+
.uv/
|
|
11
|
+
|
|
12
|
+
node_modules/
|
|
13
|
+
*.pyc
|
|
14
|
+
*.log
|
|
15
|
+
.DS_Store
|
|
16
|
+
coverage/
|
|
17
|
+
.rlsbl-notes-*.tmp
|
|
18
|
+
.rlsbl/lock
|
|
19
|
+
.credentials.json
|
|
20
|
+
.*-cache.json
|
|
21
|
+
.env
|
|
22
|
+
.env.local
|
|
23
|
+
*.local-only
|
|
24
|
+
docs/_build/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
# requires-python: >= {{pypi.minRequiredPython}}
|
|
15
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
- uses: astral-sh/setup-uv@v7
|
|
19
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
20
|
+
- run: uv sync
|
|
21
|
+
- run: uv run python -c "import wesktop"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: astral-sh/setup-uv@v7
|
|
17
|
+
- run: uv build
|
|
18
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
File without changes
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Post-release hook. Runs after a successful release (non-fatal).
|
|
3
|
+
# Environment: RLSBL_VERSION is set to the released version.
|
|
4
|
+
# Customize this for your project (e.g., local install, deploy, notify).
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
echo "Post-release: v$RLSBL_VERSION"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
# Project-specific pre-release checks.
|
|
4
|
+
# Built-in checks (tests, lint) run automatically before this hook.
|
|
5
|
+
# Add custom validation here, e.g.:
|
|
6
|
+
# - Check for uncommitted documentation
|
|
7
|
+
# - Verify external service connectivity
|
|
8
|
+
# - Run integration tests not covered by the test suite
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[forbidden-imports]
|
|
2
|
+
modules = [
|
|
3
|
+
"argparse",
|
|
4
|
+
"click",
|
|
5
|
+
"typer",
|
|
6
|
+
"flask",
|
|
7
|
+
"fastapi",
|
|
8
|
+
"django",
|
|
9
|
+
"uvicorn",
|
|
10
|
+
"granian",
|
|
11
|
+
"starlette",
|
|
12
|
+
"tornado",
|
|
13
|
+
"bottle",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[stdout]
|
|
17
|
+
enabled = true
|
|
18
|
+
ignore = []
|
|
19
|
+
|
|
20
|
+
[entry-point]
|
|
21
|
+
enabled = true
|
|
22
|
+
ignore = []
|
|
23
|
+
|
|
24
|
+
[files]
|
|
25
|
+
exclude = []
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# wesktop
|
|
2
|
+
|
|
3
|
+
## Release workflow
|
|
4
|
+
|
|
5
|
+
This project uses [rlsbl](https://github.com/smm-h/rlsbl) for release orchestration.
|
|
6
|
+
|
|
7
|
+
- Update CHANGELOG.md with a `## X.Y.Z` entry describing changes
|
|
8
|
+
- Run `rlsbl release [patch|minor|major]` to bump version and create a GitHub Release
|
|
9
|
+
- CI handles publishing automatically via the publish workflow
|
|
10
|
+
- Never publish manually — always use `rlsbl release`
|
|
11
|
+
- Configure Trusted Publishing on pypi.org for automated PyPI releases
|
|
12
|
+
- Use `rlsbl release --dry-run` to preview a release without making changes
|
|
13
|
+
|
|
14
|
+
## Conventions
|
|
15
|
+
|
|
16
|
+
- No tokens or secrets in command-line arguments (use env vars or config files)
|
|
17
|
+
- All file writes to shared state should be atomic (write to tmp, then rename)
|
|
18
|
+
- External calls (APIs, CLI tools) must have timeouts and graceful fallbacks
|
|
19
|
+
- Use `npm link` (npm) or `uv pip install -e .` (Python) for local development
|
|
20
|
+
- CI runs smoke tests on every push; manual testing for UI/UX changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 smm-h
|
|
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
|
+
3540d09fa802bb88537ce076800b9b0b2801ef79
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{"commits":["d00e0a314abbc6720b06864ad8a4014e653e9a33","53b83ce974becab9c7d3d20debd682d3abf9297d","0949e1ab49d7d24616f8173cadb6a646cd04bfba"],"user_facing":false}
|
|
2
|
+
{"commits":["97e0ad7fe9f96f3a815b3f6138cd8dbd57c365df","3da18c78e2074da14a555ef30d8656b4b2c38ba2","4fe003a36934d1b53642c549a9e68936a279053f"],"user_facing":false}
|
|
3
|
+
{"commits":["128679ea96ada6f978bf01aa78cab828694e503e","a4b37f708c9822b0658d592010a1b0bbde5df001","b12f712986de331350ba98daf2ec54db58fddeef"],"user_facing":true,"description":"**Initial release.** ASGI router, SSE broadcaster, and extracted server lifecycle.","type":"feature"}
|
|
4
|
+
{"commits":["e6f466e1857c268c80f66a150d27b1e8fc0a064f","48d0d63b608e0f58ac817a4c322be5e28132f51b","e03976716edb4de95ba55122e0d00ed4ae8807de","ceb985a298b9d8b0510f6b49b6505203870450b9"],"user_facing":true,"description":"**Desktop integration.** pywebview, desktop entry creation, and public API exports.","type":"feature"}
|
|
5
|
+
{"commits":["679c1bfcbc6db58d7143a807de6fa9ee4921d979","797fc29feda110bc8893439e2652d1118ef8cfa5"],"user_facing":false}
|
|
6
|
+
{"commits":["a453cf8830b6d86e5d9bf32d540e069a5432adaf"],"user_facing":false}
|
|
7
|
+
{"commits":["2ad42e3dc9e0153ed992771f48b60f5255d8db1b"],"user_facing":false}
|
|
8
|
+
{"commits":["1e2274bfe5ae37f4b1649ee8a9c0e6228539baff"],"user_facing":false}
|
|
9
|
+
{"commits":["7c4c6b89d705bad412bd89037cb61715a0932585","01edd549dd66b46d2907a8d3f36d44f969de71c2"],"user_facing":true,"description":"**npm shim.** Install via `npm i -g @smmh/wesktop` for a global `wesktop` CLI that delegates to Python.","type":"feature"}
|
|
10
|
+
{"commits":["2c16194bae86e9398bd7083561c2aa53c37402a3"],"user_facing":false}
|
|
11
|
+
{"commits":["8d7e8fd69b946abd58bebb51a60d55c0778d5366"],"user_facing":false}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
## 0.1.0
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **Initial release.** ASGI router, SSE broadcaster, and extracted server lifecycle.
|
|
6
|
+
- **Desktop integration.** pywebview, desktop entry creation, and public API exports.
|
|
7
|
+
- **npm shim.** Install via `npm i -g @smmh/wesktop` for a global `wesktop` CLI that delegates to Python.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"commits":["e814207a9b87c4b742c70c2adf59246c38fdf804"],"user_facing":false}
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
".github/workflows/ci.yml": "c1c40dd67db0a91b305570028a0579ec03c747da0dd187f31de80a099b6fb516",
|
|
3
|
+
".github/workflows/publish.yml": "55e2dba57d17218c2887ba90051d31aee15067cc0b69c8adebc2deab07aef76b",
|
|
4
|
+
"CHANGELOG.md": "7a6ec46141007c18090a0ff325e2dd68cd51588c4e0b5af7b580365e5eaaca85",
|
|
5
|
+
".gitignore": "ce5391c115e249532a3bc27098546bb1ff2a32410b53b0d59ad7b54e765c0a04",
|
|
6
|
+
"LICENSE": "e958892abc1dd5d991fca6d528e695d335f25773d373d2e0be5f4a9507d8f8d5",
|
|
7
|
+
".rlsbl/hooks/pre-checks.sh": "60c57d4563263124530e6f33aca77550ea2161ad3b33b3ba6ad1c03fea9eb6e2",
|
|
8
|
+
".rlsbl/hooks/pre-release.sh": "b2dc17c243d0b1a2c1e23c1c25db6f94878596df81dc76c41b32d95f740a7d44",
|
|
9
|
+
".rlsbl/hooks/post-release.sh": "b455f8511e0b2655509ecf5dcb0ab7da5bb7c961f47910ff8e00cab5bd51f833",
|
|
10
|
+
".claude/settings.json": "78922a784ee78e9e50587e93628cd3b9d4dfbe49087adc4514e6781cea38cbb9",
|
|
11
|
+
".rlsbl/lint/python.toml": "9cfbcef2e010d5fad243437bf2fd8df54a1fae70ee0762f9d11da70fe207501c",
|
|
12
|
+
".rlsbl/lint/go.toml": "807d5cf760baad6d571a5bfd43cb163efe356f7462ba9f1918d72de45f62339f",
|
|
13
|
+
".rlsbl/lint/npm.toml": "baa36014e65923d8cc5c8b83c77fa651da79351627570476402da66840027645",
|
|
14
|
+
".rlsbl/changes/unreleased.jsonl": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Post-release hook. Runs after a successful release (non-fatal).
|
|
3
|
+
# Environment: RLSBL_VERSION is set to the released version.
|
|
4
|
+
# Customize this for your project (e.g., local install, deploy, notify).
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
echo "Post-release: v$RLSBL_VERSION"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
# Project-specific pre-release checks.
|
|
4
|
+
# Built-in checks (tests, lint) run automatically before this hook.
|
|
5
|
+
# Add custom validation here, e.g.:
|
|
6
|
+
# - Check for uncommitted documentation
|
|
7
|
+
# - Verify external service connectivity
|
|
8
|
+
# - Run integration tests not covered by the test suite
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[forbidden-imports]
|
|
2
|
+
modules = [
|
|
3
|
+
"argparse",
|
|
4
|
+
"click",
|
|
5
|
+
"typer",
|
|
6
|
+
"flask",
|
|
7
|
+
"fastapi",
|
|
8
|
+
"django",
|
|
9
|
+
"uvicorn",
|
|
10
|
+
"granian",
|
|
11
|
+
"starlette",
|
|
12
|
+
"tornado",
|
|
13
|
+
"bottle",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[stdout]
|
|
17
|
+
enabled = true
|
|
18
|
+
ignore = []
|
|
19
|
+
|
|
20
|
+
[entry-point]
|
|
21
|
+
enabled = true
|
|
22
|
+
ignore = []
|
|
23
|
+
|
|
24
|
+
[files]
|
|
25
|
+
exclude = []
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.36.0
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"api.md": {
|
|
3
|
+
"content": "7a853df7d84d377b3026c46995c42747190bea4ef53a1b496c255dfeb09e77e2",
|
|
4
|
+
"description": "1c49db4136318e727bafdf1f66c2c763db8914038f6e1f5c31b680aef4687ed2"
|
|
5
|
+
},
|
|
6
|
+
"index.md": {
|
|
7
|
+
"content": "448279a5ee5b07cf889a65674ac848328f2ee88f40c6f3be4f8a0bf9087335fd",
|
|
8
|
+
"description": "e11c3c93cacc51bdb50b42c2b50d609a9f0f03665eeef92ade3c01df5b86bb5f"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!-- Generated by rlsbl from .rlsbl/changes/ — do not edit -->
|
|
2
|
+
|
|
3
|
+
# Changelog
|
|
4
|
+
|
|
5
|
+
## 0.1.1
|
|
6
|
+
|
|
7
|
+
- No user-facing changes.
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- **Initial release.** ASGI router, SSE broadcaster, and extracted server lifecycle.
|
|
14
|
+
- **Desktop integration.** pywebview, desktop entry creation, and public API exports.
|
|
15
|
+
- **npm shim.** Install via `npm i -g @smmh/wesktop` for a global `wesktop` CLI that delegates to Python.
|
wesktop-0.1.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# wesktop
|
|
2
|
+
|
|
3
|
+
A Python framework for building web-based desktop applications. Uses granian (Rust-based ASGI server), pywebview (native OS windows), and msgspec (fast serialization).
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
wesktop was extracted from ProductEngine as a reusable library. It provides four layers:
|
|
8
|
+
|
|
9
|
+
1. **ASGI micro-router** (`asgi.py`) -- minimal HTTP routing with `{param}` placeholders, response type dispatch (JSON, text, HTML, bytes, streaming), static file serving, SPA fallback, WebSocket route registry, middleware chain, and async lifespan support. Zero external dependencies beyond msgspec for JSON encoding.
|
|
10
|
+
|
|
11
|
+
2. **SSE broadcaster** (`sse.py`) -- typed server-sent events with per-client async queues. Event types must be registered before broadcast (strict mode). Disconnected clients are pruned automatically when their queue fills up.
|
|
12
|
+
|
|
13
|
+
3. **Server lifecycle** (`server.py`) -- granian integration with PID file management, port availability checks, process group leadership (so worker subprocesses die with the parent), and signal handling. Supports both blocking (`start_server`) and background-thread (`start_server_in_background`) modes.
|
|
14
|
+
|
|
15
|
+
4. **Desktop window** (`desktop.py`) -- pywebview integration. Starts the server in a background thread, opens a native OS window, and blocks until the window is closed. Late-imports pywebview so headless mode has no GUI dependency.
|
|
16
|
+
|
|
17
|
+
5. **Desktop entries** (`entries.py`) -- cross-platform desktop shortcut creation and removal (Linux `.desktop` files, macOS `.app` bundles, Windows Start Menu shortcuts via COM or PowerShell).
|
|
18
|
+
|
|
19
|
+
## Module Layout
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
src/wesktop/
|
|
23
|
+
__init__.py Public API: re-exports from all modules, __version__, __all__
|
|
24
|
+
asgi.py ASGI router, request/response types, app factory, WebSocket registry
|
|
25
|
+
sse.py SSE Broadcaster and sse_route helper
|
|
26
|
+
server.py Granian lifecycle: PID files, port checks, start/stop
|
|
27
|
+
desktop.py pywebview window: start server + open native window
|
|
28
|
+
entries.py Cross-platform desktop entry creation/removal
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Dependencies
|
|
32
|
+
|
|
33
|
+
| Package | Why |
|
|
34
|
+
|---------|-----|
|
|
35
|
+
| `granian` | Rust-based ASGI server. Faster than uvicorn for production, handles process management internally. |
|
|
36
|
+
| `pywebview` | Opens native OS windows (WebKit on Linux/macOS, Edge WebView2 on Windows). Avoids Electron overhead. |
|
|
37
|
+
| `msgspec` | Fast JSON serialization/deserialization. Used in the ASGI layer for request parsing and response encoding. |
|
|
38
|
+
|
|
39
|
+
Dev dependencies: `pytest`, `httpx` (for async test client).
|
|
40
|
+
|
|
41
|
+
## Consumer Patterns
|
|
42
|
+
|
|
43
|
+
wesktop is a library, not a CLI tool. Consumers bring their own entry point and call either:
|
|
44
|
+
|
|
45
|
+
- `wesktop.run("myapp:app")` -- desktop mode (server + native window)
|
|
46
|
+
- `wesktop.serve("myapp:app")` -- headless mode (server only)
|
|
47
|
+
|
|
48
|
+
The `target` argument is an ASGI import path (e.g., `"myapp.web:app"`). Consumers create a `Router`, register routes, call `create_app()`, and then pass the module path to `run()` or `serve()`.
|
|
49
|
+
|
|
50
|
+
## Public API
|
|
51
|
+
|
|
52
|
+
All public symbols are importable from `wesktop` directly:
|
|
53
|
+
|
|
54
|
+
- **Router, Request** -- routing and request handling
|
|
55
|
+
- **JSONResponse, TextResponse, HTMLResponse, BytesResponse, StreamResponse** -- response types
|
|
56
|
+
- **create_app** -- ASGI app factory
|
|
57
|
+
- **add_ws_route** -- WebSocket route registration
|
|
58
|
+
- **Broadcaster, sse_route** -- SSE support
|
|
59
|
+
- **create_entry, remove_entry** -- desktop shortcut management
|
|
60
|
+
- **run, serve** -- entry points
|
|
61
|
+
- **__version__** -- package version from metadata
|
|
62
|
+
|
|
63
|
+
## Development
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv run pytest # Run test suite
|
|
67
|
+
selfdoc build # Build documentation
|
|
68
|
+
selfdoc serve # Serve documentation locally
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Project Structure
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
src/wesktop/ Source code
|
|
75
|
+
tests/ Test suite
|
|
76
|
+
docs/ Documentation (selfdoc templates)
|
|
77
|
+
```
|
wesktop-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 smm-h
|
|
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.
|
wesktop-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wesktop
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A Python framework for building web-based desktop applications
|
|
5
|
+
Author-email: smm-h <smmh72@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: asgi,desktop,granian,gui,pywebview,rlsbl,web
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Requires-Dist: granian>=2.7.4
|
|
11
|
+
Requires-Dist: msgspec>=0.21.1
|
|
12
|
+
Requires-Dist: pywebview>=6.2.1
|
wesktop-0.1.1/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# wesktop
|
wesktop-0.1.1/bin/cli.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { execFileSync, spawnSync } = require("child_process");
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
execFileSync("python3", ["--version"], { stdio: "pipe" });
|
|
8
|
+
} catch {
|
|
9
|
+
console.error("wesktop requires Python 3.11+. Install from https://python.org/");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const result = spawnSync("python3", ["-m", "wesktop", ...process.argv.slice(2)], {
|
|
14
|
+
stdio: "inherit",
|
|
15
|
+
});
|
|
16
|
+
process.exit(result.status ?? 1);
|