Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 60 additions & 25 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ jobs:
"3.12",
"3.13",
"3.14",
"3.15",
"pypy-3.11",
"pypy-3.12",
]
raylib-platform: ["Desktop", "SDL"]
env:
Expand Down Expand Up @@ -142,10 +144,10 @@ jobs:
runs-on: macos-14
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15", "pypy-3.11", "pypy-3.12"]
raylib-platform: ["Desktop", "SDL"]
env:
MACOSX_DEPLOYMENT_TARGET: "11"
MACOSX_DEPLOYMENT_TARGET: "12.0"
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
Expand Down Expand Up @@ -255,11 +257,13 @@ jobs:
image: electronstudio/ubuntu16-modern:latest
options: --user root
volumes:
# override /__e/node20 because GitHub Actions uses a version that requires too-recent glibc
# override /__e/node20 AND /__e/node24 with the image's own node because the nodes
# that GitHub Actions provides require too-recent glibc. Still needed for node
# actions such as actions/upload-artifact (we no longer use actions/checkout, we
# just run git directly). Since June 2026 the runner resolves ALL js actions to
# /__e/node24, so both paths must be overridden.
- /tmp:/__e/node20
env:
# Github Actions Checkout now wants Node 24. Maybe easier just to stop using Checkout than keep messing around with Node.
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
- /tmp:/__e/node24
strategy:
# You can use PyPy versions in python-version.
# For example, pypy2 and pypy3
Expand All @@ -274,13 +278,27 @@ jobs:
"python3.12",
"python3.13",
"python3.14",
"python3.15",
"pypy3.11",
"pypy3.12"
]
raylib-platform: ["Desktop", "SDL", "DRM", "SDL_SOFT"]
steps:
# Must be the first step so the workspace is empty and git clone works
- name: Checkout
run: |
# workspace dir is owned by the host runner user but we are root in the
# container, so tell git that is OK (avoids "dubious ownership" error)
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git clone ${{ github.server_url }}/${{ github.repository }} .
git fetch --force origin "${{ github.ref }}"
git checkout --force FETCH_HEAD
git submodule update --init --recursive

- name: fix node
run: |
ln -s /usr/local/bin /__e/node20/bin
ln -s /usr/local/bin /__e/node24/bin

- name: setup wayland
run: |
Expand All @@ -303,10 +321,6 @@ jobs:
cmake --build . --config Release
cmake --install .

- uses: actions/checkout@v2
with:
submodules: recursive

- name: fix raygui bug
run: |
patch -p0 <raygui.h.diff
Expand Down Expand Up @@ -402,11 +416,13 @@ jobs:
image: electronstudio/ubuntu16-modern:i386
options: --user root --platform=linux/386
volumes:
# override /__e/node20 because GitHub Actions uses a version that requires too-recent glibc
# override /__e/node20 AND /__e/node24 with the image's own node because the nodes
# that GitHub Actions provides require too-recent glibc. Still needed for node
# actions such as actions/upload-artifact (we no longer use actions/checkout, we
# just run git directly). Since June 2026 the runner resolves ALL js actions to
# /__e/node24, so both paths must be overridden.
- /tmp:/__e/node20
env:
# Github Actions Checkout now wants Node 24. Maybe easier just to stop using Checkout than keep messing around with Node.
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
- /tmp:/__e/node24
strategy:
# You can use PyPy versions in python-version.
# For example, pypy2 and pypy3
Expand All @@ -421,12 +437,25 @@ jobs:
"python3.12",
"python3.13",
"python3.14",
"python3.15"
]
raylib-platform: ["Desktop", "SDL", "DRM", "SDL_SOFT"]
steps:
# Must be the first step so the workspace is empty and git clone works
- name: Checkout
run: |
# workspace dir is owned by the host runner user but we are root in the
# container, so tell git that is OK (avoids "dubious ownership" error)
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git clone ${{ github.server_url }}/${{ github.repository }} .
git fetch --force origin "${{ github.ref }}"
git checkout --force FETCH_HEAD
git submodule update --init --recursive

