Skip to content

[DEPRECATION] Removal of Iron Python loader and Refactor loader to enhance C# session orchestration#3438

Open
romangolev wants to merge 9 commits into
developfrom
refactor/entry_module
Open

[DEPRECATION] Removal of Iron Python loader and Refactor loader to enhance C# session orchestration#3438
romangolev wants to merge 9 commits into
developfrom
refactor/entry_module

Conversation

@romangolev

Copy link
Copy Markdown
Member

This pull request makes significant changes to modernize the pyRevit build system, streamline loader startup, and drop support for Revit versions prior to 2021. The C# loader now directly manages the session without bootstrapping IronPython, and the build process is fully driven by a .NET pipeline. The runtime and loader code for Revit 2017–2020 has been removed, simplifying the codebase and reducing maintenance overhead. Additionally, extension assembly caching is improved to avoid unnecessary rebuilds.

Build system modernization:

  • Migrated the build process to a C# ModularPipelines project under the build/ directory, replacing the legacy Python CLI for CI and standard builds. The legacy CLI remains for manual workflows only. Updated documentation and build instructions accordingly. [1] [2]

Loader and runtime changes:

  • The C# loader (PyRevitLoaderApplication) now directly calls the session manager for both startup and reload, removing the IronPython bootstrap and the legacy pure-Python loader. This also clarifies the loading sequence and restricts support to Revit 2021 and newer. [1] [2] [3] [4] [5]
  • Removed obsolete loader configuration flags for the new loader, as the new C# loader is now always used.

Revit version support changes:

  • Dropped support for Revit 2013–2020: removed related runtime project files and solution entries, and updated build targets and references to only include Revit 2021 and newer. [1] [2] [3] [4] [5] [6] [7] [8]

Extension assembly caching:

  • Improved extension assembly build caching by keying the cache only on the loader's semantic version, not the DLL file write time. This prevents unnecessary extension recompilation on every loader update, but requires a version bump for generator logic changes. [1] [2]

Copilot AI review requested due to automatic review settings June 18, 2026 03:15
@devloai

devloai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Unable to trigger custom agent "Code Reviewer". You have run out of credits 😔
Please upgrade your plan or buy additional credits from the subscription page.

@romangolev

Copy link
Copy Markdown
Member Author

@copilot

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors pyRevit’s startup/reload flow so the C# loader/session manager orchestrates the session (with Python limited to pre/post load services), modernizes supporting build/documentation guidance, and removes legacy support paths (notably pre-2021 Revit loader/runtime artifacts and the “new loader” toggle).

Changes:

  • Replace the legacy pyRevitLoader.py bootstrap with session_preload.py / session_postload.py, and split Python session management into explicit pre/post phases invoked by the C# orchestrator.
  • Remove the “new loader” configuration/UI plumbing and delete legacy Python-only loader modules (uimaker.py, asmmaker.py) in favor of the C# UI/assembly pipeline.
  • Drop older Revit runtime project entries (2017–2020) and update installer assets + documentation to reflect supported versions and the new build/loader flow.

Reviewed changes

