Skip to main content

A playful Python toolkit for creative coding and small games.

Project description

Gummy Snake

PyPI Python Versions License: LGPL-2.1 Downloads

Gummy Snake is a playful Python toolkit for creative coding and small games. It is for people who want to sketch with code: draw shapes, animate motion, react to input, load sprites, play with pixels, and build visual toys without first building a full app.

The public API is Python-first. Function names use snake_case, sketches are ordinary Python files, and drawing, export, pixels, text, images, and native interactive windows are powered by the packaged Rust gummy_canvas runtime. On desktop builds, native windows and input use the SDL3-backed runtime. The Rust canvas owns the hot renderer state used to construct draw commands, including the current style, transform stack, image/text state, and GPU command batches. It also owns the mutable sketch context state for canvas lifecycle fields, timing, loop/redraw flags, input snapshots, and in-progress shape buffers.

Install

pip install gummy-snake

Published wheels include the required Rust gummy_canvas canvas runtime. Source or editable installs must build that PyO3 module; there is no Python renderer fallback for canvas-owned behavior. Local development builds compile SDL3 from source/static through Rust when native interactive support is enabled, so no separate system SDL3 install is normally required.

Install optional media helpers when you need camera, video, or sound-related extras:

pip install "gummy-snake[media]"

First Sketch

Create a file named circle_sketch.py:

import gummysnake as gs


@gs.setup
def setup() -> None:
    gs.create_canvas(400, 300)
    gs.no_stroke()


@gs.draw
def draw() -> None:
    gs.background(245)
    gs.fill(255, 90, 90)
    gs.circle(200, 150, 100)


gs.run()

Run it:

python circle_sketch.py

For repeatable scripts, use a bounded headless render:

gs.run(headless=True, max_frames=1)

Callbacks can also be async def, which is useful with async-compatible asset helpers:

image = None


@gs.preload
async def preload() -> None:
    global image
    image = await gs.load_image_async("sprite.png")

What You Can Make

  • 2D drawings with shapes, curves, color, transforms, and blend modes.
  • Animated sketches using the familiar setup() and draw() lifecycle.
  • Decorator-based sketches, async-compatible callbacks, and object-oriented Sketch subclasses.
  • Image and pixel experiments, including canvas export.
  • Text, font measurement, and accessibility descriptions.
  • Interactive sketches with SDL3-backed native windows, mouse, keyboard, and touch state when native window support is available.
  • Software 3D sketches with primitives, lights, materials, models, textures, and shader objects on the current Rust-backed software 3D path.
  • Small games and visual toys using the examples as starting points.

Loaded images, models/meshes, and sounds keep Rust-managed asset handles behind friendly Python wrappers. This is intentional for performance: bulk asset bytes, geometry arrays, parsing, export, and metadata extraction should stay in the Rust canvas runtime so sketches avoid repeated Python object materialization and per-element loops. Normal load_image(); image(...) sprite drawing can stay on the fast renderer path, model projection/export can use Rust-owned geometry without first creating Python Vec3 objects, untextured software-3D faces can be submitted directly as Rust/GPU triangles when GPU drawing is available, and loaded sounds keep their bytes and duration metadata in CanvasSound until user code asks for Python bytes. Image-local resize, mask, filter, crop/copy, and alpha compositing delegate bulk byte work to the Rust canvas runtime while keeping the Python Image API and version semantics. For pixel effects, load_pixels() returns a list-based pixel buffer and load_pixel_bytes() provides a bytes readback path; update_pixels() accepts lists and buffer-like inputs such as bytes, bytearray, and memoryview. Small canvas get() and set() region operations use Rust region calls instead of reconstructing the full canvas as a Python image. For dense drawing loops, gs.fast() returns a frame-local facade that keeps public style/transform state while reducing global-mode dispatch overhead. Opt-in enable_performance_diagnostics() counters can identify readback, pixel conversion, upload, texture cache, and CPU compositing fallback paths. HiDPI/Retina rendering keeps sketch coordinates logical while physical pixel buffers and GPU vertices are scaled by pixel_density().

Learn More

For Contributors

This repository uses uv for Python commands:

uv sync --dev
uv run ruff check .
uv run mypy src
uv run pytest

The canvas runtime is a required PyO3 module for development/source installs:

uvx maturin develop --manifest-path crates/gummy_canvas/Cargo.toml --features extension-module

The refactored Python package is split by responsibility: public API modules in src/gummysnake/api/, SketchContext mixins in src/gummysnake/_context/, lifecycle code in src/gummysnake/sketch/, enum-backed constants in src/gummysnake/constants/, and thin canvas backend/renderer facades over the implementation modules in src/gummysnake/backend/_canvas/. The native desktop runtime itself lives in crates/gummy_canvas, owns sketch context state, canvas draw state, and command construction, and uses SDL3 for windowing, resizing, and input event collection. Python keeps the public API, callbacks, plugin hooks, and friendly wrapper objects.