- name: fix node
run: |
ln -s /usr/local/bin /__e/node20/bin
ln -s /usr/local/bin /__e/node24/bin

- name: update cmake
run: |
Expand All @@ -444,10 +473,6 @@ jobs:
cmake --build . --config Release
cmake --install .

- uses: actions/checkout@v2
with:
submodules: recursive

- name: fix raygui bug
run: |
patch -p0 <raygui.h.diff
Expand Down Expand Up @@ -540,7 +565,7 @@ jobs:
runs-on: ubuntu-22.04-arm
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
raylib-platform: ["Desktop", "SDL", "SDL_SOFT"]
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
Expand Down Expand Up @@ -676,7 +701,20 @@ jobs:
docker-tag: "python3.13-bullseye"
- python-version: "3.14"
docker-tag: "python3.14-bookworm"
- python-version: "3.15"
docker-tag: "python3.15-bookworm"
steps:
# Must be the first step so the workspace is empty and git clone works
- name: Checkout
run: |
# workspace dir is owned by the host runner user but we are root in the
# container, so tell git that is OK (avoids "dubious ownership" error)
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git clone ${{ github.server_url }}/${{ github.repository }} .
git fetch --force origin "${{ github.ref }}"
git checkout --force FETCH_HEAD
git submodule update --init --recursive

- name: update cmake
run: |
wget https://github.com/Kitware/CMake/releases/download/v3.31.10/cmake-3.31.10-linux-aarch64.tar.gz
Expand All @@ -688,10 +726,6 @@ jobs:
apt update
apt -y install libdrm-dev libgbm-dev libegl-dev libgles2-mesa-dev libasound2-dev libedit2

- uses: actions/checkout@v2
with:
submodules: recursive

