Skip to content

Commit 3adf071

Browse files
filmorMartin-Molinero
authored andcommitted
Name missing from __all__ on re-import (pythonnet#2717)
* Adjust test_import to always trigger error-case * Ensure that names are added to __all__ exactly once (cherry picked from commit dc69411)
1 parent ca19e49 commit 3adf071

2 files changed

Lines changed: 19 additions & 12 deletions

File tree

src/runtime/Types/ModuleObject.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ internal class ModuleObject : ExtensionType
2020
internal PyDict dict;
2121
protected string _namespace;
2222
private readonly PyList __all__ = new ();
23+
private readonly HashSet<string> allNames = new();
2324

2425
// Attributes to be set on the module according to PEP302 and 451
2526
// by the import machinery.
@@ -179,22 +180,23 @@ public void LoadNames()
179180
{
180181
foreach (string name in AssemblyManager.GetNames(_namespace))
181182
{
182-
cache.TryGetValue(name, out var m);
183-
if (m != null)
183+
bool hasValidAttribute = cache.TryGetValue(name, out var m);
184+
if (!hasValidAttribute)
184185
{
185-
continue;
186-
}
187-
BorrowedReference attr = Runtime.PyDict_GetItemString(dict, name);
188-
// If __dict__ has already set a custom property, skip it.
189-
if (!attr.IsNull)
190-
{
191-
continue;
186+
BorrowedReference attr = Runtime.PyDict_GetItemString(dict, name);
187+
// If __dict__ has already set a custom property, skip it.
188+
if (!attr.IsNull)
189+
{
190+
continue;
191+
}
192+
193+
using var attrVal = GetAttribute(name, true);
194+
hasValidAttribute = !attrVal.IsNull();
192195
}
193196

194-
using var attrVal = GetAttribute(name, true);
195-
if (!attrVal.IsNull())
197+
if (hasValidAttribute && allNames.Add(name))
196198
{
197-
// if it's a valid attribute, add it to __all__
199+
// if it's a valid attribute, add it to __all__ once.
198200
using var pyname = Runtime.PyString_FromString(name);
199201
if (Runtime.PyList_Append(__all__, pyname.Borrow()) != 0)
200202
{

tests/test_import.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
import pytest
66
import sys
77

8+
# Unused import to preload the class
9+
#
10+
# This resulted in the FileStream name missing from the wildcard import later
11+
from System.IO import FileStream # noqa: F401
12+
813
def test_relative_missing_import():
914
"""Test that a relative missing import doesn't crash.
1015
Some modules use this to check if a package is installed.

0 commit comments

Comments
 (0)