Skip to content

Commit eec0e23

Browse files
committed
refactor: fix Ruff violations across codebase
1 parent 3d6e364 commit eec0e23

12 files changed

Lines changed: 425 additions & 308 deletions

File tree

objinspect/__init__.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ def inspect(
1414
public: bool = True,
1515
inherited: bool = True,
1616
static_methods: bool = True,
17-
classmethod: bool = False,
17+
class_method: bool = False,
1818
protected: bool = False,
1919
private: bool = False,
20+
**legacy_options: object,
2021
) -> Function | Class | Method:
2122
"""
2223
Inspects an object and returns a structured representation of its attributes and methods.
@@ -32,9 +33,10 @@ def inspect(
3233
public (bool, optional): Whether to include public attributes and methods.
3334
inherited (bool, optional): Whether to include inherited attributes and methods.
3435
static_methods (bool, optional): Whether to include static methods.
35-
classmethod (bool, optional): Whether to include class methods.
36+
class_method (bool, optional): Whether to include class methods.
3637
protected (bool, optional): Whether to include protected attributes and methods (prefixed with _).
3738
private (bool, optional): Whether to include private attributes and methods (prefixed with __).
39+
**legacy_options: Backward-compatible keyword options (supports `classmethod`).
3840
3941
Returns:
4042
An object representing the structure of the inspected object.
@@ -68,13 +70,22 @@ def inspect(
6870
return Function(obj)
6971
return Method(obj, cls)
7072

73+
legacy_classmethod = legacy_options.pop("classmethod", None)
74+
if legacy_classmethod is not None:
75+
if not isinstance(legacy_classmethod, bool):
76+
raise TypeError("`classmethod` must be a bool")
77+
class_method = legacy_classmethod
78+
if legacy_options:
79+
unexpected_keys = ", ".join(sorted(legacy_options))
80+
raise TypeError(f"Unexpected keyword argument(s): {unexpected_keys}")
81+
7182
return Class(
7283
obj,
7384
init=init,
7485
public=public,
7586
inherited=inherited,
7687
static_methods=static_methods,
77-
classmethod=classmethod,
88+
class_method=class_method,
7889
protected=protected,
7990
private=private,
8091
)
@@ -107,10 +118,10 @@ def get_class_from_method(method: Callable[..., Any]) -> type | None:
107118

108119

109120
__all__ = [
110-
"inspect",
111121
"Class",
112122
"Function",
113123
"Method",
114-
"Parameter",
115124
"MethodFilter",
125+
"Parameter",
126+
"inspect",
116127
]

objinspect/_class.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import functools
22
import inspect
33
from dataclasses import dataclass
4-
from typing import Any
54

65
import docstring_parser
76
from docstring_parser import Docstring
@@ -29,7 +28,7 @@ class Class:
2928
public (bool, optional): Include public methods.
3029
inherited (bool, optional): Include inherited methods.
3130
static_methods (bool, optional): Include static methods.
32-
classmethod (bool, optional): Include class methods.
31+
class_method (bool, optional): Include class methods.
3332
protected (bool, optional): Include protected methods.
3433
private (bool, optional): Include private methods.
3534
@@ -55,9 +54,19 @@ def __init__(
5554
static_methods: bool = True,
5655
protected: bool = False,
5756
private: bool = False,
58-
classmethod: bool = True,
57+
class_method: bool = True,
5958
skip_self: bool = True,
59+
**legacy_options: object,
6060
) -> None:
61+
legacy_classmethod = legacy_options.pop("classmethod", None)
62+
if legacy_classmethod is not None:
63+
if not isinstance(legacy_classmethod, bool):
64+
raise TypeError("`classmethod` must be a bool")
65+
class_method = legacy_classmethod
66+
if legacy_options:
67+
unexpected_keys = ", ".join(sorted(legacy_options))
68+
raise TypeError(f"Unexpected keyword argument(s): {unexpected_keys}")
69+
6170
self.cls = cls
6271
self.skip_self = skip_self
6372
self.receieved_instance = not inspect.isclass(cls)
@@ -79,13 +88,14 @@ def __init__(
7988
"static_methods": static_methods,
8089
"protected": protected,
8190
"private": private,
82-
"classmethod": classmethod,
91+
"class_method": class_method,
8392
}
8493
self._methods = self._find_methods()
8594
self.has_init = "__init__" in self._methods
86-
self.docstring: Docstring | None = (
87-
docstring_parser.parse(self.docstring_text) if self.has_docstring else None # type: ignore
88-
)
95+
if self.has_docstring and self.docstring_text is not None:
96+
self.docstring: Docstring | None = docstring_parser.parse(self.docstring_text)
97+
else:
98+
self.docstring = None
8999
self.description = _get_docstr_description(self.docstring)
90100

91101
def __repr__(self) -> str:
@@ -95,7 +105,9 @@ def __repr__(self) -> str:
95105
def _class_base(self) -> type:
96106
if self.is_initialized:
97107
return self.cls.__class__ if hasattr(self.cls, "__class__") else type(self.cls)
98-
return self.cls # type: ignore[return-value]
108+
if isinstance(self.cls, type):
109+
return self.cls
110+
return type(self.cls)
99111

100112
def _find_methods(self) -> dict[str, Method]:
101113
method_filter = MethodFilter(**self.extractor_kwargs)
@@ -112,7 +124,7 @@ def _find_methods(self) -> dict[str, Method]:
112124
methods[method.name] = method
113125
return methods
114126

115-
def init(self, *args: Any, **kwargs: Any) -> None:
127+
def init(self, *args: object, **kwargs: object) -> None:
116128
"""
117129
Initializes the class as an instance using the provided arguments.
118130
@@ -128,7 +140,7 @@ def init(self, *args: Any, **kwargs: Any) -> None:
128140
raise TypeError(f"Cannot initialize object of type {type(self.cls)}")
129141
self.is_initialized = True
130142

