Skip to content

Commit b40da05

Browse files
committed
Make it possible to use inherited indexers
If a class A had indexer, and class B derived from it, Python.NET would not consider class B to have any indexer.
1 parent f808166 commit b40da05

File tree

4 files changed

+50
-0
lines changed

4 files changed

+50
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ details about the cause of the failure
3030
- Fix incorrect choice of method to invoke when using keyword arguments.
3131
- Fix non-delegate types incorrectly appearing as callable.
3232
- Indexers can now be used with interface objects
33+
- Fixed a bug where indexers could not be used if they were inherited
3334

3435
## [2.5.0][] - 2020-06-14
3536

src/runtime/classmanager.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,25 @@ private static ClassInfo GetClassInfo(Type type)
389389
ci.members[name] = ob;
390390
}
391391

392+
if (ci.indexer == null && type.IsClass)
393+
{
394+
// Indexer may be inherited.
395+
var parent = type.BaseType;
396+
while (parent != null && ci.indexer == null)
397+
{
398+
foreach (var prop in parent.GetProperties()) {
399+
var args = prop.GetIndexParameters();
400+
if (args.GetLength(0) > 0)
401+
{
402+
ci.indexer = new Indexer();
403+
ci.indexer.AddProperty(prop);
404+
break;
405+
}
406+
}
407+
parent = parent.BaseType;
408+
}
409+
}
410+
392411
return ci;
393412
}
394413
}

src/testing/indexertest.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,4 +411,12 @@ public MultiDefaultKeyIndexerTest() : base()
411411
}
412412
}
413413
}
414+
415+
public class PublicInheritedIndexerTest : PublicIndexerTest { }
416+
417+
public class ProtectedInheritedIndexerTest : ProtectedIndexerTest { }
418+
419+
public class PrivateInheritedIndexerTest : ProtectedIndexerTest { }
420+
421+
public class InternalInheritedIndexerTest : InternalIndexerTest { }
414422
}

src/tests/test_indexer.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,3 +614,25 @@ def test_using_indexer_on_object_without_indexer():
614614

615615
with pytest.raises(TypeError):
616616
o[0] = 1
617+
618+
619+
def test_inherited_indexer():
620+
"""Test that inherited indexers are accessible"""
621+
from Python.Test import PublicInheritedIndexerTest
622+
from Python.Test import ProtectedInheritedIndexerTest
623+
from Python.Test import PrivateInheritedIndexerTest
624+
from Python.Test import InternalInheritedIndexerTest
625+
626+
pub = PublicInheritedIndexerTest()
627+
pub[0] = "zero"
628+
assert pub[0] == "zero"
629+
630+
def assert_no_indexer(obj):
631+
with pytest.raises(TypeError):
632+
obj[0]
633+
with pytest.raises(TypeError):
634+
obj[0] = "zero"
635+
636+
assert_no_indexer(PrivateInheritedIndexerTest)
637+
assert_no_indexer(ProtectedInheritedIndexerTest)
638+
assert_no_indexer(InternalInheritedIndexerTest)

0 commit comments

Comments
 (0)