Technical Briefing – fake‑bpy-module


The Problem

Developers writing Blender add‑ons need reliable code‑completion for the Blender Python API, but the real API is large, version‑specific, and only available at runtime inside Blender. This repository ships fake API modules that IDEs can index offline, giving accurate import‑completion and type‑hinting without launching Blender.

What This Does

The repo contains ~540 files organized into src/, tests/, tools/, and documentation. Core responsibilities live in:

  • src/fake_bpy_module/analyzer/ – parses Blender’s .py source and generates fake modules (directives.py, nodes.py, analyzer.py).
  • src/fake_bpy_module/generator/ – writes the completed module files (code_writer.py, translator.py, writers.py).
  • src/gen.py – the top‑level driver that orchestrates analysis → generation.
  • src/fake_bpy_module/transformer/transformer_base.py – a hub used by 20 other modules; changes here ripple widely.

Measured import‑graph: 69 internal modules, 61 import edges, no cycles. The most connected module is src/fake_bpy_module/transformer/transformer (Ca = 1, Ce = 20, instability = 0.95).

How It Is Wired

  • Entry points – main in src/gen.py:197 reaches 179 functions and is called once (typically from a CI job or manual script). run in src/fake_bpy_module/analyzer/directives.py:275 reaches 42 functions and is invoked from 67 call sites.
  • Traced paths – main → analyze [filesystem via Path(config.bgl_c_file).open]; setUp [filesystem via Path(self.output_dir).mkdir].
  • Call density – analyze is called from 67 places, BaseAnalyzer from 63, compare_with_file_contents from 61, astext from 61. The transformer file src/fake_bpy_module/transformer/transformer_base.py has 20 dependents, making it a high‑blast‑radius hub.
  • File‑level responsibilities – e.g., src/fake_bpy_module/analyzer/nodes.py defines append_child, element, deepcopy and is called from 22 other files; src/fake_bpy_module/generator/writers.py (22 functions, 5 classes) is called from 3 files and writes output files.

How To Use It

StepCommand / FileEvidence
Install released packagepip install fake-bpy-module (or pip install fake-bpy-module-<ver> for a specific Blender version)pyproject.toml, setup.py
Generate modules from sourcepython src/gen.py (runs the main entry point)src/gen.py
Run the test suitepython -m pytest tests/ (342 test files)tests/ directory
Build inside Dockerdocker build -f tools/docker/Dockerfile_blender . or tools/docker/Dockerfile_upbgetools/docker/
Configure IDEAdd the generated module path to IDE’s Python completion; for PyCharm set idea.max.intellisense.filesize > 2600 (README)README.md

No environment variables or secrets are required for basic use.

Real‑World Use

A Blender add‑on developer can import import bpy in their IDE; the fake module provides stubs for every Blender type/operator, so autocomplete suggests bpy.ops.object.delete(), bpy.types.Mesh, etc., even when offline. The generated stubs stay in sync with the Blender version selected via the fake-bpy-module-<ver> packages or by running gen.py after a new Blender release.

Code Health & Issues

Static analysis (36 findings: 18 high, 18 medium) and a separate CODE HEALTH AUDIT (10 findings: 3 high, 6 medium, 1 low).

  • [HIGH] Pin third‑party GitHub Actions to a commit SHA – .github/workflows declare @v1.3.1 for pypa/gh-action-pypi-publish; a tag can move, exposing secrets. Fix: replace with 40‑char SHA.
  • [HIGH] Commit a lockfile beside the manifest – pyproject.toml has no lockfile; transitive dependencies may differ between installs. Fix: run pip lock and commit the generated file.
  • [HIGH] Make CI invoke the test suite it has – 4 workflows contain no test command; a green check that never runs assertions is misleading. Fix: add pytest (or equivalent) step to existing workflows.
  • [MEDIUM] Declare least‑privilege permissions for GITHUB_TOKEN – 4 workflows declare no permissions while referencing secrets. Fix: add permissions: contents: read at the top and widen per‑job as needed.
  • [MEDIUM] Enable Dependabot or Renovate – 2 manifests, no update bot configured. Fix: add .github/dependabot.yml covering pip and github-actions.
  • [MEDIUM] Pin the container base image by digest – tools/gen_module/Dockerfile uses python:3.10-bullseye. Fix: python:3.10-bullseye@sha256::<digest> and enable Dependabot Docker monitoring.
  • [MEDIUM] Gate pull requests on a dependency vulnerability scan – no dependency‑scan action in CI. Fix: add dependency-review-action on pull_request or osv-scanner on push/schedule.
  • [MEDIUM] Set persist-credentials: false on checkout – checkout retains the token; later steps could read pushable credentials. Fix: add with: persist-credentials: false and pass an explicit token only to the push step.
  • [LOW] Set timeout-minutes on workflow jobs – 4 jobs have no timeout, risking overlap on a two‑hourly schedule. Fix: add a realistic timeout-minutes to each job.

These findings stem from deterministic static analysis; they are not opinions.

The Bottom Line

The repository delivers a practical solution for offline Blender‑API code completion, with a clear entry point (src/gen.py) and a modular architecture that, while functional, suffers from deep nesting, duplicated blocks, and a high‑impact hub (transformer_base.py). The CI setup is incomplete (missing test invocation, unpinned Actions, no lockfile), and the Docker base image is mutable. Teams that need stable, reproducible completions should pin dependencies, commit a lockfile, and add the recommended CI safeguards; otherwise the risk of divergent builds or hidden vulnerabilities is non‑trivial.

Word count: ~430.