Copilot reviewed 43 out of 46 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
release/pyrevit.aip Updates installer packaging to ship session_preload.py/session_postload.py and removes legacy pyRevitLoader.py and uimaker.py payload.
release/pyrevit-hosts.json Removes pre-2021 host/build metadata, aligning release data with the supported Revit range.
release/bin-assets/netfx/engines/session_preload.py Adds pre-load Python entrypoint used by the C# session orchestrator.
release/bin-assets/netfx/engines/session_postload.py Adds post-load Python entrypoint used by the C# session orchestrator.
release/bin-assets/netfx/engines/pyRevitLoader.py Removes legacy IronPython bootstrap entry script.
release/bin-assets/netcore/engines/session_preload.py Adds pre-load Python entrypoint for netcore engine assets.
release/bin-assets/netcore/engines/session_postload.py Adds post-load Python entrypoint for netcore engine assets.
release/bin-assets/netcore/engines/pyRevitLoader.py Removes legacy IronPython bootstrap entry script (netcore assets).
pyrevitlib/pyrevit/userconfig.py Removes the new_loader option from user configuration.
pyrevitlib/pyrevit/loader/uimaker.py Deletes the legacy Python UI builder module.
pyrevitlib/pyrevit/loader/sessionmgr.py Refactors session management into perform_preload()/perform_postload() and delegates reload to the C# orchestrator.
pyrevitlib/pyrevit/loader/hooks.py Removes extension hook parsing/registration logic from Python side (now C# driven).
pyrevitlib/pyrevit/loader/asmmaker.py Deletes the legacy Python dynamic assembly builder module.
pyrevitlib/pyrevit/coreutils/ribbon.py Removes outdated TODO comments about UI cleanup ownership.
pyrevitlib/pyrevit/coreutils/appdata.py Removes Python-side appdata cleanup routine now implemented in C#.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.xaml Removes the “new loader” toggle from the Settings UI.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.ru.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.pt_br.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.ko.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.fr_fr.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.es_es.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.en_us.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.de_de.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/SettingsWindow.ResourceDictionary.chinese_s.xaml Removes localized strings for the removed “new loader” setting.
extensions/pyRevitCore.extension/pyRevit.tab/pyRevit.panel/Settings.smartbutton/script.py Removes reading/writing and reload prompting for the removed new_loader setting.
docs/architecture.md Updates architecture docs to describe the new C# orchestrated load with Python pre/post entry scripts.
docs/adding-revit-version.md Updates supported version targeting guidance and switches build instructions to the build/ .NET pipeline.
dev/pyRevitLoader/Source/PyRevitLoaderApplication.cs Routes startup + reload through the C# session manager (no IronPython bootstrap).
dev/pyRevitLoader/pyRevitExtensionParser/PyRevitConfig.cs Removes config surface area for the deprecated new_loader flag.
dev/pyRevitLoader/pyRevitAssemblyBuilder/UIManager/UIManagerConstants.cs Updates tooltip format comments to reflect current/legacy semantics without pre-2019 branching.
dev/pyRevitLoader/pyRevitAssemblyBuilder/UIManager/SessionManagerService.cs Runs Python pre/post entry scripts and moves cleanup responsibilities (stale assemblies/appdata) into C#.
dev/pyRevitLoader/pyRevitAssemblyBuilder/SessionManager/ISessionManagerService.cs Updates the session manager interface to accept firstLoad.
dev/pyRevitLoader/pyRevitAssemblyBuilder/SessionManager/Constants.cs Adds constants for Python pre/post entry script filenames.
dev/pyRevitLoader/pyRevitAssemblyBuilder/AssemblyMaker/AssemblyBuilderService.cs Improves extension assembly cache keying to avoid rebuilds on file write-time changes.
dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConsts.cs Removes constants related to the removed new_loader setting.
dev/pyRevitLabs.PyRevit.Runtime/pyRevitLabs.PyRevit.Runtime.sln Removes runtime solution projects for Revit 2017–2020.
dev/pyRevitLabs.PyRevit.Runtime/2020/pyRevitLabs.PyRevit.Runtime.2020.csproj Removes Revit 2020 runtime project file.
dev/pyRevitLabs.PyRevit.Runtime/2019/pyRevitLabs.PyRevit.Runtime.2019.csproj Removes Revit 2019 runtime project file.
dev/pyRevitLabs.PyRevit.Runtime/2018/pyRevitLabs.PyRevit.Runtime.2018.csproj Removes Revit 2018 runtime project file.
dev/pyRevitLabs.PyRevit.Runtime/2017/pyRevitLabs.PyRevit.Runtime.2017.csproj Removes Revit 2017 runtime project file.
dev/Directory.Build.targets Updates default net48 RevitVersion and removes REVIT2013–2020 constants; raises AvalonDock gating to 2021+.
CLAUDE.md Updates contributor build/run documentation to the new build/ .NET pipeline and loader sequence.
.github/copilot-instructions.md Updates repository agent instructions to reflect supported Revit versions and loader variants.

Comment thread dev/pyRevitLoader/pyRevitAssemblyBuilder/UIManager/SessionManagerService.cs Outdated
Comment thread release/bin-assets/netfx/engines/session_preload.py
Comment thread release/bin-assets/netfx/engines/session_postload.py
Comment thread release/bin-assets/netcore/engines/session_preload.py
Comment thread release/bin-assets/netcore/engines/session_postload.py

Copilot AI commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@copilot

Addressed in commit fix: robust path resolution for session scripts and C# script locator:

ExecuteEntryScript (SessionManagerService.cs): Replaced the single GetDirectoryName(_binDir) call with a two-step probe — it now checks _binDir itself first (handles a loader DLL placed directly in engines/), then falls back to the parent directory (handles the current layout where the DLL lives in engines/<version>/).

Session scripts (all four session_preload.py / session_postload.py): Replaced the hardcoded 4-level dirname walk with a walk-upward helper (_find_pyrevit_root) that searches for the pyrevitlib directory. This is correct for both the old installer layout (bin/engines/, 3 levels deep) and the current build layout (bin/netfx|netcore/engines/, 4 levels deep). A RuntimeError with a descriptive message is now raised if the root cannot be found, rather than silently continuing into a confusing ImportError.

@Wurschdhaud

Copy link
Copy Markdown
Contributor

I hope no one is trapped in Revit <2021, but i would drop support only in a major version, so no 6.X but rather 7.0

@jmcouffin

jmcouffin commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

I hope no one is trapped in Revit <2021, but i would drop support only in a major version, so no 6.X but rather 7.0

Agreed and that's the plan.
I may do 2 release at once, a 6.5 with all the latest fixes and make a specific branch that will stick. And then merge this PR and a 7.0 right away.
How does that sound? @Wurschdhaud @romangolev

@romangolev

Copy link
Copy Markdown
Member Author

@jmcouffin @Wurschdhaud dropping old pythonic loader leads to the situation where there is no loader at all as the new one supports only 2021+

That's why it does not make any sense keeping support for versions lower than 2021.

2 releases sounds good

@jmcouffin

Copy link
Copy Markdown
Contributor

Where are we on this one in terms of 'mergeability', have you tested it? @Wurschdhaud @romangolev

Maybe @tay0thman @ChrisCrosley can help test it?

@jmcouffin jmcouffin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed but not tested

@romangolev

Copy link
Copy Markdown
Member Author

@jmcouffin tested it locally "on my machine"
let me address AI comments

another testing besides mine is prefferable😊

@romangolev

Copy link
Copy Markdown
Member Author

@jmcouffin took a look again at comments - all of them addressed
solo needs additional testing

@ChrisCrosley

Copy link
Copy Markdown
Contributor

I agree it would be nice to release all the work that's already been done before dropping Revit version support. holding this as the start of 7.0 makes sense to me. I may have some time to test.

@jmcouffin jmcouffin changed the title Refactor loader to enhance C# session orchestration and cleanup [DEPRECATION] Removal of Iron Python loader and Refactor loader to enhance C# session orchestration Jun 20, 2026
@jmcouffin

Copy link
Copy Markdown
Contributor
  • Additionnal testing required
  • Do not merge before 6.5 ⚠️

@jmcouffin

Copy link
Copy Markdown
Contributor

@romangolev please take a look and fix the small conflict

@ChrisCrosley

Copy link
Copy Markdown
Contributor

I was able to build successfully on my machine. Let me know if there are specific tests I should run.

The C# session orchestrator now drives the full load directly, replacing
the legacy pyRevitLoader.py bootstrap that spun up IronPython only to
hand off to the C# loader. Residual Python session services
(env/session, telemetry, routes, output window, hooks) are split into
session_preload.py (runs before the C# UI build) and session_postload.py
(runs after) so the C# orchestrator can call them as two steps.

The new_loader user-config toggle and the legacy _new_session() Python
path are removed, along with uimaker.py whose responsibilities now live
in the C# loader. Settings UI strings and the installer manifest are
updated accordingly. The C# loader requires Revit 2021+ to run.
Mirrors the legacy pyRevitLoader.py banner that was removed in the
previous commit, so the C# entry point keeps the same branding.
The asmmaker.cleanup_assembly_files() helper has been ported into
SessionManagerService.CleanupStaleAssemblyFiles() and is now called
inline before the postload script. The C# version preserves the
existing behavior: only delete assemblies not currently loaded in the
AppDomain, and skip the cleanup when other Revit instances are running
so files another process still needs are not removed. asmmaker.py is
deleted since the assembly-building code that justified the module was
already moved to C# in a prior commit.
The pid-stamped appdata file cleanup previously implemented in
appdata.cleanup_appdata_folder() is ported to
SessionManagerService.CleanupAppDataFolder(). A new firstLoad parameter
is threaded through LoadSession so the cleanup matches the prior
behavior of being gated on EXEC_PARAMS.first_load: it runs only on
initial Revit startup, not on reload.

The Python call is removed from _perform_onsessionloadcomplete_ops()
and the now-unused imports are dropped from appdata.py. The public
LoadSession() entry stays available unchanged so the Python reload
path that resolves it by reflection continues to work.
The C# loader now discovers extension hooks and registers them with
the runtime EventHooks service, so the Python helpers that did the
same work (get_extension_hooks, register_hooks, unregister_hooks,
is_valid_hook_script, _get_hook_parts, _create_hook_id) are no longer
needed. hooks.py is trimmed to the thin wrappers around the runtime
service: get_hooks_handler, set_hooks_handler, get_event_hooks,
unregister_all_hooks, activate, and setup_hooks.
The empty _perform_onsessionreload_ops and
_perform_onsessionloadcomplete_ops placeholders, which were never
extended beyond a pass statement, are removed. reload_pyrevit() now
delegates directly to load_session() and returns its result.

ScriptExecutor.Initialize() is also dropped from the preload path: the
C# session orchestrator already initializes the executor it shares
with the runtime, so the Python call was redundant.
The C# ModularPipelines project under build/ is now the entry point
for CI and release-style local builds (dotnet run -- ci, with
Build__Channel for wip/release stamping). The pipenv-based \pyrevit
build products\ / \set build\ commands in CLAUDE.md and
docs/adding-revit-version.md are replaced with the corresponding
dotnet invocations and a pointer to build/README.md for the full
pipeline options.

The legacy Python CLI still works for local/manual workflows and
remains documented in docs/ci-cd.md; CI no longer invokes it.
The C# loader requires .NET Framework 4.8 with the
System.Runtime.CompilerServices.Unsafe and System.Collections.Immutable
references available, which the Revit 2013-2020 runtimes do not
provide. After the previous C# loader work, those versions are no
longer buildable.

- Default RevitVersion for net48 builds raised from 2017 to 2021
- REVIT2013..REVIT2020 DefineConstants removed from Directory.Build.targets
- pyRevitLabs.PyRevit.Runtime.2017..2020 projects dropped from the solution
- Xceed.Wpf.AvalonDock reference condition raised to >=2021 and the
  2018/2019/2020 DLL binaries removed
- Tooltip video format comments no longer split at Revit 2019
- Architecture, copilot-instructions and adding-revit-version docs now
  refer to "Revit 2021-2024" instead of "older Revit versions"
- pyrevit-hosts.json entries for Revit <=2020 removed
@romangolev
romangolev force-pushed the refactor/entry_module branch from ee1e08c to 4f8bc6b Compare June 21, 2026 19:20
@romangolev

Copy link
Copy Markdown
Member Author

@romangolev please take a look and fix the small conflict

taken care of

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants