Skip to content

Commit 64611f2

Browse files
committed
test: add unit tests for ToPythonLoggingLevel (#3203)
1 parent c31fdd2 commit 64611f2

4 files changed

Lines changed: 80 additions & 16 deletions

File tree

dev/pyRevitLoader/pyRevitAssemblyBuilder/SessionManager/EnvDictionarySeeder.cs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,6 @@ internal static class EnvDictionarySeeder
4545
private const string KeyAutoUpdating = "PYREVIT_AUTOUPDATE";
4646
private const string KeyOutputStyleSheet = "PYREVIT_STYLESHEET";
4747

48-
/// <summary>
49-
/// Converts PyRevitConfig's logging level enum (0=Quiet, 1=Verbose, 2=Debug)
50-
/// to Python's logging module level (30=WARNING, 20=INFO, 10=DEBUG).
51-
/// See: pyrevitlib/pyrevit/coreutils/logger.py DEFAULT_LOGGING_LEVEL
52-
/// </summary>
53-
private static int TranslateLoggingLevel(int pyrevitLevel)
54-
{
55-
switch (pyrevitLevel)
56-
{
57-
case 2: return 10; // Debug → logging.DEBUG
58-
case 1: return 20; // Verbose → logging.INFO
59-
default: return 30; // Quiet → logging.WARNING (default)
60-
}
61-
}
62-
6348
/// <summary>
6449
/// Builds the session environment dictionary and stores it in the AppDomain via a reflection
6550
/// call to <c>EnvDictionary.Seed()</c> in the Runtime assembly.
@@ -85,7 +70,11 @@ public static void Seed(UIApplication uiApp, Assembly runtimeAssembly, string py
8570
[KeyIPYVersion] = ReadIPYVersion(pyRevitRoot),
8671
[KeyCPYVersion] = "3.12.3", // Known default for the bundled CPython engine
8772

88-
[KeyLoggingLevel] = TranslateLoggingLevel(config.LoggingLevel),
73+
// Fix for #3203: PyRevitConfig.LoggingLevel returns a pyRevit enum
74+
// (0=Quiet, 1=Verbose, 2=Debug) but the Python logger reads this
75+
// env var as a Python logging module level (10=DEBUG, 20=INFO, 30=WARNING).
76+
// Translate to avoid corrupting the Python logging threshold.
77+
[KeyLoggingLevel] = ToPythonLoggingLevel(config.LoggingLevel),
8978
[KeyFileLogging] = config.FileLogging,
9079

9180
[KeyTelemetryState] = config.TelemetryState,
@@ -118,6 +107,27 @@ public static void Seed(UIApplication uiApp, Assembly runtimeAssembly, string py
118107
seedMethod.Invoke(null, new object[] { values });
119108
}
120109

110+
/// <summary>
111+
/// Converts PyRevitConfig's logging level enum (0=Quiet, 1=Verbose, 2=Debug)
112+
/// to Python's logging module level (30=WARNING, 20=INFO, 10=DEBUG).
113+
/// <para>
114+
/// Python's logger (pyrevitlib/pyrevit/coreutils/logger.py) reads PYREVIT_LOGGINGLEVEL
115+
/// and compares it directly: <c>record.levelno >= _curlevel</c>. The Python logging
116+
/// constants are DEBUG=10, INFO=20, WARNING=30. If we store 0 (pyRevit Quiet) the
117+
/// comparison <c>10 >= 0</c> is always true — every message passes, which forces the
118+
/// console window open.
119+
/// </para>
120+
/// </summary>
121+
internal static int ToPythonLoggingLevel(int pyrevitLevel)
122+
{
123+
switch (pyrevitLevel)
124+
{
125+
case 2: return 10; // Debug → logging.DEBUG
126+
case 1: return 20; // Verbose → logging.INFO
127+
default: return 30; // Quiet → logging.WARNING (Python default)
128+
}
129+
}
130+
121131
private static string ReadPyRevitVersion(string pyRevitRoot)
122132
{
123133
if (string.IsNullOrEmpty(pyRevitRoot))

dev/pyRevitLoader/pyRevitAssemblyBuilder/pyRevitAssemblyBuilder.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
<DeployToAllVersions>true</DeployToAllVersions>
1818
</PropertyGroup>
1919

20+
<ItemGroup>
21+
<InternalsVisibleTo Include="pyRevitExtensionParserTest" />
22+
</ItemGroup>
23+
2024
<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
2125
<Reference Include="WindowsBase" />
2226
<Reference Include="PresentationCore" />
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using NUnit.Framework;
2+
using pyRevitAssemblyBuilder.SessionManager;
3+
4+
namespace pyRevitExtensionParserTester
5+
{
6+
/// <summary>
7+
/// Tests for EnvDictionarySeeder logging level translation.
8+
/// Verifies that pyRevit's logging level enum (0/1/2) is correctly
9+
/// mapped to Python's logging module scale (30/20/10).
10+
/// See: issue #3203
11+
/// </summary>
12+
[TestFixture]
13+
public class EnvDictionarySeederTests
14+
{
15+
[Test]
16+
public void ToPythonLoggingLevel_Quiet_ReturnsWarning30()
17+
{
18+
// pyRevit Quiet (0) → Python logging.WARNING (30)
19+
Assert.AreEqual(30, EnvDictionarySeeder.ToPythonLoggingLevel(0),
20+
"Quiet (0) must map to logging.WARNING (30) to suppress DEBUG/INFO output");
21+
}
22+
23+
[Test]
24+
public void ToPythonLoggingLevel_Verbose_ReturnsInfo20()
25+
{
26+
// pyRevit Verbose (1) → Python logging.INFO (20)
27+
Assert.AreEqual(20, EnvDictionarySeeder.ToPythonLoggingLevel(1),
28+
"Verbose (1) must map to logging.INFO (20)");
29+
}
30+
31+
[Test]
32+
public void ToPythonLoggingLevel_Debug_ReturnsDebug10()
33+
{
34+
// pyRevit Debug (2) → Python logging.DEBUG (10)
35+
Assert.AreEqual(10, EnvDictionarySeeder.ToPythonLoggingLevel(2),
36+
"Debug (2) must map to logging.DEBUG (10)");
37+
}
38+
39+
[Test]
40+
public void ToPythonLoggingLevel_UnexpectedValue_DefaultsToWarning30()
41+
{
42+
// Any unrecognized value should fall through to WARNING (safe default)
43+
Assert.AreEqual(30, EnvDictionarySeeder.ToPythonLoggingLevel(-1),
44+
"Negative values should default to WARNING (30)");
45+
Assert.AreEqual(30, EnvDictionarySeeder.ToPythonLoggingLevel(99),
46+
"Out-of-range values should default to WARNING (30)");
47+
}
48+
}
49+
}

dev/pyRevitLoader/pyRevitExtensionParserTester/pyRevitExtensionParserTest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<Compile Include="HelpUrlTests.cs" />
6262
<Compile Include="ScriptMetadataParsingTest.cs" />
6363
<Compile Include="VersionFilteringTests.cs" />
64+
<Compile Include="EnvDictionarySeederTests.cs" />
6465
</ItemGroup>
6566

6667
<ItemGroup>

0 commit comments

Comments
 (0)