The contributor documentation explains the architecture, lifecycle, testing workflow, and release shape in more detail:

Performance benchmarks are opt-in:

uv run pytest tests/benchmark/test_canvas_backend_perf.py --run-benchmarks
uv run pytest tests/benchmark/test_api_overhead_perf.py --run-benchmarks
uv run pytest tests/benchmark/test_image_pipeline_perf.py --run-benchmarks
uv run pytest tests/benchmark/test_model_export_perf.py --run-benchmarks
uv run pytest tests/benchmark/test_webgl_3d_perf.py --run-benchmarks

Canvas and WEBGL frame-style benchmark scenarios are expected to average at least 120 FPS. Failures below that floor are intentional optimization signals. Model export benchmarks use a memory budget for streaming OBJ/STL output. Machine-specific baseline snapshots live in tests/benchmark/baselines/.

Long-running resource lifecycle checks are also opt-in:

uv run pytest tests/stress --run-stress -q -s

Compatibility

Gummy Snake keeps the sketch lifecycle familiar, but it is not a browser port. It does not include DOM helpers, browser-only APIs, JavaScript aliases, or a Pillow/Pyglet/Python renderer fallback. Unsupported features raise explicit package errors so sketches fail clearly.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gummy_snake-0.6.0.tar.gz (203.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gummy_snake-0.6.0-cp312-cp312-win_amd64.whl (4.2 MB view details)

Uploaded CPython 3.12Windows x86-64

gummy_snake-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

gummy_snake-0.6.0-cp312-cp312-macosx_11_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

gummy_snake-0.6.0-cp312-cp312-macosx_10_12_x86_64.whl (3.8 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

File details

Details for the file gummy_snake-0.6.0.tar.gz.

File metadata

  • Download URL: gummy_snake-0.6.0.tar.gz
  • Upload date:
  • Size: 203.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gummy_snake-0.6.0.tar.gz
Algorithm Hash digest
SHA256 3ecd5da2cf82b3432ad0f63c4ce4869754db0952b663dfe4370ff41e7af0026e
MD5 fb76bd4b1860b1432f489dc8196c4e29
BLAKE2b-256 e244beb59007be2ee0c69d058eceffebb56d74fffa9bbb309aa46e81ed86f34b

See more details on using hashes here.

Provenance

The following attestation bundles were made for gummy_snake-0.6.0.tar.gz:

Publisher: publish.yml on JonathanHHenson/gummy_snake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gummy_snake-0.6.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for gummy_snake-0.6.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 564e2f0a4941889044a926770b14cd41b1515a439403892963778f36966ae028
MD5 0f7069c28cc0758c63b7d859c5617701
BLAKE2b-256 b7f5bf3e62161c00634f2dceb7a566b3cb3f8d9ffca1bae554bdf45bf5c4536c

See more details on using hashes here.

Provenance

The following attestation bundles were made for gummy_snake-0.6.0-cp312-cp312-win_amd64.whl:

Publisher: publish.yml on JonathanHHenson/gummy_snake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gummy_snake-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gummy_snake-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6952727171502324ac5512c5deb198f6d908c6f8d4b4c970ab7d7e2b0d522fbf
MD5 20675044a883d1f0bc6505ab55923794
BLAKE2b-256 ec6c41fa0855733a665a230fdbc6ccdb1710a06fbe573bd95eecf85b828b8744

See more details on using hashes here.

Provenance

The following attestation bundles were made for gummy_snake-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on JonathanHHenson/gummy_snake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gummy_snake-0.6.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gummy_snake-0.6.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 62e4daf2e280a3f878c5ca674c7760f9c486460de01dfb8366cf65921f2502ad
MD5 c402429fe97025053e533e071ff28efe
BLAKE2b-256 7a4131ab3b776cd44eaf8a1253777edc8b3a2d889bd108cbdcf5d0ed9156c81f

See more details on using hashes here.

Provenance

The following attestation bundles were made for gummy_snake-0.6.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: publish.yml on JonathanHHenson/gummy_snake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gummy_snake-0.6.0-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for gummy_snake-0.6.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 009b5b820d92cc42e116cf2f75a113f5b7828e51a27254420f9b4fdd0fb4a4bb
MD5 a3980a2a8b4cc69f5c7a887165646ee0
BLAKE2b-256 bdd4871bf89044b5e968e58b2674820c3ba53ac0f82aa1e525638bd7c53edefc

See more details on using hashes here.

Provenance

The following attestation bundles were made for gummy_snake-0.6.0-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: publish.yml on JonathanHHenson/gummy_snake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page