pygf
Graphics math types for Python: vectors, matrices and quaternions, built on
ctypes with no compiled extension. A shared foundation for scene-description,
shading-language and rendering projects that all need the same numeric types and
none of them should have to depend on each other for them.
from pygf import double3, matrix4d, quatd, funcs
v = double3(1.0, 0.0, 0.0)
m = matrix4d() * 2.0 # element-wise, `*` not matrix multiply
m = matrix4d() * matrix4d() # matrix multiply
n = funcs.normalize(double3(3.0, 4.0, 0.0))
w = funcs.dot(v, n)
r = quatd(0.0, 1.0, 0.0, 0.0) * v # rotate by a half turn about X
Note that * is matrix multiply for matrix * matrix, matching what this layer
has always done, and that there is no @ operator.
What is here
| Group | Types |
|---|---|
| Vectors | float2/3/4, double2/3/4, int2/3/4, uint2/3/4, half2/3/4, bool2/3/4 |
| Matrices | matrix2/3/4 in f, d, b |
| Quaternions | quatf, quatd, quath, quatb |
| USD aliases | point3f, normal3f, vector3f, color3f, texCoord2f, frame4d, ... |
| Functions | the GLSL-shaped set: abs, mix, clamp, cross, dot, normalize, determinant, inverse, ... |
Design notes
Element types, not operators. A genVec counts its slots with _slot_count,
which is rows for a matrix and the element count for a vector or quaternion.
len() is ctypes' flat element count on a matrix -- 16 for a 4x4 -- while
m[i] yields the i-th row, so driving the element-wise loops with len()
overruns. The element-wise helpers in funcs.py also recurse, because a matrix
slot is a row and handing that row to builtins.abs still fails once the count is
right.
Matrices are square only. genMat.mat_type refuses a non-square shape rather
than silently truncating it to shape[0] x shape[0].
half is a real IEEE-754 binary16. Stored as c_uint16 bit patterns in
private fields, converted on access through struct's native e format. The
component names are properties, so ctypes.Structure.__setattr__ still reaches
them. Overflow saturates to infinity rather than raising, which is what a GPU
buffer would hold.
Swizzles are runtime-dynamic. genVec.__getattr__ builds every combination
of xyzw / rgba / stpq on demand, so the class carries no swizzle
declarations at runtime. A generated if TYPE_CHECKING: block declares all of
them for type checkers and IDEs; see tools/sync_swizzle_blocks.py.
numpy interop. Importing pygf replaces numpy.array so that it reads a
container as its components: np.array(matrix3d()) gives a (3, 3) array
rather than ctypes' flat storage. Arguments it does not recognise are passed
straight through.
Layout
pygf/ the package
tests/ test_pygf.py -- stdlib plus pygf, nothing else
tools/ sync_swizzle_blocks.py -- the only writer of the swizzle blocks
static_check.py
publish.py
Development
python -m pip install -e ".[dev]"
python static_check.py
python tests/test_pygf.py
static_check.py runs compileall, ruff check --fix, and ty check. Every
check in the test file corresponds to a defect that type checking or review
surfaced; the module docstring in the test lists them.
After changing genVec's swizzle generation, regenerate the declaration blocks:
python tools/sync_swizzle_blocks.py
It is idempotent, and it is the only thing that writes those blocks.
Publishing
python -m pip install -e ".[publish]"
python publish.py build
python publish.py
License
MIT
Metadata
Release files for pygf 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pygf-0.1.4.tar.gz | 86.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pygf-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 173.6 kB
Release files / pygf-0.1.4.tar.gz
| Download URL | pygf-0.1.4.tar.gz |
|---|---|
| Size | 86.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c9a43cf3f3bd7c0cdffae85ff655c0e9f38d2c46aa8b8d372913ccc63d4e9488
|
|
BLAKE2b-256 checksum How to use checksums |
43fecb500021df2b58426149d39dd30bdce2ad4747817084621dff3a94c47705
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / pygf-0.1.4-py3-none-any.whl
| Download URL | pygf-0.1.4-py3-none-any.whl |
|---|---|
| Size | 86.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3aed177fab654da8c4d04b828ca554693c08510fd3c4a3d94db89ffb9184bab1
|
|
BLAKE2b-256 checksum How to use checksums |
182e57abf8b255aa2a98da428eee99f3819ae24450d2240ee8de034bf652e0a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Security for pygf 0.1.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.