19
19
20
20
[2] Python data model, https://docs.python.org/reference/datamodel.html
21
21
"""
22
+ from __future__ import annotations
23
+
24
+ import typing as ty
25
+
26
+ InstanceT = ty .TypeVar ('InstanceT' )
27
+ T = ty .TypeVar ('T' )
22
28
23
29
from nibabel .deprecated import deprecate_with_version
24
30
@@ -96,26 +102,24 @@ class ResetMixin:
96
102
10.0
97
103
"""
98
104
99
- def reset (self ):
105
+ def reset (self ) -> None :
100
106
"""Reset all OneTimeProperty attributes that may have fired already."""
101
- instdict = self .__dict__
102
- classdict = self .__class__ .__dict__
103
107
# To reset them, we simply remove them from the instance dict. At that
104
108
# point, it's as if they had never been computed. On the next access,
105
109
# the accessor function from the parent class will be called, simply
106
110
# because that's how the python descriptor protocol works.
107
- for mname , mval in classdict .items ():
108
- if mname in instdict and isinstance (mval , OneTimeProperty ):
111
+ for mname , mval in self . __class__ . __dict__ .items ():
112
+ if mname in self . __dict__ and isinstance (mval , OneTimeProperty ):
109
113
delattr (self , mname )
110
114
111
115
112
- class OneTimeProperty :
116
+ class OneTimeProperty ( ty . Generic [ T ]) :
113
117
"""A descriptor to make special properties that become normal attributes.
114
118
115
119
This is meant to be used mostly by the auto_attr decorator in this module.
116
120
"""
117
121
118
- def __init__ (self , func ):
122
+ def __init__ (self , func : ty . Callable [[ InstanceT ], T ] ):
119
123
"""Create a OneTimeProperty instance.
120
124
121
125
Parameters
@@ -128,24 +132,35 @@ def __init__(self, func):
128
132
"""
129
133
self .getter = func
130
134
self .name = func .__name__
135
+ self .__doc__ = func .__doc__
136
+
137
+ @ty .overload
138
+ def __get__ (
139
+ self , obj : None , objtype : type [InstanceT ] | None = None
140
+ ) -> ty .Callable [[InstanceT ], T ]:
141
+ ... # pragma: no cover
142
+
143
+ @ty .overload
144
+ def __get__ (self , obj : InstanceT , objtype : type [InstanceT ] | None = None ) -> T :
145
+ ... # pragma: no cover
131
146
132
- def __get__ (self , obj , type = None ):
147
+ def __get__ (
148
+ self , obj : InstanceT | None , objtype : type [InstanceT ] | None = None
149
+ ) -> T | ty .Callable [[InstanceT ], T ]:
133
150
"""This will be called on attribute access on the class or instance."""
134
151
if obj is None :
135
152
# Being called on the class, return the original function. This
136
153
# way, introspection works on the class.
137
- # return func
138
154
return self .getter
139
155
140
- # Errors in the following line are errors in setting a
141
- # OneTimeProperty
156
+ # Errors in the following line are errors in setting a OneTimeProperty
142
157
val = self .getter (obj )
143
158
144
- setattr ( obj , self .name , val )
159
+ obj . __dict__ [ self .name ] = val
145
160
return val
146
161
147
162
148
- def auto_attr (func ) :
163
+ def auto_attr (func : ty . Callable [[ InstanceT ], T ]) -> OneTimeProperty [ T ] :
149
164
"""Decorator to create OneTimeProperty attributes.
150
165
151
166
Parameters
0 commit comments