Skip to content

fix: resolve pyRevit/IPY version showing Unknown in output window#3260

Merged
tay0thman merged 3 commits intopyrevitlabs:developfrom
tay0thman:tay0thman-fix-version-unknown-output
Apr 4, 2026
Merged

fix: resolve pyRevit/IPY version showing Unknown in output window#3260
tay0thman merged 3 commits intopyrevitlabs:developfrom
tay0thman:tay0thman-fix-version-unknown-output

Conversation

@tay0thman
Copy link
Copy Markdown
Contributor

SeedEnvironmentDictionary() was called before _pyRevitRoot was resolved, so EnvDictionarySeeder.Seed() received an empty string for pyRevitRoot. Both ReadPyRevitVersion() and ReadIPYVersion() returned "Unknown" because the repo root path was empty, skipping the version file and IronPython.dll lookup entirely.

Fix: eagerly resolve _pyRevitRoot from _binDir inside InitializeScriptExecutor(), which runs immediately before SeedEnvironmentDictionary() in LoadSession(). The executing assembly lives at {pyRevitRoot}/bin/, so FindPyRevitRoot(_binDir) walks up one level and finds pyrevitlib/. If it fails (non-standard layout), _pyRevitRoot stays null and BuildSearchPaths() retries later with the extension directory as an additional hint.

## fix: resolve pyRevit/IPY version showing "Unknown" in output window

Problem

The ScriptConsole output window displays Unknown:Unknown:{revitYear} for the version header instead of the actual pyRevit and IronPython versions. This affects every script run under the new C# loader.
image

Root Cause

SeedEnvironmentDictionary() is called at the top of LoadSession() (line 114) before _pyRevitRoot has been resolved. The field _pyRevitRoot was only populated lazily inside BuildSearchPaths(), which runs during startup script execution — well after the environment dictionary was already seeded.

With _pyRevitRoot == null, EnvDictionarySeeder.Seed() receives an empty string, and both ReadPyRevitVersion("") and ReadIPYVersion("") short-circuit to "Unknown".

Fix

Eagerly resolve _pyRevitRoot from _binDir inside InitializeScriptExecutor(), which runs immediately before SeedEnvironmentDictionary(). The executing assembly lives at {pyRevitRoot}/bin/, so FindPyRevitRoot(_binDir) walks up one level and finds pyrevitlib/.

If resolution fails (non-standard install layout), _pyRevitRoot stays null and BuildSearchPaths() retries later with the extension directory as an additional hint — no worse than before.
image

Changes

SessionManagerService.cs — 1 functional line + comments added after _binDir assignment (line 266):

_pyRevitRoot = FindPyRevitRoot(_binDir);

Testing

  • Output window shows actual pyRevit version (e.g., 6.1.0.0) instead of Unknown
  • IronPython version displays correctly
  • Startup scripts still execute normally
  • Extensions in custom directories still load
  • No regression on NETFX or NETCORE builds

SeedEnvironmentDictionary() was called before _pyRevitRoot was resolved,
so EnvDictionarySeeder.Seed() received an empty string for pyRevitRoot.
Both ReadPyRevitVersion() and ReadIPYVersion() returned "Unknown" because
the repo root path was empty, skipping the version file and IronPython.dll
lookup entirely.

Fix: eagerly resolve _pyRevitRoot from _binDir inside InitializeScriptExecutor(),
which runs immediately before SeedEnvironmentDictionary() in LoadSession().
The executing assembly lives at {pyRevitRoot}/bin/, so FindPyRevitRoot(_binDir)
walks up one level and finds pyrevitlib/. If it fails (non-standard layout),
_pyRevitRoot stays null and BuildSearchPaths() retries later with the extension
directory as an additional hint.
@tay0thman tay0thman requested a review from romangolev April 4, 2026 08:31
Copy link
Copy Markdown
Contributor

@devloai devloai bot left a comment

Choose a reason for hiding this comment

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

PR Summary:

Fixes the output window displaying Unknown:Unknown:{revitYear} for pyRevit/IronPython version info. Root cause: SeedEnvironmentDictionary() was called before _pyRevitRoot was populated. Fix: one line added in InitializeScriptExecutor() to eagerly resolve _pyRevitRoot from _binDir, ensuring it's available when the env dictionary is seeded.

Review Summary:

The fix is correct and minimal. The ordering bug is real — _pyRevitRoot was only populated lazily inside BuildSearchPaths(), which runs well after SeedEnvironmentDictionary() had already passed an empty string to ReadPyRevitVersion and ReadIPYVersion. The new eager resolution from _binDir (assembly lives at {root}/bin/) is the right approach. The lazy fallback in BuildSearchPaths() is preserved as a safety net for non-standard installs, and the string.Empty null-coalescing in SeedEnvironmentDictionary continues to degrade gracefully. One minor observability gap: there's no debug log emitted when the eager resolution fails, making future regression on non-standard layouts hard to diagnose.

Suggestions

  • Add a debug log in InitializeScriptExecutor() after the FindPyRevitRoot call to record whether resolution succeeded or fell back to null. Apply
  • Add a unit/integration test that verifies EnvDictionarySeeder.Seed() receives a non-empty pyRevitRoot during a standard session load, to prevent regression of this ordering bug. Apply

Log whether pyRevit root resolution succeeded or fell back to null,
making it easier to diagnose version-display issues in the output window.
@devloai
Copy link
Copy Markdown
Contributor

devloai bot commented Apr 4, 2026

Implemented the suggestion to add a debug log after the FindPyRevitRoot call in InitializeScriptExecutor().

Change (SessionManagerService.cs):

_pyRevitRoot = FindPyRevitRoot(_binDir);

if (_pyRevitRoot != null)
    _logger.Debug($"pyRevit root resolved to: {_pyRevitRoot}");
else
    _logger.Debug("pyRevit root could not be resolved from bin directory; will retry during BuildSearchPaths");

This logs the resolved path on success, or records that the fallback path (via BuildSearchPaths) will be used — making it straightforward to diagnose version-display issues from logs.

Commit: 3669ff0

…yrevitlabs#3260)

Add PyRevitRootResolutionTests to verify that FindPyRevitRoot correctly
resolves the repo root from a bin/ subdirectory (via pyRevitfile marker
or pyrevitlib/ directory), and that ReadPyRevitVersion/ReadIPYVersion
return actual values (not 'Unknown') when given a valid root.

End-to-end tests replicate the exact bug scenario: without early
resolution of _pyRevitRoot in InitializeScriptExecutor(), the
SeedEnvironmentDictionary() call receives an empty string, causing
both version reads to short-circuit to 'Unknown'.

Changes:
- SessionManagerService.FindPyRevitRoot: private → internal (testable)
- EnvDictionarySeeder.ReadPyRevitVersion: private → internal (testable)
- New PyRevitRootResolutionTests.cs with 11 test cases
- Updated .csproj to include the new test file
@devloai
Copy link
Copy Markdown
Contributor

devloai bot commented Apr 4, 2026

✅ Added regression tests for pyRevitRoot resolution ordering bug

Implemented the review suggestion to add tests that prevent regression of the ordering bug where EnvDictionarySeeder.Seed() received an empty pyRevitRoot.

Changes (commit fad1353)

New file: PyRevitRootResolutionTests.cs — 11 NUnit test cases covering:

Category Tests What they verify
FindPyRevitRoot 5 tests Resolves root from bin/ via pyRevitfile marker; resolves via pyrevitlib/ directory; returns null for missing markers, null hint, and empty hint
ReadPyRevitVersion 4 tests Returns "Unknown" for empty/null root (the exact bug path); returns actual version from file; trims whitespace; degrades gracefully when version file is missing
ReadIPYVersion 1 test Returns "Unknown" for empty root (same bug path)
End-to-end 2 tests FindPyRevitRoot(binDir) → ReadPyRevitVersion(root) produces real version (post-fix); null root → "Unknown" (demonstrates pre-fix bug)

Visibility changes (needed for testability via existing InternalsVisibleTo):

  • SessionManagerService.FindPyRevitRoot: privateinternal
  • EnvDictionarySeeder.ReadPyRevitVersion: privateinternal
  • EnvDictionarySeeder.ReadIPYVersion was already changed to internal in a prior commit

All tests use the existing TempFileTestBase helper for temp directory management, consistent with the rest of the test suite.

@tay0thman tay0thman merged commit 718b1e5 into pyrevitlabs:develop Apr 4, 2026
@tay0thman tay0thman deleted the tay0thman-fix-version-unknown-output branch April 4, 2026 08:53
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

📦 New work-in-progress (wip) builds are available for 6.3.0.26095+0645-wip

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

📦 New work-in-progress (wip) builds are available for 6.3.0.26095+0645-wip

@devloai devloai bot mentioned this pull request Apr 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

📦 New public release are available for 6.3.0.26095+0830

1 similar comment
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

📦 New public release are available for 6.3.0.26095+0830

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.

2 participants