Skip to content

Commit f6c4382

Browse files
committed
Find all converter subclasses / descendants
1 parent a33e43b commit f6c4382

2 files changed

Lines changed: 28 additions & 6 deletions

File tree

src/undate/converters/base.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def available_converters(cls) -> Dict[str, Type["BaseDateConverter"]]:
114114
return {c.name: c for c in cls.subclasses()} # type: ignore
115115

116116
@classmethod
117-
def subclasses(cls) -> list[Type["BaseDateConverter"]]:
117+
def subclasses(cls) -> set[Type["BaseDateConverter"]]:
118118
"""
119119
List of available converters classes. Includes calendar convert
120120
subclasses.
@@ -123,11 +123,16 @@ def subclasses(cls) -> list[Type["BaseDateConverter"]]:
123123
cls.import_converters()
124124

125125
# find all direct subclasses, excluding base calendar converter
126-
subclasses = cls.__subclasses__()
127-
subclasses.remove(BaseCalendarConverter)
128-
# add all subclasses of calendar converter base class
129-
subclasses.extend(BaseCalendarConverter.__subclasses__())
130-
return subclasses
126+
direct_subclasses = cls.__subclasses__()
127+
all_subclasses = set(direct_subclasses)
128+
# recurse to find nested subclasses
129+
for subc in direct_subclasses:
130+
# print(f"class subclasses: {subc.name} {subc.subclasses()}")
131+
all_subclasses |= subc.subclasses()
132+
133+
# omit the calendar converter base class, which is not itself a converter
134+
all_subclasses -= {BaseCalendarConverter}
135+
return all_subclasses
131136

132137

133138
class BaseCalendarConverter(BaseDateConverter):

tests/test_converters/test_base.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
import pytest
44
from undate.converters.base import BaseDateConverter, BaseCalendarConverter
5+
from undate.converters.calendars import (
6+
GregorianDateConverter,
7+
HebrewDateConverter,
8+
HijriDateConverter,
9+
)
510

611

712
class TestBaseDateConverter:
@@ -29,6 +34,18 @@ def test_parse_to_string(self):
2934
with pytest.raises(NotImplementedError):
3035
BaseDateConverter().to_string(1991)
3136

37+
def test_subclasses(self):
38+
# define a nested subclass
39+
class SubSubConverter(HijriDateConverter):
40+
pass
41+
42+
subclasses = BaseDateConverter.subclasses()
43+
assert BaseCalendarConverter not in subclasses
44+
assert HijriDateConverter in subclasses
45+
assert HebrewDateConverter in subclasses
46+
assert GregorianDateConverter in subclasses
47+
assert SubSubConverter in subclasses
48+
3249

3350
def test_import_converters_import_only_once(caplog):
3451
# clear the cache, since any instantiation of an Undate

0 commit comments

Comments
 (0)