131-
def call_method(self, method: str | int, *args: Any, **kwargs: Any) -> Any:
143+
def call_method(self, method: str | int, *args: object, **kwargs: object) -> object:
132144
"""
133145
Calls the specified method on the class or instance.
134146
@@ -189,7 +201,7 @@ def methods(self) -> list[Method]:
189201
return list(self._methods.values())
190202

191203
@property
192-
def dict(self) -> dict[str, Any]:
204+
def dict(self) -> dict[str, object]:
193205
"""Return a dictionary representation of the class."""
194206
return {
195207
"name": self.name,
@@ -238,10 +250,10 @@ def as_str(
238250

239251

240252
def split_init_args(
241-
args: dict[str, Any],
253+
args: dict[str, object],
242254
cls: Class,
243255
method: Method,
244-
) -> tuple[dict[str, Any], dict[str, Any]]:
256+
) -> tuple[dict[str, object], dict[str, object]]:
245257
"""
246258
Split the arguments into those that should be passed to the __init__ method
247259
and those that should be passed to the method call.

objinspect/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import inspect
22

3-
EMPTY = inspect._empty
3+
EMPTY = inspect.Signature.empty
44

55
__all__ = ["EMPTY"]

objinspect/function.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from collections.abc import Callable
33
from dataclasses import dataclass
44
from types import NoneType
5-
from typing import Any
65

76
import docstring_parser
87
from docstring_parser import Docstring
@@ -57,15 +56,16 @@ class Function:
5756
5857
"""
5958

60-
def __init__(self, func: Callable[..., Any], skip_self: bool = True) -> None:
59+
def __init__(self, func: Callable[..., object], skip_self: bool = True) -> None:
6160
self.func = func
6261
self.skip_self = skip_self
6362
self.name: str = self.func.__name__
6463
self.docstring_text: str | None = inspect.getdoc(self.func)
6564
self.has_docstring = _has_docstr(self.docstring_text)
66-
self.docstring: Docstring | None = (
67-
docstring_parser.parse(self.docstring_text) if self.has_docstring else None # type: ignore
68-
)
65+
if self.has_docstring and self.docstring_text is not None:
66+
self.docstring: Docstring | None = docstring_parser.parse(self.docstring_text)
67+
else:
68+
self.docstring = None
6969
self.return_type = NoneType
7070
self._parameters = self._get_parameters()
7171
self.description = _get_docstr_description(self.docstring)
@@ -81,9 +81,8 @@ def _get_parameters(self) -> dict[str, Parameter]:
8181
if self.docstring is not None:
8282
params_mapping = {par.arg_name: par for par in self.docstring.params}
8383
for param in params:
84-
if parameter := params_mapping.get(param.name, False):
85-
if parameter.description: # type: ignore
86-
param.description = parameter.description # type: ignore
84+
if (parameter := params_mapping.get(param.name)) and parameter.description:
85+
param.description = parameter.description
8786

8887
parameters = {}
8988
for param in params:
@@ -113,7 +112,7 @@ def get_param(self, arg: str | int) -> Parameter:
113112
case _:
114113
raise TypeError(type(arg))
115114

116-
def call(self, *args: Any, **kwargs: Any) -> Any:
115+
def call(self, *args: object, **kwargs: object) -> object:
117116
"""
118117
Calls the function and returns the result of its call.
119118
@@ -129,7 +128,7 @@ def params(self) -> list[Parameter]:
129128
return list(self._parameters.values())
130129

