FluxScript 0.1.0__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.
Potentially problematic release.
This version of FluxScript might be problematic. Click here for more details.
- fluxscript-0.1.0/.github/workflows/ci.yml +50 -0
- fluxscript-0.1.0/CHANGELOG.md +11 -0
- fluxscript-0.1.0/CONTRIBUTING.md +17 -0
- fluxscript-0.1.0/FluxScript.egg-info/PKG-INFO +141 -0
- fluxscript-0.1.0/FluxScript.egg-info/SOURCES.txt +41 -0
- fluxscript-0.1.0/FluxScript.egg-info/dependency_links.txt +1 -0
- fluxscript-0.1.0/FluxScript.egg-info/entry_points.txt +3 -0
- fluxscript-0.1.0/FluxScript.egg-info/requires.txt +5 -0
- fluxscript-0.1.0/FluxScript.egg-info/top_level.txt +1 -0
- fluxscript-0.1.0/FluxScript_Release.ipynb +283 -0
- fluxscript-0.1.0/LICENSE +21 -0
- fluxscript-0.1.0/MANIFEST.in +13 -0
- fluxscript-0.1.0/PKG-INFO +141 -0
- fluxscript-0.1.0/README.md +120 -0
- fluxscript-0.1.0/SECURITY.md +15 -0
- fluxscript-0.1.0/TEST_REPORT.md +30 -0
- fluxscript-0.1.0/docs/ARCHITECTURE.md +24 -0
- fluxscript-0.1.0/docs/COMMANDS.md +65 -0
- fluxscript-0.1.0/docs/INTEGRATION_NOTES.md +18 -0
- fluxscript-0.1.0/docs/PYPI_RELEASE.md +40 -0
- fluxscript-0.1.0/docs/ROADMAP.md +30 -0
- fluxscript-0.1.0/examples/app.py +9 -0
- fluxscript-0.1.0/fluxscript/__init__.py +5 -0
- fluxscript-0.1.0/fluxscript/__main__.py +2 -0
- fluxscript-0.1.0/fluxscript/analyzer.py +72 -0
- fluxscript-0.1.0/fluxscript/backends/__init__.py +6 -0
- fluxscript-0.1.0/fluxscript/backends/android.py +127 -0
- fluxscript-0.1.0/fluxscript/backends/cli.py +50 -0
- fluxscript-0.1.0/fluxscript/backends/ios.py +66 -0
- fluxscript-0.1.0/fluxscript/backends/web.py +140 -0
- fluxscript-0.1.0/fluxscript/cli.py +303 -0
- fluxscript-0.1.0/fluxscript/dependencies.py +96 -0
- fluxscript-0.1.0/fluxscript/dsl.py +25 -0
- fluxscript-0.1.0/fluxscript/integrations/__init__.py +23 -0
- fluxscript-0.1.0/fluxscript/integrations/commands.py +29 -0
- fluxscript-0.1.0/fluxscript/integrations/execution_service.py +50 -0
- fluxscript-0.1.0/fluxscript/models.py +56 -0
- fluxscript-0.1.0/fluxscript/parser.py +82 -0
- fluxscript-0.1.0/fluxscript/project.py +74 -0
- fluxscript-0.1.0/fluxscript/version.py +1 -0
- fluxscript-0.1.0/pyproject.toml +34 -0
- fluxscript-0.1.0/setup.cfg +4 -0
- fluxscript-0.1.0/tests/test_core.py +122 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: FluxScript CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: fluxscript-ci-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
python:
|
|
16
|
+
name: Python ${{ matrix.python-version }}
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
python-version: ['3.10', '3.11', '3.12', '3.13']
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
- run: python -m pip install --upgrade pip build
|
|
28
|
+
- run: python -m compileall -q fluxscript tests
|
|
29
|
+
- run: python -m unittest discover -s tests -v
|
|
30
|
+
- run: python -m build
|
|
31
|
+
- run: python -m pip install --no-deps dist/fluxscript-0.1.0-py3-none-any.whl
|
|
32
|
+
- run: fluxscript --version
|
|
33
|
+
|
|
34
|
+
web-smoke:
|
|
35
|
+
name: Generated web smoke test
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
- uses: actions/setup-python@v5
|
|
40
|
+
with:
|
|
41
|
+
python-version: '3.12'
|
|
42
|
+
- uses: actions/setup-node@v4
|
|
43
|
+
with:
|
|
44
|
+
node-version: '22'
|
|
45
|
+
- run: python -m pip install .
|
|
46
|
+
- run: fluxscript new /tmp/fluxscript-smoke
|
|
47
|
+
- run: fluxscript check /tmp/fluxscript-smoke/app.py
|
|
48
|
+
- run: fluxscript build /tmp/fluxscript-smoke/app.py --target web --out /tmp/fluxscript-smoke/build/web
|
|
49
|
+
- run: node --check /tmp/fluxscript-smoke/build/web/app.js
|
|
50
|
+
- run: cd /tmp/fluxscript-smoke/build/web && npm install && npm run typecheck
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
- Establish FluxScript's restricted declarative Python source API and shared application model.
|
|
6
|
+
- Generate web, Android, iOS and standalone CLI source projects.
|
|
7
|
+
- Add a read-only source/project analyzer with JSON reports and review findings.
|
|
8
|
+
- Add target-specific validation and on-demand upgrade of required Python helper packages.
|
|
9
|
+
- Add project export to a timestamped storage directory and ZIP archive.
|
|
10
|
+
- Add `guide`, builder, `generate-project`, and remote execution-service commands.
|
|
11
|
+
- Add a capability registry, architecture/security documentation, tests and CI workflow.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
1. Keep core runtime dependencies at zero unless a dependency is essential and justified.
|
|
4
|
+
2. Do not execute source being compiled. Extend the parser through explicit AST node allowlists and tests.
|
|
5
|
+
3. Keep the semantic model backend-neutral. Validate model constraints before any backend writes files.
|
|
6
|
+
4. Add regression tests for parser rejection cases, escaping, multi-page generation, CLI behavior and service error handling.
|
|
7
|
+
5. Run before submitting changes:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
python -m compileall -q fluxscript tests
|
|
11
|
+
python -m unittest discover -s tests -v
|
|
12
|
+
python -m pip wheel . --no-deps --no-build-isolation -w /tmp/fluxscript-wheel
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
6. If Node.js and TypeScript are available, generate a sample project and run `node --check app.js` and `tsc --noEmit`. Validate Kotlin/Gradle on a configured Android SDK/JDK and SwiftUI on macOS/Xcode; do not claim those targets build if they were not actually tested.
|
|
16
|
+
7. Never include service tokens, user source files, generated credentials or proprietary third-party code in commits.
|
|
17
|
+
8. Version changes require updating `fluxscript/version.py`, `pyproject.toml`, tests and release notes together.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: FluxScript
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: FluxScript Python-first multi-target application generator and developer CLI
|
|
5
|
+
Author: Md Safarujjaman
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: fluxscript,compiler,code-generation,python,web,android,ios
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
12
|
+
Classifier: Topic :: Software Development :: Compilers
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Provides-Extra: test
|
|
17
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
18
|
+
Requires-Dist: build>=1.2; extra == "test"
|
|
19
|
+
Requires-Dist: twine>=5.0; extra == "test"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# FluxScript 0.1.0
|
|
23
|
+
|
|
24
|
+
FluxScript is a Python-first project generator and developer command-line toolkit. It provides a restricted declarative Python source format, shared application model, web source generation, native-platform source starters, project export, and an optional remote execution-service client.
|
|
25
|
+
|
|
26
|
+
> **Release status:** 0.1.0 is an alpha. It is suitable for experimentation and generated-source workflows, not a claim that arbitrary Python compiles to every platform. Inspect generated source and validate native projects with their real toolchains before production use.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
After the package is published under the PyPI project name `FluxScript`, install it with `python -m pip install FluxScript`. Package names are case-insensitive on PyPI. Until publication, install from the source checkout using the command below.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
From the extracted source directory:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python -m pip install .
|
|
37
|
+
fluxscript --version
|
|
38
|
+
fluxscript guide
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
After FluxScript has been published to PyPI, users can install or update it with `python -m pip install --upgrade FluxScript`. It has **not** been published from this archive. FluxScript's core has no mandatory third-party runtime dependencies. When a builder is invoked, it automatically upgrades the Python helper packages required for that target's validation. Use `--no-install-deps` to disable this network/install step when the helper is already installed. This does not install operating-system toolchains.
|
|
42
|
+
|
|
43
|
+
## First project
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
fluxscript new my_app
|
|
47
|
+
cd my_app
|
|
48
|
+
fluxscript check app.py
|
|
49
|
+
fluxscript website app.py
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Preview the generated site:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd build/web
|
|
56
|
+
python -m http.server 8000
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Open `http://127.0.0.1:8000` in a browser.
|
|
60
|
+
|
|
61
|
+
## Generate a project ZIP into storage
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
fluxscript generateproject --source app.py --target web
|
|
65
|
+
fluxscript generateproject --source app.py --target android
|
|
66
|
+
fluxscript generateproject --source app.py --target ios
|
|
67
|
+
fluxscript generateproject --source app.py --target all
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This creates **both a project directory and a ZIP archive**. By default, FluxScript uses `/storage/emulated/0/FluxScriptProjects` when that shared Android storage location exists and is writable; otherwise it uses `~/FluxScriptProjects`. Specify `--storage /path/to/folder` to choose a different location.
|
|
71
|
+
|
|
72
|
+
## Builders
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
fluxscript website app.py --out build/web
|
|
76
|
+
fluxscript android app.py --out build/android
|
|
77
|
+
fluxscript ios app.py --out build/ios
|
|
78
|
+
fluxscript cli app.py --out build/cli
|
|
79
|
+
fluxscript build app.py --target all --out build/all
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- **Website:** HTML, responsive CSS, JavaScript, TypeScript, and structural HTML validation. Buttons emit action events; real business logic, APIs, authentication and persistence must be connected by the developer.
|
|
83
|
+
- **Android:** Kotlin/Gradle source project with a manifest validated by a safe XML parser. Building an APK requires a JDK, Android SDK, and compatible Gradle/Android Gradle Plugin toolchain.
|
|
84
|
+
- **iOS:** SwiftUI source starter. Building/signing an app requires macOS and Xcode. The builder does not produce an IPA.
|
|
85
|
+
- **CLI:** standalone Python `argparse` command interface for declared button actions; generated commands emit JSON action requests for application-specific handlers to consume.
|
|
86
|
+
|
|
87
|
+
The web and Android builder commands automatically upgrade their respective Python validation helper package to the latest available release. The iOS source generator has no Python helper dependency to install. Native build tools are not pip packages and are not silently downloaded.
|
|
88
|
+
|
|
89
|
+
## Remote execution service
|
|
90
|
+
|
|
91
|
+
Configure an execution API that implements the documented runtime-listing and code-execution request shape. FluxScript never starts a remote service implicitly.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
fluxscript service status
|
|
95
|
+
export FLUXSCRIPT_SERVICE_URL='http://127.0.0.1:2000/api/v2'
|
|
96
|
+
export FLUXSCRIPT_SERVICE_TOKEN='your-token-if-required'
|
|
97
|
+
fluxscript service runtimes
|
|
98
|
+
fluxscript service run python 3.12 main.py
|
|
99
|
+
fluxscript service run javascript 20.11.1 app.js --stdin-file input.txt
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Remote non-local endpoints must use HTTPS. Never send secrets or untrusted code to an execution service unless you trust its operator and isolation controls. Client-side limits do not make a server secure.
|
|
103
|
+
|
|
104
|
+
## Commands
|
|
105
|
+
|
|
106
|
+
Run `fluxscript guide` for the complete built-in command reference. Other useful commands:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
fluxscript --help
|
|
110
|
+
fluxscript new [directory]
|
|
111
|
+
fluxscript check [app.py]
|
|
112
|
+
fluxscript targets
|
|
113
|
+
fluxscript doctor
|
|
114
|
+
fluxscript integrations
|
|
115
|
+
fluxscript analyze ./source --out report.json
|
|
116
|
+
fluxscript review ./source
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Source format and security boundary
|
|
120
|
+
|
|
121
|
+
The `app.py` source is parsed using Python's AST and is **not executed**. Version 0.1.0 accepts only an explicit subset of declarative constructors, assignments, and page-registration calls. It is not a general Python interpreter or arbitrary Python-to-native compiler. Unsupported statements are rejected.
|
|
122
|
+
|
|
123
|
+
## Development and release checks
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
python -m compileall -q fluxscript tests
|
|
127
|
+
python -m unittest discover -s tests -v
|
|
128
|
+
python -m pip install build twine
|
|
129
|
+
python -m build
|
|
130
|
+
python -m twine check dist/*
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
See `docs/ARCHITECTURE.md`, `docs/COMMANDS.md`, `docs/INTEGRATION_NOTES.md`, `docs/ROADMAP.md`, and `docs/PYPI_RELEASE.md`.
|
|
134
|
+
|
|
135
|
+
## Clean command names
|
|
136
|
+
|
|
137
|
+
The CLI accepts easy-to-type commands without hyphens or underscores: `fluxscript website app.py`, `fluxscript android app.py`, `fluxscript ios app.py`, `fluxscript cli app.py`, `fluxscript generateproject --source app.py --target all`, and `fluxscript device`. Existing hyphenated commands remain supported for compatibility.
|
|
138
|
+
|
|
139
|
+
## Author
|
|
140
|
+
|
|
141
|
+
**Md Safarujjaman** is the author listed in the package metadata. Run `fluxscript developer` to display the project author and version.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
CHANGELOG.md
|
|
2
|
+
CONTRIBUTING.md
|
|
3
|
+
FluxScript_Release.ipynb
|
|
4
|
+
LICENSE
|
|
5
|
+
MANIFEST.in
|
|
6
|
+
README.md
|
|
7
|
+
SECURITY.md
|
|
8
|
+
TEST_REPORT.md
|
|
9
|
+
pyproject.toml
|
|
10
|
+
.github/workflows/ci.yml
|
|
11
|
+
FluxScript.egg-info/PKG-INFO
|
|
12
|
+
FluxScript.egg-info/SOURCES.txt
|
|
13
|
+
FluxScript.egg-info/dependency_links.txt
|
|
14
|
+
FluxScript.egg-info/entry_points.txt
|
|
15
|
+
FluxScript.egg-info/requires.txt
|
|
16
|
+
FluxScript.egg-info/top_level.txt
|
|
17
|
+
docs/ARCHITECTURE.md
|
|
18
|
+
docs/COMMANDS.md
|
|
19
|
+
docs/INTEGRATION_NOTES.md
|
|
20
|
+
docs/PYPI_RELEASE.md
|
|
21
|
+
docs/ROADMAP.md
|
|
22
|
+
examples/app.py
|
|
23
|
+
fluxscript/__init__.py
|
|
24
|
+
fluxscript/__main__.py
|
|
25
|
+
fluxscript/analyzer.py
|
|
26
|
+
fluxscript/cli.py
|
|
27
|
+
fluxscript/dependencies.py
|
|
28
|
+
fluxscript/dsl.py
|
|
29
|
+
fluxscript/models.py
|
|
30
|
+
fluxscript/parser.py
|
|
31
|
+
fluxscript/project.py
|
|
32
|
+
fluxscript/version.py
|
|
33
|
+
fluxscript/backends/__init__.py
|
|
34
|
+
fluxscript/backends/android.py
|
|
35
|
+
fluxscript/backends/cli.py
|
|
36
|
+
fluxscript/backends/ios.py
|
|
37
|
+
fluxscript/backends/web.py
|
|
38
|
+
fluxscript/integrations/__init__.py
|
|
39
|
+
fluxscript/integrations/commands.py
|
|
40
|
+
fluxscript/integrations/execution_service.py
|
|
41
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fluxscript
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# FluxScript 0.1.0 \u2014 GitHub and PyPI Release Notebook\n",
|
|
8
|
+
"\n",
|
|
9
|
+
"**Author:** Md Safarujjaman \n",
|
|
10
|
+
"**Distribution:** `FluxScript` \n",
|
|
11
|
+
"**Version:** `0.1.0`\n",
|
|
12
|
+
"\n",
|
|
13
|
+
"This notebook prepares a clean release, runs tests, builds and validates the wheel/source archive, and optionally publishes to PyPI and pushes source to an existing GitHub repository.\n",
|
|
14
|
+
"\n",
|
|
15
|
+
"**Security:** Tokens are requested through hidden prompts and are not written into source files. Never print, paste into a code cell, or commit a token. Prefer a project-scoped PyPI token or PyPI Trusted Publishing. The PyPI project name must be available to you. GitHub publishing requires an existing empty repository and a token with repository contents write access. Publishing is optional and requires explicit confirmation in the relevant cells.\n",
|
|
16
|
+
"\n",
|
|
17
|
+
"Run top to bottom. Works best in Google Colab, but the upload cell also accepts a local file path in ordinary Jupyter."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"cell_type": "code",
|
|
22
|
+
"execution_count": null,
|
|
23
|
+
"metadata": {},
|
|
24
|
+
"outputs": [],
|
|
25
|
+
"source": [
|
|
26
|
+
"from pathlib import Path\n",
|
|
27
|
+
"import os, shutil, subprocess, sys, zipfile, tempfile, getpass, textwrap\n",
|
|
28
|
+
"\n",
|
|
29
|
+
"WORK_ROOT = Path.cwd()\n",
|
|
30
|
+
"SOURCE_ZIP = None\n",
|
|
31
|
+
"\n",
|
|
32
|
+
"def run(command, *, cwd=None, env=None):\n",
|
|
33
|
+
" print(\"$\", \" \".join(map(str, command)))\n",
|
|
34
|
+
" subprocess.run(list(map(str, command)), cwd=cwd, env=env, check=True)\n",
|
|
35
|
+
"\n",
|
|
36
|
+
"def locate_project(root: Path) -> Path:\n",
|
|
37
|
+
" candidates = [root] + [p for p in root.rglob(\"pyproject.toml\") if p.parent != root]\n",
|
|
38
|
+
" for candidate in candidates:\n",
|
|
39
|
+
" if (candidate / \"pyproject.toml\").is_file() and (candidate / \"fluxscript\").is_dir():\n",
|
|
40
|
+
" return candidate\n",
|
|
41
|
+
" raise FileNotFoundError(\"Could not find a FluxScript source folder containing pyproject.toml and fluxscript/.\")\n",
|
|
42
|
+
"\n",
|
|
43
|
+
"print(\"Python:\", sys.version)\n",
|
|
44
|
+
"print(\"Working directory:\", WORK_ROOT)"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"cell_type": "markdown",
|
|
49
|
+
"metadata": {},
|
|
50
|
+
"source": [
|
|
51
|
+
"## 1. Upload the source ZIP\n",
|
|
52
|
+
"\n",
|
|
53
|
+
"Upload `FluxScript-0.1.0-source.zip` from the project download. In Google Colab, a file picker opens. In local Jupyter, enter the ZIP path when prompted."
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"cell_type": "code",
|
|
58
|
+
"execution_count": null,
|
|
59
|
+
"metadata": {},
|
|
60
|
+
"outputs": [],
|
|
61
|
+
"source": [
|
|
62
|
+
"try:\n",
|
|
63
|
+
" from google.colab import files # type: ignore\n",
|
|
64
|
+
" uploaded = files.upload()\n",
|
|
65
|
+
" if not uploaded:\n",
|
|
66
|
+
" raise RuntimeError(\"No ZIP uploaded.\")\n",
|
|
67
|
+
" SOURCE_ZIP = Path(next(iter(uploaded.keys()))).resolve()\n",
|
|
68
|
+
"except ImportError:\n",
|
|
69
|
+
" SOURCE_ZIP = Path(input(\"Path to FluxScript source ZIP: \").strip()).expanduser().resolve()\n",
|
|
70
|
+
"\n",
|
|
71
|
+
"if not SOURCE_ZIP.is_file() or SOURCE_ZIP.suffix.lower() != \".zip\":\n",
|
|
72
|
+
" raise FileNotFoundError(f\"Source ZIP not found or not a .zip file: {SOURCE_ZIP}\")\n",
|
|
73
|
+
"\n",
|
|
74
|
+
"EXTRACT_ROOT = WORK_ROOT / \"fluxscript_release_input\"\n",
|
|
75
|
+
"if EXTRACT_ROOT.exists():\n",
|
|
76
|
+
" shutil.rmtree(EXTRACT_ROOT)\n",
|
|
77
|
+
"EXTRACT_ROOT.mkdir(parents=True)\n",
|
|
78
|
+
"with zipfile.ZipFile(SOURCE_ZIP) as archive:\n",
|
|
79
|
+
" # Reject path traversal entries before extraction.\n",
|
|
80
|
+
" for member in archive.infolist():\n",
|
|
81
|
+
" destination = (EXTRACT_ROOT / member.filename).resolve()\n",
|
|
82
|
+
" if destination != EXTRACT_ROOT.resolve() and EXTRACT_ROOT.resolve() not in destination.parents:\n",
|
|
83
|
+
" raise ValueError(f\"Unsafe ZIP path: {member.filename}\")\n",
|
|
84
|
+
" archive.extractall(EXTRACT_ROOT)\n",
|
|
85
|
+
"PROJECT = locate_project(EXTRACT_ROOT)\n",
|
|
86
|
+
"print(\"Source project:\", PROJECT)\n",
|
|
87
|
+
"print((PROJECT / \"pyproject.toml\").read_text(encoding=\"utf-8\"))"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"cell_type": "markdown",
|
|
92
|
+
"metadata": {},
|
|
93
|
+
"source": [
|
|
94
|
+
"## 2. Install release tools and verify metadata\n",
|
|
95
|
+
"\n",
|
|
96
|
+
"This installs the packaging tools in the notebook runtime only. It does not modify the FluxScript runtime dependency list."
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"cell_type": "code",
|
|
101
|
+
"execution_count": null,
|
|
102
|
+
"metadata": {},
|
|
103
|
+
"outputs": [],
|
|
104
|
+
"source": [
|
|
105
|
+
"run([sys.executable, \"-m\", \"pip\", \"install\", \"--upgrade\", \"build\", \"twine\"])\n",
|
|
106
|
+
"\n",
|
|
107
|
+
"try:\n",
|
|
108
|
+
" import tomllib\n",
|
|
109
|
+
"except ImportError: # Python 3.10\n",
|
|
110
|
+
" run([sys.executable, \"-m\", \"pip\", \"install\", \"tomli\"])\n",
|
|
111
|
+
" import tomli as tomllib\n",
|
|
112
|
+
"metadata = tomllib.loads((PROJECT / \"pyproject.toml\").read_text(encoding=\"utf-8\"))\n",
|
|
113
|
+
"project_meta = metadata[\"project\"]\n",
|
|
114
|
+
"assert project_meta[\"name\"].lower() == \"fluxscript\", project_meta[\"name\"]\n",
|
|
115
|
+
"assert project_meta[\"version\"] == \"0.1.0\", project_meta[\"version\"]\n",
|
|
116
|
+
"assert project_meta.get(\"authors\", [{}])[0].get(\"name\") == \"Md Safarujjaman\"\n",
|
|
117
|
+
"print(\"Metadata checks passed:\", project_meta[\"name\"], project_meta[\"version\"], project_meta[\"authors\"])"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"cell_type": "markdown",
|
|
122
|
+
"metadata": {},
|
|
123
|
+
"source": [
|
|
124
|
+
"## 3. Run tests and build clean distributions\n",
|
|
125
|
+
"\n",
|
|
126
|
+
"The source ZIP may contain previously generated artifacts; this step removes them and builds fresh artifacts from the checked source."
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"cell_type": "code",
|
|
131
|
+
"execution_count": null,
|
|
132
|
+
"metadata": {},
|
|
133
|
+
"outputs": [],
|
|
134
|
+
"source": [
|
|
135
|
+
"dist_dir = PROJECT / \"dist\"\n",
|
|
136
|
+
"if dist_dir.exists():\n",
|
|
137
|
+
" shutil.rmtree(dist_dir)\n",
|
|
138
|
+
"for generated in PROJECT.glob(\"*.egg-info\"):\n",
|
|
139
|
+
" shutil.rmtree(generated, ignore_errors=True)\n",
|
|
140
|
+
"\n",
|
|
141
|
+
"run([sys.executable, \"-m\", \"compileall\", \"-q\", \"fluxscript\", \"tests\"], cwd=PROJECT)\n",
|
|
142
|
+
"run([sys.executable, \"-m\", \"unittest\", \"discover\", \"-s\", \"tests\", \"-v\"], cwd=PROJECT)\n",
|
|
143
|
+
"run([sys.executable, \"-m\", \"build\"], cwd=PROJECT)\n",
|
|
144
|
+
"run([sys.executable, \"-m\", \"twine\", \"check\", *sorted(dist_dir.glob(\"*\"))], cwd=PROJECT)\n",
|
|
145
|
+
"print(\"Release artifacts:\")\n",
|
|
146
|
+
"for artifact in sorted(dist_dir.glob(\"*\")):\n",
|
|
147
|
+
" print(artifact.name, artifact.stat().st_size, \"bytes\")"
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"cell_type": "markdown",
|
|
152
|
+
"metadata": {},
|
|
153
|
+
"source": [
|
|
154
|
+
"## 4. Optional: publish to PyPI\n",
|
|
155
|
+
"\n",
|
|
156
|
+
"Confirm that the `FluxScript` project name is available and that you control it before continuing. For an existing project, use a project-scoped API token. The token is read with a hidden prompt and passed to Twine only through environment variables."
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"cell_type": "code",
|
|
161
|
+
"execution_count": null,
|
|
162
|
+
"metadata": {},
|
|
163
|
+
"outputs": [],
|
|
164
|
+
"source": [
|
|
165
|
+
"publish_pypi = input(\"Publish these artifacts to PyPI now? Type YES to confirm: \").strip()\n",
|
|
166
|
+
"if publish_pypi == \"YES\":\n",
|
|
167
|
+
" pypi_token = getpass.getpass(\"PyPI API token (input hidden): \").strip()\n",
|
|
168
|
+
" if not pypi_token.startswith(\"pypi-\"):\n",
|
|
169
|
+
" raise ValueError(\"This does not look like a PyPI API token. Nothing was uploaded.\")\n",
|
|
170
|
+
" env = os.environ.copy()\n",
|
|
171
|
+
" env[\"TWINE_USERNAME\"] = \"__token__\"\n",
|
|
172
|
+
" env[\"TWINE_PASSWORD\"] = pypi_token\n",
|
|
173
|
+
" env[\"TWINE_NON_INTERACTIVE\"] = \"1\"\n",
|
|
174
|
+
" try:\n",
|
|
175
|
+
" run([sys.executable, \"-m\", \"twine\", \"upload\", \"--non-interactive\", *sorted(dist_dir.glob(\"*\"))], cwd=PROJECT, env=env)\n",
|
|
176
|
+
" print(\"PyPI upload command completed. Verify the release on your PyPI project page.\")\n",
|
|
177
|
+
" finally:\n",
|
|
178
|
+
" env.pop(\"TWINE_PASSWORD\", None)\n",
|
|
179
|
+
" pypi_token = None\n",
|
|
180
|
+
"else:\n",
|
|
181
|
+
" print(\"Skipped PyPI upload. Artifacts remain in:\", dist_dir)"
|
|
182
|
+
]
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"cell_type": "markdown",
|
|
186
|
+
"metadata": {},
|
|
187
|
+
"source": [
|
|
188
|
+
"## 5. Optional: push source to GitHub\n",
|
|
189
|
+
"\n",
|
|
190
|
+
"Create an **empty** GitHub repository first. This cell pushes the source tree to its `main` branch. A token is entered with a hidden prompt and is not embedded in the remote URL or saved in the repository. Do not use a personal token with broader permissions than necessary."
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"cell_type": "code",
|
|
195
|
+
"execution_count": null,
|
|
196
|
+
"metadata": {},
|
|
197
|
+
"outputs": [],
|
|
198
|
+
"source": [
|
|
199
|
+
"push_github = input(\"Push this source tree to an existing GitHub repository? Type YES to confirm: \").strip()\n",
|
|
200
|
+
"if push_github == \"YES\":\n",
|
|
201
|
+
" repo_url = input(\"HTTPS URL of your empty GitHub repository (for example https://github.com/USER/REPO.git): \").strip()\n",
|
|
202
|
+
" if not repo_url.startswith(\"https://github.com/\") or not repo_url.endswith(\".git\"):\n",
|
|
203
|
+
" raise ValueError(\"Use an HTTPS GitHub repository URL ending in .git. No push was attempted.\")\n",
|
|
204
|
+
" github_token = getpass.getpass(\"GitHub token (hidden; needs repository contents write access): \").strip()\n",
|
|
205
|
+
" if not github_token:\n",
|
|
206
|
+
" raise ValueError(\"GitHub token is empty.\")\n",
|
|
207
|
+
"\n",
|
|
208
|
+
" run([\"git\", \"--version\"], cwd=PROJECT)\n",
|
|
209
|
+
" run([\"git\", \"init\", \"-b\", \"main\"], cwd=PROJECT)\n",
|
|
210
|
+
" run([\"git\", \"config\", \"user.name\", \"Md Safarujjaman\"], cwd=PROJECT)\n",
|
|
211
|
+
" commit_email = input(\"Git commit email (public email or GitHub noreply email): \").strip()\n",
|
|
212
|
+
" if not commit_email or \"\\n\" in commit_email:\n",
|
|
213
|
+
" raise ValueError(\"A valid one-line commit email is required.\")\n",
|
|
214
|
+
" run([\"git\", \"config\", \"user.email\", commit_email], cwd=PROJECT)\n",
|
|
215
|
+
" run([\"git\", \"add\", \"-A\"], cwd=PROJECT)\n",
|
|
216
|
+
" run([\"git\", \"commit\", \"-m\", \"Release FluxScript 0.1.0\"], cwd=PROJECT)\n",
|
|
217
|
+
" # Configure askpass in a temporary file; the secret is supplied only via env.\n",
|
|
218
|
+
" askpass_dir = Path(tempfile.mkdtemp(prefix=\"fluxscript-askpass-\"))\n",
|
|
219
|
+
" askpass = askpass_dir / \"askpass.py\"\n",
|
|
220
|
+
" askpass.write_text(\n",
|
|
221
|
+
" \"import os, sys\\nprompt = sys.argv[1].lower() if len(sys.argv) > 1 else ''\\n\"\n",
|
|
222
|
+
" \"print('x-access-token' if 'username' in prompt else os.environ.get('FLUXSCRIPT_GITHUB_TOKEN', ''))\\n\",\n",
|
|
223
|
+
" encoding=\"utf-8\",\n",
|
|
224
|
+
" )\n",
|
|
225
|
+
" env = os.environ.copy()\n",
|
|
226
|
+
" env[\"GIT_ASKPASS\"] = sys.executable + \" \" + str(askpass)\n",
|
|
227
|
+
" # GIT_ASKPASS is normally an executable path; use a temporary executable wrapper.\n",
|
|
228
|
+
" wrapper = askpass_dir / \"askpass\"\n",
|
|
229
|
+
" wrapper.write_text(\"#!/bin/sh\\nexec \"+repr(sys.executable)+\" \"+repr(str(askpass))+\" \\\"$@\\\"\\n\", encoding=\"utf-8\")\n",
|
|
230
|
+
" wrapper.chmod(0o700)\n",
|
|
231
|
+
" env[\"GIT_ASKPASS\"] = str(wrapper)\n",
|
|
232
|
+
" env[\"GIT_TERMINAL_PROMPT\"] = \"0\"\n",
|
|
233
|
+
" env[\"FLUXSCRIPT_GITHUB_TOKEN\"] = github_token\n",
|
|
234
|
+
" try:\n",
|
|
235
|
+
" remotes = subprocess.run([\"git\", \"remote\"], cwd=PROJECT, capture_output=True, text=True, check=True).stdout.split()\n",
|
|
236
|
+
" if \"origin\" in remotes:\n",
|
|
237
|
+
" run([\"git\", \"remote\", \"set-url\", \"origin\", repo_url], cwd=PROJECT)\n",
|
|
238
|
+
" else:\n",
|
|
239
|
+
" run([\"git\", \"remote\", \"add\", \"origin\", repo_url], cwd=PROJECT)\n",
|
|
240
|
+
" run([\"git\", \"push\", \"-u\", \"origin\", \"main\"], cwd=PROJECT, env=env)\n",
|
|
241
|
+
" print(\"GitHub push completed. Verify the repository page.\")\n",
|
|
242
|
+
" finally:\n",
|
|
243
|
+
" env.pop(\"FLUXSCRIPT_GITHUB_TOKEN\", None)\n",
|
|
244
|
+
" github_token = None\n",
|
|
245
|
+
" shutil.rmtree(askpass_dir, ignore_errors=True)\n",
|
|
246
|
+
"else:\n",
|
|
247
|
+
" print(\"Skipped GitHub push. Source remains in:\", PROJECT)"
|
|
248
|
+
]
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"cell_type": "markdown",
|
|
252
|
+
"metadata": {},
|
|
253
|
+
"source": [
|
|
254
|
+
"## 6. Final checklist\n",
|
|
255
|
+
"\n",
|
|
256
|
+
"- [ ] Confirm the PyPI project name `FluxScript` is available or belongs to you.\n",
|
|
257
|
+
"- [ ] Check package metadata, license, README and release notes.\n",
|
|
258
|
+
"- [ ] Review the test output and `twine check` results.\n",
|
|
259
|
+
"- [ ] Prefer TestPyPI or a protected GitHub Actions Trusted Publishing workflow before a production release.\n",
|
|
260
|
+
"- [ ] Verify the PyPI release and GitHub repository after upload.\n",
|
|
261
|
+
"\n",
|
|
262
|
+
"**This notebook does not publish anything unless you explicitly type `YES` in the corresponding cell.** Version stays `0.1.0`; PyPI does not allow replacing an already-published file with the same version, so any changes after publishing require a new version."
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
],
|
|
266
|
+
"metadata": {
|
|
267
|
+
"kernelspec": {
|
|
268
|
+
"display_name": "Python 3",
|
|
269
|
+
"language": "python",
|
|
270
|
+
"name": "python3"
|
|
271
|
+
},
|
|
272
|
+
"language_info": {
|
|
273
|
+
"name": "python",
|
|
274
|
+
"version": "3.10+"
|
|
275
|
+
},
|
|
276
|
+
"colab": {
|
|
277
|
+
"name": "FluxScript_Release.ipynb",
|
|
278
|
+
"provenance": []
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
"nbformat": 4,
|
|
282
|
+
"nbformat_minor": 5
|
|
283
|
+
}
|
fluxscript-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Md Safarujjaman
|
|
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,13 @@
|
|
|
1
|
+
include README.md LICENSE
|
|
2
|
+
recursive-include docs *.md
|
|
3
|
+
recursive-include examples *.py
|
|
4
|
+
recursive-include tests *.py
|
|
5
|
+
|
|
6
|
+
include SECURITY.md
|
|
7
|
+
include CHANGELOG.md
|
|
8
|
+
include CONTRIBUTING.md
|
|
9
|
+
recursive-include .github *.yml
|
|
10
|
+
|
|
11
|
+
include FluxScript_Release.ipynb
|
|
12
|
+
|
|
13
|
+
include TEST_REPORT.md
|