01 Install — Desktop
Python v2 has no dependencies and no install step. If you have Python 3.10+ and Git, you're done. Works on macOS, Linux, Windows (native or WSL), and a fridge with a shell.
python3 --version # need 3.10 or newer
git --version
git clone https://github.com/gefrus112/pythonv2
cd pythonv2
python3 -m pyv2 --version
# Python v2 1.1.0
python3 -m pyv2 examples/hello.pyv2
# Hello, World!
# 2 + 2 = 4
python3 -m unittest discover -s tests -t .
# ... OK
Command line
| Command | What it does |
|---|---|
python3 -m pyv2 script.pyv2 | Run a program |
python3 -m pyv2 -c 'print(42)' | Run a one-liner |
python3 -m pyv2 | Start the REPL (... continues blocks) |
python3 -m pyv2 --version | Print the version |
python3 -m pyv2 --help | Show usage |
Windows notes
- If
python3is not found, trypy -m pyv2 script.pyv2. - WSL is the smoothest path: install Ubuntu from the Microsoft Store, then follow the three steps above.
02 VS Code
The repository ships ready-made VS Code config in .vscode/
and a language extension in editors/vscode/ for
syntax highlighting of .pyv2 files.
Quick start (run & debug your code)
- Open the
pythonv2folder in VS Code (File → Open Folder…). - Open any
.pyv2file, e.g.examples/fib.pyv2. - Press Ctrl+Shift+B
(macOS: Cmd+Shift+B) — the default build task
runs
python3 -m pyv2on the current file. - Output appears in the Terminal panel. That's it.
The included .vscode/tasks.json defines two tasks:
Run Python v2 file (default build) and
Python v2 REPL. The included
.vscode/settings.json associates *.pyv2 with
the pyv2 language.
Syntax highlighting (the bundled extension)
- Copy the extension folder into your VS Code extensions directory:
# macOS / Linux cp -r editors/vscode ~/.vscode/extensions/pyv2-0.1.0 # Windows (PowerShell) Copy-Item -Recurse editors/vscode "$env:USERPROFILE\.vscode\extensions\pyv2-0.1.0" - Restart VS Code (or run Developer: Reload Window).
- Open any
.pyv2file — keywords, strings, f-strings, numbers and comments are now colored.
Prefer the marketplace workflow? Pack it once with the
vsce tool and install the VSIX:
cd editors/vscode
npx @vscode/vsce package # builds pyv2-0.1.0.vsix
code --install-extension pyv2-0.1.0.vsix
Alternative: Code Runner
If you use the popular Code Runner extension, add this to
your user settings.json and press
Ctrl+Alt+N to run:
{
"code-runner.executorMap": {
"python": "python3 -m pyv2"
},
"code-runner.fileDirectoryAsCwd": true
}
03 Dev Containers & GitHub Codespaces
Opening the repo in a dev container (VS Code or
Codespaces) gives you a ready environment in seconds — Python preinstalled,
tasks wired, tests passing. The config lives in
.devcontainer/devcontainer.json (that's the ".dev" part).
VS Code Dev Containers
- Install Docker and the
Dev Containers extension
(
ms-vscode-remote.remote-containers). - Open the repo folder, then run Dev Containers: Reopen in Container from the Command Palette (Ctrl+Shift+P).
- First boot pulls the Python image; after that everything is instant.
- Run
python3 -m pyv2 examples/hello.pyv2— or just hit Ctrl+Shift+B.
GitHub Codespaces
- On GitHub, open the repo → Code → Codespaces → Create codespace on main.
- VS Code opens in your browser with the dev container already built.
- Everything from the desktop guide works identically inside it.
The container runs python3 -m unittest discover -s tests -t .
at build time, so you always start from a green suite.
04 Any Other Code Editor
Python v2 is just text plus a CLI. Any editor that can run a shell command can run it. The universal recipe:
- Coloring — associate
*.pyv2with Python syntax. It's close enough (and free). - Running — bind a build/run command to
python3 -m pyv2 "$file"with the working directory set to your project. - Formatting — 4 spaces, one statement per line, blocks
end with
end. Your formatter can't break it. That's the point.
Sublime Text
Tools → Build System → New Build System…
{
"cmd": ["python3", "-m", "pyv2", "$file"],
"selector": "source.python",
"working_dir": "$file_path"
}
Vim / Neovim
" in init.vim / .vimrc
autocmd BufNewFile,BufRead *.pyv2 set filetype=python
autocmd FileType python nnoremap <F5> :w<CR>:!
\python3 -m pyv2 %<CR>
JetBrains (PyCharm, IntelliJ)
- Settings → Editor → File Types → add
*.pyv2to the Python type. - Settings → Tools → External Tools → add a tool with
program
python3, arguments-m pyv2 $FileName$, working directory$FileDir$. - Bind it to a shortcut under Settings → Keymap.
Notepad++
Run → Run… (F5) with:
cmd /c python3 -m pyv2 "$(FULL_CURRENT_PATH)"
05 Browser Playground
Open the Playground to edit and run code without installing anything. It has line numbers, starter programs, keyboard execution, command history, and separate Output and Problems terminals so runtime errors never get mixed into normal program output.
| Mode | What runs | Use it for |
|---|---|---|
| Python v2 | The complete pyv2.js browser runtime | Language programs, game data, and website templates |
| Classic Python | A documented compatibility subset translated locally to Python v2 | def, indentation, variables, loops, lists, maps, functions, and print |
| Local CPython | Not embedded in the static website | Imports, packages, native extensions, files, and the full standard library |
- Choose Python v2 or Classic compatibility.
- Pick a starter, edit the source, and press Ctrl+Enter.
- Read normal text in Output and failures in Problems.
- Use the bottom prompt for expressions and assignments. Commands
:help,:clear,:reset, and:mode classicare built in.
The Portfolio Starter uses editable Python v2 maps and lists for your profile, role, biography, skills, statistics, projects, games, location, and contact details. Valid edits live-sync into a responsive preview. Switch to HTML Code to inspect or copy the exact generated document, then download it as a standalone page. The desktop New Project tool creates the richer multi-file offline version.
06 Python v2 + PyHope Workspace
Python v2 1.1 ships with its own desktop workspace. It is implemented
with Python's standard-library tkinter toolkit—no Electron,
pygame, browser shell, subscription, or account.
Open the app
# after running install.bat or install.sh, either command opens the workspace:
pyhope-studio
pyv2-launcher
# the PyHope CLI can launch it too:
pyhope --studio
# always works, even if the command folder is not on PATH:
python3 -m pyv2.launcher
Windows also gets a Desktop shortcut. macOS gets
~/Applications/Python v2 Sudbury.app. Linux gets an app
menu entry. If your Linux distribution separates tkinter, install its
python3-tk package; the language CLI still works without it.
App layout
| Area | What it does |
|---|---|
| Home | Workspace overview and shortcuts to every main tool |
| Code Studio | Open, edit, save, and run .pyv2; output/errors stay in the app |
| Files | Safe local workspace service: create, read, atomically save, rename, and delete files without path traversal |
| New Project | Create Website, Windows app, CLI app, or Game starters without overwriting files |
| Assets | Browse and export eight packaged original CC0 PyHope SVGs offline |
| Games & GPU | Open the 10-game arcade, animated sprites, and 9M GPU Lab |
| Connected Editors | Detect VS Code, VSCodium, Zed, Sublime Text, and PyCharm from PATH; no account or token |
| Settings | Workspace folder, preferred editor, code font size, and run autosave |
| Docs & Learn | Playground, tutorial, 50-topic guide, reference, and CubeCometYT milestone |
| Donation | Coming soon—the app does not collect money or payment data |
Build a website with Python v2
- Open New Project and choose Website.
- The Launcher creates
app.pyv2,index.html,runner.js, an offline copy ofpyv2.js, and ready-to-run.vscodetasks/settings. - Edit
app.pyv2. Its structured output fills the profile, skills, project cards, featured games, and contact section. - Choose local preview. The Launcher starts a safe local HTTP server on an available port and opens your responsive portfolio.
# app.pyv2 — one record becomes one part of the page
profile = {name: "Alex", role: "Creative developer"}
skills = ["Python v2", "PyHope", "Web design"]
print("PROFILE|" + profile.name + "|" + profile.role + "|I build playful tools.")
print("ABOUT|My personal biography goes here.")
for skill in skills:
print("SKILL|" + skill)
end
print("GAME|Comet Circuit|Racing|Three-lap AI racing.|games.html#comet-circuit")
07 Production Apps & Windows EXE Builder
Sudbury Build Tools turn a .pyv2 program into a validated,
inspectable application project and—when the native build runs on
Windows—a real one-file .exe. Python v2 does not rename a
Linux or macOS binary and pretend it is a Windows executable.
Create, run, check, and build
# Complete console application with JSON persistence
pyv2 new windows-app "Comet Tasks"
# Or create a dialog-based app with no terminal window
pyv2 new windows-app "Hello Window" --windowed
pyv2 Comet-Tasks/main.pyv2 --add "Ship the EXE"
pyv2 check Comet-Tasks
pyv2 build Comet-Tasks
# Run this final command on Windows with PyInstaller installed.
# The generated build-windows.bat handles that installation for you.
pyv2 build Comet-Tasks --native
| Generated file | Purpose |
|---|---|
main.pyv2 | Readable application source using arguments, strict JSON, and persistent app data |
pyv2app.json | Name, stable app ID, version, publisher, console/windowed mode, icon, and assets |
build-windows.bat | Validates and builds the real EXE on Windows without administrator access |
.github/workflows/windows-exe.yml | Optional Windows CI build and downloadable executable artifact |
build/windows/manifest.json | SHA-256 source and build-input integrity record |
runtime/pyv2 | Exact vendored language runtime used for the build—no moving runtime dependency |
app.spec + launcher.py | Reviewable PyInstaller recipe and embedded Python v2 host |
Application APIs
info = app_info() # name, version, platform, safe data directory
commands = args() # values after the .pyv2 filename / EXE
settings = {theme: "night", zoom: 1.25}
write_text("settings.json", json_encode(settings))
loaded = json_decode(read_text("settings.json"))
print(loaded.theme)
# Other safe services:
# append_text, file_exists, list_dir, make_dir, delete_file
# read_asset, asset_exists, sleep_ms, ui_message, ui_ask
During development, writable data stays in .pyv2-data/
beside the program. Packaged apps use
%LOCALAPPDATA%\PythonV2Apps\APP-ID. Paths are relative and
sandboxed; atomic writes, UTF-8 validation, an 8 MB text limit, asset
size validation, symlink-escape checks, and unmanaged-build-directory
protection are enabled by default.
pyv2 build still creates the complete Windows kit. Copy it
to Windows and run build.bat, or push the generated project
and run its GitHub Actions workflow on a Windows runner. PyInstaller
cannot cross-compile Windows PE files from another operating system.Signing note: generated executables are reproducible but not Authenticode-signed automatically. Public distributors should add their own protected code-signing certificate in Windows CI; never commit a certificate or password to the project.
08 PyHope Game Engine
PyHope is Python v2's own dependency-free game engine. It is not pygame and it installs no native libraries. The portable Python module handles game logic and terminal previews; the website adds Canvas and WebGL2 renderers for full visual games.
Install and verify
# one-click: download install.bat (Windows) or install.sh (macOS/Linux)
# manual, from the cloned repo:
python3 -m pip install --user .
pyv2 --version
pyhope --check
pyhope --demo
Download the installers. The installer adds both commands and runs the check automatically.
Core API
| API | Purpose | Example |
|---|---|---|
Vec2 | Immutable 2D vectors, length, normalize, dot product | Vec2(3, 4).normalized() |
Sprite | Named entity with position, velocity, tags and alive state | Sprite("hero", Vec2(2, 2), "@") |
TileMap | Rectangular collision map; dots/spaces are walkable | TileMap.from_text(level) |
Engine | Fixed-step scene, systems, movement and collision | Engine(world, tick_rate=60) |
raycast | Fast grid DDA ray casting with hit distance and wall side | raycast(world, origin, direction) |
render_ascii | Dependency-free terminal scene preview | print(engine.render_ascii()) |
| Canvas renderer | 10 games: shooting, platform physics, racing, grid and brick arcade modes | Play arcade |
| WebGL2 renderer | 1280×720 live / 4096×2304 9M frame | Open GPU lab |
Your first PyHope scene
from pyhope import Engine, Sprite, TileMap, Vec2
world = TileMap.from_text("""#####
#...#
#...#
#####""")
engine = Engine(world)
hero = engine.add(Sprite("hero", Vec2(1.5, 1.5), "@"))
hero.velocity = Vec2(0.5, 0)
engine.step()
print(engine.render_ascii())
The visual examples are open source: game.js is the CPU
sprite raycaster, gpu-game.js is the 9M renderer, and
games.js contains Comet Hopper. Original sprites are CC0 in
assets/sprites/.
09 Language Quick Reference
The full spec (grammar, semantics, error kinds) lives in docs/LANGUAGE.md. Here is the day-to-day core.
Values
| Type | Example | Notes |
|---|---|---|
| number | 1, 2.5, 1e-3 | Whole numbers print without .0 |
| string | "hi", f"hi {x}" | Indexed s[0], tons of methods |
| bool | true, false | |
| nil | nil | Absence of a value |
| list | [1, 2, 3] | Mutable; negative indices work |
| map | {name: "Ada"} | Bare keys, dot access, get(k, default) |
| fn | fn add(a, b): … end | First-class, real closures |
| range | range(10) | Lazy, from the range builtin |
Operators
| Kind | Operators |
|---|---|
| Arithmetic | + - * / // % ** |
| Comparison | == != < <= > >= |
| Logic | and, or, not |
| Membership | x in list, k in map, s in string |
| Ternary | ok ? "yes" : "no" |
| Assignment | = += -= *= /= %= |
Statements
| Statement | Example |
|---|---|
| function | fn add(a, b): return a + b end |
| branch | if x: … elif y: … else: … end |
| while | while running: step() end |
| for | for item in [1, 2, 3]: print(item) end |
| range loop | for i in range(1, 10, 2): print(i) end |
| recover | try: risky() catch error: print(error.kind) finally: cleanup() end |
| raise | raise {kind: "ConfigError", message: "port required"} |
| jump | return, break, continue |
Structured error recovery
Runtime errors are catchable values. A named catch receives a map with
kind, message, line, and trace.
The optional finally block always runs, including during
return, break, and continue.
try:
result = 100 / divisor
catch error:
print(error.kind + ":", error.message)
result = 0
finally:
print("calculation complete")
end
raise "message" creates a UserError. Raise a map with string
kind and message fields to create a named application error.
Syntax errors are detected before execution and are not catchable.
Builtins
| Function | Description |
|---|---|
print(...) | Print values, space-separated |
len(x) | Length of string / list / map / range |
range(stop) · range(a, b, step) | Integer range |
sum · enumerate · zip | Iterable aggregation and pairing |
all · any | Truth tests across an iterable |
str int float bool repr | Conversions |
abs floor ceil round sqrt pow | Math |
min · max | Over arguments or one list |
type(x) | "number", "string", "list", "map", … |
push pop insert remove | List mutation |
keys values has get | Map access |
sort sort_by join | Helpers |
assert(cond, msg?) | Raises AssertionError when falsy |
json_encode json_decode | Strict JSON for persistent application data |
args app_info | Application arguments, identity, platform, and capability details |
read_text write_text append_text | Sandboxed UTF-8 files with atomic replacement |
file_exists list_dir make_dir delete_file | Safe app-data management |
read_asset asset_exists ui_message ui_ask | Packaged assets and native dialogs |
chr ord clock input sleep_ms | Characters, timing, and desktop input |
10 Try It Right Here
No install needed to experiment — this is the real interpreter, running in your browser. Edit and hit Run.