131130
@property
132-
def dict(self) -> dict[str, Any]:
131+
def dict(self) -> dict[str, object]:
133132
"""Return a dictionary representation of the function."""
134133
return {
135134
"name": self.name,

objinspect/method.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import inspect
22
from collections.abc import Callable
33
from inspect import _ParameterKind
4-
from typing import Any
54

65
from objinspect.function import Function
76

87

8+
def _resolve_class_method_option(class_method: bool, legacy_options: dict[str, object]) -> bool:
9+
legacy_classmethod = legacy_options.pop("classmethod", None)
10+
if legacy_classmethod is not None:
11+
if not isinstance(legacy_classmethod, bool):
12+
raise TypeError("`classmethod` must be a bool")
13+
class_method = legacy_classmethod
14+
if legacy_options:
15+
unexpected_keys = ", ".join(sorted(legacy_options))
16+
raise TypeError(f"Unexpected keyword argument(s): {unexpected_keys}")
17+
return class_method
18+
19+
920
class Method(Function):
1021
"""
1122
The Method class represents a method of a class.
@@ -32,7 +43,7 @@ class Method(Function):
3243
3344
"""
3445

35-
def __init__(self, method: Callable[..., Any], cls: type, skip_self: bool = True) -> None:
46+
def __init__(self, method: Callable[..., object], cls: type, skip_self: bool = True) -> None:
3647
super().__init__(method, skip_self)
3748
self.cls = cls
3849

@@ -44,11 +55,12 @@ def class_instance(self) -> object | None:
4455
@property
4556
def is_static(self) -> bool:
4657
"""Whether the method is a static method."""
58+
if not inspect.isroutine(self.func):
59+
return False
4760
for cls in inspect.getmro(self.cls):
48-
if inspect.isroutine(self.func):
49-
if self.name in cls.__dict__:
50-
binded_value = cls.__dict__[self.name]
51-
return isinstance(binded_value, staticmethod)
61+
if self.name in cls.__dict__:
62+
binded_value = cls.__dict__[self.name]
63+
return isinstance(binded_value, staticmethod)
5264
return False
5365

5466
@property
@@ -94,18 +106,24 @@ def __init__(
94106
static_methods: bool = True,
95107
protected: bool = False,
96108
private: bool = False,
97-
classmethod: bool = False,
109+
class_method: bool = False,
110+
**legacy_options: object,
98111
) -> None:
112+
class_method = _resolve_class_method_option(class_method, dict(legacy_options))
113+
99114
self.checks: list[Callable[[Method], bool]] = []
100-
# fmt: off
101-
if not init: self.checks.append(lambda method: method.name == "__init__")
102-
if not static_methods: self.checks.append(lambda method: method.is_static)
103-
if not inherited: self.checks.append(lambda method: method.is_inherited)
104-
if not private: self.checks.append(lambda method: method.is_private)
105-
if not protected: self.checks.append(lambda method: method.is_protected)
106-
if not public: self.checks.append(lambda method: method.is_public)
107-
if not classmethod: self.checks.append(lambda method: method.is_classmethod)
108-
# fmt: on
115+
filter_checks: tuple[tuple[bool, Callable[[Method], bool]], ...] = (
116+
(not init, lambda method: method.name == "__init__"),
117+
(not static_methods, lambda method: method.is_static),
118+
(not inherited, lambda method: method.is_inherited),
119+
(not private, lambda method: method.is_private),
120+
(not protected, lambda method: method.is_protected),
121+
(not public, lambda method: method.is_public),
122+
(not class_method, lambda method: method.is_classmethod),
123+
)
124+
for enabled, check in filter_checks:
125+
if enabled:
126+
self.checks.append(check)
109127

110128
def check(self, method: Method) -> bool:
111129
"""
@@ -117,10 +135,7 @@ def check(self, method: Method) -> bool:
117135
Returns:
118136
bool: True if the method passes all filters, False otherwise.
119137
"""
120-
for check_func in self.checks:
121-
if check_func(method):
122-
return False
123-
return True
138+
return all(not check_func(method) for check_func in self.checks)
124139

125140
def extract(self, methods: list[Method]) -> list[Method]:
126141
"""

0 commit comments

Comments
 (0)