- name: fix raygui bug
run: |
patch -p0 <raygui.h.diff
Expand Down Expand Up @@ -778,7 +812,8 @@ jobs:
"3.12",
"3.13",
"3.14",
"pypy-3.11",
"3.15",
"pypy-3.11"
]
raylib-platform: ["Desktop", "SDL", "SDL_SOFT"]
steps:
Expand Down Expand Up @@ -893,7 +928,7 @@ jobs:
# For example, pypy2 and pypy3
matrix:
python-version:
["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
raylib-platform: ["Desktop", "SDL", "SDL_SOFT"]
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

This is **raylib-python-cffi** (version 6.0.1.0), Python CFFI bindings for Raylib 6.0 game development library. It provides two main Python modules:
This is **raylib-python-cffi** (version 6.0.1.1), Python CFFI bindings for Raylib 6.0 game development library. It provides two main Python modules:
- `raylib`: Direct C API bindings (exact copy of C functions)
- `pyray`: More Pythonic API wrapper

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ original Raylib.

# Quickstart

`pip3 install raylib==6.0.1.0 --break-system-packages`
`pip3 install raylib==6.0.1.1 --break-system-packages`
```python
from pyray import *
init_window(800, 450, "Hello")
Expand Down Expand Up @@ -73,7 +73,7 @@ Then make sure you have the latest pip installed:
Then install

python3 -m pip install setuptools
python3 -m pip install raylib==6.0.1.0
python3 -m pip install raylib==6.0.1.1

On most platforms it should install a binary wheel. If yours isn't available then pip will attempt to build from
source, in which case you will need to have Raylib development libs installed, e.g.
Expand All @@ -95,7 +95,7 @@ Older MacOS requires building from source but this is usually simple:

brew install pkg-config
brew install raylib
python3 -m pip install raylib==6.0.1.0
python3 -m pip install raylib==6.0.1.1

## Linux

Expand Down
15 changes: 12 additions & 3 deletions create_stub_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,26 @@ class struct: ...
# continue
print(f"class {struct}:")
# sig = ""
fields = ffi.typeof(struct).fields
# Opaque structs (e.g. GLFWcursor, GLFWmonitor, GLFWwindow, rAudioBuffer,
# rAudioProcessor) are never defined in the parsed headers. cffi >= 2.0.0
# hard-aborts the process (C assert) when accessing .fields on an opaque
# struct, instead of returning None like cffi 1.x did. ffi.sizeof() raises
# a normal Python exception for opaque structs, so use it to test first.
fields = None
try:
ffi.sizeof(ffi.typeof(struct))
fields = ffi.typeof(struct).fields
except Exception:
pass
if fields is not None:
#print(ffi.typeof(struct).fields)
#print(f" {arg}: {arg}")
# print(f" def __init__(self{sig}):")
#
for arg in ffi.typeof(struct).fields:
for arg in fields:
print(f" {arg[0]}: {ctype_to_python_type(arg[1].type.cname)}")
else:
print(" ...")
# print(f" self.{arg[0]}={arg[0]}")

elif ffi.typeof(struct).kind == "enum":
print(f"{struct} = int")
Expand Down
2 changes: 1 addition & 1 deletion docs/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
config: d2e698b9576bffb5afca021582567e2a
config: 2370c1c0c28e9a086ad498bde8b78861
tags: 645f666f9bcd5a90fca523b33c5a78b7
22 changes: 11 additions & 11 deletions docs/README.html
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ <h2>Platforms: Windows, Mac, Linux, Raspberry Pi, Web<a class="headerlink" href=
</section>
<section id="quickstart">
<h1>Quickstart<a class="headerlink" href="#quickstart" title="Link to this heading"></a></h1>
<p><code class="docutils literal notranslate"><span class="pre">pip3</span> <span class="pre">install</span> <span class="pre">raylib==6.0.1.0</span> <span class="pre">--break-system-packages</span></code></p>
<p><code class="docutils literal notranslate"><span class="pre">pip3</span> <span class="pre">install</span> <span class="pre">raylib==6.0.1.1</span> <span class="pre">--break-system-packages</span></code></p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">pyray</span><span class="w"> </span><span class="kn">import</span> <span class="o">*</span>
<span class="n">init_window</span><span class="p">(</span><span class="mi">800</span><span class="p">,</span> <span class="mi">450</span><span class="p">,</span> <span class="s2">&quot;Hello&quot;</span><span class="p">)</span>
<span class="n">init_window</span><span class="p">(</span><span class="mi">800</span><span class="p">,</span> <span class="mi">450</span><span class="p">,</span> <span class="s2">"Hello"</span><span class="p">)</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">window_should_close</span><span class="p">():</span>
<span class="n">begin_drawing</span><span class="p">()</span>
<span class="n">clear_background</span><span class="p">(</span><span class="n">WHITE</span><span class="p">)</span>
<span class="n">draw_text</span><span class="p">(</span><span class="s2">&quot;Hello world&quot;</span><span class="p">,</span> <span class="mi">190</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="n">VIOLET</span><span class="p">)</span>
<span class="n">draw_text</span><span class="p">(</span><span class="s2">"Hello world"</span><span class="p">,</span> <span class="mi">190</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="n">VIOLET</span><span class="p">)</span>
<span class="n">end_drawing</span><span class="p">()</span>
<span class="n">close_window</span><span class="p">()</span>
</pre></div>
Expand Down Expand Up @@ -192,7 +192,7 @@ <h1>Installation<a class="headerlink" href="#installation" title="Link to this h
</div>
<p>Then install</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>python3 -m pip install setuptools
python3 -m pip install raylib==6.0.1.0
python3 -m pip install raylib==6.0.1.1
</pre></div>
</div>
<p>On most platforms it should install a binary wheel. If yours isn’t available then pip will attempt to build from
Expand All @@ -213,7 +213,7 @@ <h2>MacOS<a class="headerlink" href="#macos" title="Link to this heading"></a
<p>Older MacOS requires building from source but this is usually simple:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>brew install pkg-config
brew install raylib
python3 -m pip install raylib==6.0.1.0
python3 -m pip install raylib==6.0.1.1
</pre></div>
</div>
</section>
Expand Down Expand Up @@ -288,21 +288,21 @@ <h1>Running in a web browser<a class="headerlink" href="#running-in-a-web-browse
<p>Make a folder <code class="docutils literal notranslate"><span class="pre">my_project</span></code> with a file <code class="docutils literal notranslate"><span class="pre">main.py</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># /// script</span>
<span class="c1"># dependencies = [</span>
<span class="c1"># &quot;cffi&quot;,</span>
<span class="c1"># &quot;raylib&quot;</span>
<span class="c1"># "cffi",</span>
<span class="c1"># "raylib"</span>
<span class="c1"># ]</span>
<span class="c1"># ///</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">asyncio</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">platform</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">pyray</span><span class="w"> </span><span class="kn">import</span> <span class="o">*</span>

<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">main</span><span class="p">():</span> <span class="c1"># You MUST have an async main function</span>
<span class="n">init_window</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="mi">500</span><span class="p">,</span> <span class="s2">&quot;Hello&quot;</span><span class="p">)</span>
<span class="n">init_window</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="mi">500</span><span class="p">,</span> <span class="s2">"Hello"</span><span class="p">)</span>
<span class="n">platform</span><span class="o">.</span><span class="n">window</span><span class="o">.</span><span class="n">window_resize</span><span class="p">()</span> <span class="c1"># You MAY want to add this line</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">window_should_close</span><span class="p">():</span>
<span class="n">begin_drawing</span><span class="p">()</span>
<span class="n">clear_background</span><span class="p">(</span><span class="n">WHITE</span><span class="p">)</span>
<span class="n">draw_text</span><span class="p">(</span><span class="s2">&quot;Hello world&quot;</span><span class="p">,</span> <span class="mi">190</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="n">VIOLET</span><span class="p">)</span>
<span class="n">draw_text</span><span class="p">(</span><span class="s2">"Hello world"</span><span class="p">,</span> <span class="mi">190</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="n">VIOLET</span><span class="p">)</span>
<span class="n">end_drawing</span><span class="p">()</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1"># You MUST call this in your main loop</span>
<span class="n">close_window</span><span class="p">()</span>
Expand All @@ -317,7 +317,7 @@ <h1>Running in a web browser<a class="headerlink" href="#running-in-a-web-browse
</div>
<p>Point your browser to http://localhost:8000</p>
<p>Some features may not work, so you can disable them like this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">!=</span> <span class="s2">&quot;Emscripten&quot;</span><span class="p">:</span> <span class="c1"># audio may not work on current version of emscripten</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">!=</span> <span class="s2">"Emscripten"</span><span class="p">:</span> <span class="c1"># audio may not work on current version of emscripten</span>
<span class="n">init_audio_device</span><span class="p">()</span>
</pre></div>
</div>
Expand All @@ -331,7 +331,7 @@ <h1>Startup without printing anything<a class="headerlink" href="#startup-withou
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">ERROR</span><span class="p">)</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">pyray</span>
<span class="n">pyray</span><span class="o">.</span><span class="n">set_trace_log_level</span><span class="p">(</span><span class="n">pyray</span><span class="o">.</span><span class="n">LOG_ERROR</span><span class="p">)</span>
<span class="n">pyray</span><span class="o">.</span><span class="n">init_window</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="s2">&quot;test&quot;</span><span class="p">)</span>
<span class="n">pyray</span><span class="o">.</span><span class="n">init_window</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="s2">"test"</span><span class="p">)</span>
</pre></div>
</div>
</section>
Expand Down
Loading
Loading