Skip to content

Latest commit

 

History

History
183 lines (130 loc) · 7.3 KB

File metadata and controls

183 lines (130 loc) · 7.3 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Repository Overview

pyRevit is a Rapid Application Development (RAD) environment for Autodesk Revit. It is a hybrid C#/.NET and Python (IronPython) project that bootstraps a scripting layer into Revit via an add-in loader.

Active development happens on the develop branch. master is the stable release branch.

Build System

Python 3.10 + pipenv orchestrates the entire build. All build commands use:

pipenv run pyrevit <command>

Environment Setup

pip install pipenv
pipenv install --dev    # install all Python deps
pipenv run pyrevit check   # verify build environment (MSBuild, .NET, etc.)

Requirements: Visual Studio 2022 with .NET desktop workload, .NET 8.0, .NET Framework 4.7.2/4.8, MSBuild.

Key Build Commands

pipenv run pyrevit build products          # build all binaries (Release)
pipenv run pyrevit build products Debug    # build in Debug config
pipenv run pyrevit build labs              # build C# labs only
pipenv run pyrevit build engines           # build Python engines
pipenv run pyrevit build installers        # create Inno Setup + MSI installers
pipenv run pyrevit build autocmp           # build CLI autocomplete

Build outputs:

  • bin/netfx/ - .NET Framework binaries
  • bin/netcore/ - .NET 8.0 binaries
  • dist/ - installer packages

Linting

pipenv run check-docstrings   # ruff check --fix pyrevitlib/pyrevit
pipenv run ruff               # lint Python code
pipenv run black              # format Python code
pipenv run mypy               # type checking

Docstrings follow Google style convention (enforced by ruff with select = ["D"]).

Architecture

Component Map

pyRevitLoader (C#)          -- IExternalApplication; bootstraps IronPython into Revit
  --> pyrevitloader.py      -- Python entry point; loads the session
    --> pyrevitlib/pyrevit/  -- Core Python library (IronPython 2.7.12 compatible)
      loader/               -- Extension discovery, session management
      extensions/           -- Extension installation/uninstallation
      revit/                -- Revit API wrappers
      forms/                -- WPF/XAML UI components
      routes/               -- HTTP routing for telemetry API
      coreutils/            -- Shared utilities

pyRevitLabs.PyRevit.Runtime (C#) -- Executes commands when ribbon buttons are clicked
  ScriptCommand.cs          -- IExternalCommand implementation; dispatches to engines
  *Engine.cs                -- Per-language engines: IronPython, CPython, Dynamo, C#, VB

pyRevitCLI (C#)             -- `pyrevit` command-line tool for install/config/clone
pyRevitTelemetryServer (Go) -- Usage statistics server (MongoDB/PostgreSQL backend)

Extension System

Extensions live in /extensions/ and are registered in extensions/extensions.json. Each extension is a directory with the .extension suffix containing panels, buttons, and scripts.

Scripts in extensions run inside the Runtime engine: Python files execute via IronPython (or CPython if configured), and can import from pyrevitlib/pyrevit/. Multiple scripting languages are supported per-button: Python, C#, VB.Net, Dynamo.

Dual .NET Target

Most C# projects dual-target net48 (Revit 2017-2024) and net8.0 (Revit 2025+). Build artifacts are placed in bin/netfx/ and bin/netcore/ respectively. dev/Directory.Build.props and dev/Directory.Build.targets centralize shared MSBuild config.

Git Submodules

Heavy dependencies (IronPython 2.7.12, IronPython 3.4.0, Python.Net, MahApps.Metro, etc.) are git submodules under dev/modules/. Run git submodule update --init --recursive after cloning.

Key Solutions

Solution Purpose
dev/pyRevitLabs/pyRevitLabs.sln CLI, Doctor, common libraries
dev/pyRevitLabs.PyRevit.Runtime/pyRevitLabs.PyRevit.Runtime.sln Runtime command execution
dev/pyRevitLoader/pyRevitLoader.sln Add-in loader DLL

Testing

There is no automated Python test runner at the repo level. C# unit tests are in dev/pyRevitLabs/pyRevitLabs.UnitTests/. Manual/integration testing is done through the pyRevitDevTools.extension UI inside Revit.

pipenv run pyrevit test telem   # start telemetry server for manual testing

Documentation

Built with MkDocs + Material theme. Source in docs/. Deploy via:

pipenv run mkdocs gh-deploy --force

Python Library Compatibility

Any edit to pyrevitlib/ must remain compatible with IronPython 2.7.12 (the default engine).

  • No f-strings (use .format())
  • No typing module, dataclasses, walrus operator (:=), or match/case
  • No pathlib (not available in IronPython 2)
  • unicode and str are distinct types in IronPython 2 — use compat.safe_strtype() instead of str()
  • Use pyrevit.compat for version-gating instead of inline sys.version checks:
    • compat.PY2 / compat.PY3 — Python major version
    • compat.IRONPY2 / compat.IRONPY3 — IronPython 2 or 3
    • compat.NETCORE / compat.NETFRAMEWORK — .NET runtime (.NET 8 vs .NET Framework)
    • compat.get_elementid_value_func() — returns correct ElementId accessor per Revit version

Dual .NET Build Awareness

Any C# change must work under both build targets defined in dev/pyRevitLoader/Directory.Build.props:

  • net48 --> bin/netfx/ --> Revit 2017-2024 (.NET Framework 4.8)
  • net8.0-windows --> bin/netcore/ --> Revit 2025+ (.NET 8.0)

Check for #if NETCOREAPP / #if NETFRAMEWORK guards in the runtime project before adding new .NET API calls. The runtime solution is at dev/pyRevitLabs.PyRevit.Runtime/.

Codebase Navigation

Where to look when changing behavior:

Goal Location
Change how ribbon/extensions load at startup pyrevitlib/pyrevit/loader/
Change runtime command execution dev/pyRevitLabs.PyRevit.Runtime/
Change how the add-in bootstraps into Revit dev/pyRevitLoader/Source/PyRevitLoaderApplication.cs
Change Revit API wrappers (DB/UI helpers) pyrevitlib/pyrevit/revit/
Change WPF UI components (forms, dialogs) pyrevitlib/pyrevit/forms/
Change CLI behavior dev/pyRevitLabs/pyRevitCLI/
Change extension/attachment management dev/pyRevitLabs/pyRevitLabs.PyRevit/
Add a version compatibility shim pyrevitlib/pyrevit/compat.py
Find how a config key works pyrevitlib/pyrevit/userconfig.py

Revit API Version Differences

API Revit <= 2023 Revit 2024+
ElementId integer value .IntegerValue .Value
.NET runtime .NET Framework 4.8 .NET 8.0

Always use HOST_APP.is_newer_than(year) or compat.get_elementid_value_func() rather than hardcoding version checks inline.

Extension Bundle Structure

MyExtension.extension/
  Tab.tab/
    Panel.panel/
      Button.pushbutton/
        script.py       # executed when button clicked
        bundle.yaml     # title, tooltip, author (supports i18n)
        icon.png        # 32x32 px

Supported button types: .pushbutton, .smartbutton, .pulldown, .splitbutton, .stack, .panelbutton, .linkbutton, .urlbutton

Scripts receive these globals injected by the loader:

  • __revit__ -- UIApplication instance
  • __commandpath__ -- directory of the running script
  • __shiftclick__ -- True if Shift was held when clicking