Skip to content

Commit cd47ca7

Browse files
committed
Replaced __init_subclass__ with a classmethod
1 parent 1fec606 commit cd47ca7

1 file changed

Lines changed: 15 additions & 53 deletions

File tree

src/fractured_json/__init__.py

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -74,39 +74,6 @@ class NativeEnum:
7474

7575
_native_type = None
7676

77-
def __init_subclass__(
78-
cls,
79-
native_type: object | None = None,
80-
**kwargs: dict[str, bool | int | str],
81-
) -> None:
82-
# Keep behavior for any existing code that relies on subclassing
83-
super().__init_subclass__(**kwargs)
84-
85-
# If class is dynamically constructed using type()
86-
if hasattr(cls, "_native_type") and cls._native_type is not None:
87-
native_type = cls._native_type
88-
89-
if native_type is None:
90-
return
91-
92-
native_names = [
93-
str(x)
94-
for x in native_type.GetEnumNames() # pyright: ignore[reportAttributeAccessIssue]
95-
]
96-
native_values = [
97-
int(x)
98-
for x in native_type.GetEnumValues() # pyright: ignore[reportAttributeAccessIssue]
99-
]
100-
101-
name_to_value = dict(zip(native_names, native_values, strict=True))
102-
103-
for native_name in native_names:
104-
py_name = to_snake_case(native_name, upper=True)
105-
native_value = name_to_value[native_name]
106-
# Create instance and store on class
107-
instance = cls(py_name, native_value)
108-
setattr(cls, py_name, instance)
109-
11077
@property
11178
def name(self) -> str:
11279
"""The string name of the enum value."""
@@ -134,11 +101,6 @@ def __hash__(self) -> int:
134101

135102
@classmethod
136103
def from_dotnet_type(cls, dotnet_type: object) -> type:
137-
"""Create (or return cached) dynamic NativeEnum subclass for given .NET enum type.
138-
139-
The returned class exposes each enum member as a class attribute (upper snake case), and
140-
provides classmethods `from_value` and `from_name` for lookup along with `names()` and `values()`.
141-
"""
142104
key = str(dotnet_type)
143105
if key in _native_enum_cache:
144106
return _native_enum_cache[key]
@@ -151,33 +113,34 @@ def from_dotnet_type(cls, dotnet_type: object) -> type:
151113
native_values = [int(x) for x in dotnet_type.GetEnumValues()]
152114

153115
name_to_value: dict[str, int] = {}
154-
value_to_member: dict[int, "NativeEnum"] = {}
116+
value_to_member: dict[int, NativeEnum] = {}
155117

156-
for n, v in zip(native_names, native_values):
118+
for n, v in zip(native_names, native_values, strict=False):
157119
py_name = to_snake_case(n, upper=True)
158120
inst = new_cls(py_name, v)
159121
setattr(new_cls, py_name, inst)
160122
name_to_value[py_name] = v
161123
value_to_member[v] = inst
162124

163-
# Attach lookup helpers
164-
def from_value(cls2, value: int) -> "NativeEnum":
125+
def from_value(cls2: type, value: int) -> "NativeEnum":
165126
try:
166127
return value_to_member[int(value)]
167128
except Exception as e:
168-
raise ValueError(f"{value} is not a valid value for {cls2.__name__}") from e
129+
msg = f"{value} is not a valid value for {cls2.__name__}"
130+
raise ValueError(msg) from e
169131

170-
def from_name(cls2, name: str) -> "NativeEnum":
132+
def from_name(cls2: type, name: str) -> "NativeEnum":
171133
py_name = to_snake_case(name, upper=True)
172134
try:
173135
return getattr(cls2, py_name)
174136
except Exception as e:
175-
raise ValueError(f"{name} is not a valid name for {cls2.__name__}") from e
137+
msg = f"{name} is not a valid name for {cls2.__name__}"
138+
raise ValueError(msg) from e
176139

177-
def names_fn(cls2) -> list[str]:
140+
def names_fn(_cls: type) -> list[str]:
178141
return list(name_to_value.keys())
179142

180-
def values_fn(cls2) -> list[int]:
143+
def values_fn(_cls: type) -> list[int]:
181144
return list(value_to_member.keys())
182145

183146
new_cls.from_value = classmethod(from_value)
@@ -188,6 +151,7 @@ def values_fn(cls2) -> list[int]:
188151
_native_enum_cache[key] = new_cls
189152
return new_cls
190153

154+
191155
types = get_object_types()
192156
FormatterType = types["Formatter"]
193157
FracturedJsonOptionsType = types["FracturedJsonOptions"]
@@ -209,13 +173,8 @@ def __init__(self, **kwargs: dict[str, int | str | NativeEnum]) -> None:
209173
"""Initialize FracturedJsonOptions with optional keyword arguments."""
210174
self._dotnet_instance = Activator.CreateInstance(FracturedJsonOptionsType)
211175
self._properties: dict[str, dict[str, object | str | list | bool]] = {}
212-
self._get_dotnet_props()
213176

214-
for key, value in kwargs.items():
215-
self.set(key, value)
216-
217-
def _get_dotnet_props(self) -> None:
218-
"""Dynamically populate the list of available options through .NET reflection."""
177+
# Dynamically populate the list of available options through .NET reflection.
219178
t = Type.GetType(self._dotnet_instance.GetType().AssemblyQualifiedName)
220179
props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance)
221180
for prop in props:
@@ -238,6 +197,9 @@ def _get_dotnet_props(self) -> None:
238197
"enum_names": enum_names,
239198
}
240199

200+
for key, value in kwargs.items():
201+
self.set(key, value)
202+
241203
def list_options(self) -> dict[str, dict[str, object | str | list | bool]]:
242204
"""Return a dictionary of available options and their metadata."""
243205
return self._properties

0 commit comments

Comments
 (0)