@@ -8,15 +8,16 @@ use pyo3::prelude::*;
8
8
use crate :: singledispatch:: builtins:: Builtins ;
9
9
use pyo3:: types:: { PyDict , PyTuple , PyType } ;
10
10
use pyo3:: {
11
- pyclass, pyfunction, pymethods, Bound , IntoPyObjectExt , Py , PyAny , PyObject , PyResult , Python ,
11
+ intern, pyclass, pyfunction, pymethods, Bound , IntoPyObjectExt , Py , PyAny , PyObject , PyResult ,
12
+ Python ,
12
13
} ;
13
14
use std:: collections:: HashMap ;
14
15
use std:: sync:: Mutex ;
15
16
16
17
fn get_abc_cache_token ( py : Python ) -> Bound < ' _ , PyAny > {
17
- py. import ( "abc" )
18
+ py. import ( intern ! ( py , "abc" ) )
18
19
. unwrap ( )
19
- . getattr ( "get_cache_token" )
20
+ . getattr ( intern ! ( py , "get_cache_token" ) )
20
21
. unwrap ( )
21
22
. call0 ( )
22
23
. unwrap ( )
@@ -74,8 +75,12 @@ struct SingleDispatchState {
74
75
impl SingleDispatchState {
75
76
fn find_impl ( & mut self , py : Python , cls : Bound < ' _ , PyAny > ) -> PyResult < PyObject > {
76
77
let cls_mro = get_obj_mro ( & cls. clone ( ) ) . unwrap ( ) ;
77
- let mro = compose_mro ( py, cls. clone ( ) , self . registry . keys ( ) ) ?;
78
+ let mro = match compose_mro ( py, cls. clone ( ) , self . registry . keys ( ) ) {
79
+ Ok ( mro) => mro,
80
+ Err ( e) => return Err ( e) ,
81
+ } ;
78
82
let mut mro_match: Option < PyTypeReference > = None ;
83
+ eprintln ! ( "Finding impl for {cls}" ) ;
79
84
for typ in mro. iter ( ) {
80
85
if self . registry . contains_key ( typ) {
81
86
mro_match = Some ( typ. clone_ref ( py) ) ;
@@ -95,31 +100,50 @@ impl SingleDispatchState {
95
100
) ) ) ;
96
101
}
97
102
mro_match = Some ( m. clone_ref ( py) ) ;
103
+ eprintln ! ( "MRO match: {m}" ) ;
98
104
break ;
99
105
}
100
106
}
101
- match mro_match {
107
+ let impl_fn = match mro_match {
102
108
Some ( _) => match self . registry . get ( & mro_match. unwrap ( ) ) {
103
- Some ( & ref it) => Ok ( it. clone_ref ( py) ) ,
104
- None => Ok ( py . None ( ) ) ,
109
+ Some ( & ref it) => Some ( it. clone_ref ( py) ) ,
110
+ None => None ,
105
111
} ,
106
- None => Ok ( py. None ( ) ) ,
112
+ None => None ,
113
+ } ;
114
+ match impl_fn {
115
+ Some ( f) => Ok ( f) ,
116
+ None => {
117
+ let obj_type = PyTypeReference :: new ( Builtins :: cached ( py) . object_type . clone_ref ( py) ) ;
118
+ eprintln ! ( "Found impl for {cls}: {obj_type}" ) ;
119
+ match self . registry . get ( & obj_type) {
120
+ Some ( it) => Ok ( it. clone_ref ( py) ) ,
121
+ None => Err ( PyRuntimeError :: new_err ( format ! (
122
+ "No dispatch function found for {cls}!"
123
+ ) ) ) ,
124
+ }
125
+ }
107
126
}
108
127
}
109
128
110
129
fn get_or_find_impl ( & mut self , py : Python , cls : Bound < ' _ , PyAny > ) -> PyResult < PyObject > {
111
130
let free_cls = cls. unbind ( ) ;
112
131
let type_reference = PyTypeReference :: new ( free_cls. clone_ref ( py) ) ;
132
+ eprintln ! ( "Finding impl {type_reference}" ) ;
113
133
114
134
match self . cache . get ( & type_reference) {
115
135
Some ( handler) => Ok ( handler. clone_ref ( py) ) ,
116
136
None => {
117
137
let handler_for_cls = match self . registry . get ( & type_reference) {
118
138
Some ( handler) => handler. clone_ref ( py) ,
119
- None => self . find_impl ( py, free_cls. bind ( py) . clone ( ) ) ?,
139
+ None => match self . find_impl ( py, free_cls. bind ( py) . clone ( ) ) {
140
+ Ok ( handler) => handler,
141
+ Err ( e) => return Err ( e) ,
142
+ } ,
120
143
} ;
121
144
self . cache
122
145
. insert ( type_reference, handler_for_cls. clone_ref ( py) ) ;
146
+ eprintln ! ( "Found new handler {handler_for_cls}" ) ;
123
147
Ok ( handler_for_cls)
124
148
}
125
149
}
@@ -161,7 +185,7 @@ impl SingleDispatch {
161
185
) ;
162
186
}
163
187
if state. cache_token . is_none ( ) {
164
- if let Ok ( _) = unbound_func. getattr ( py, "__abstractmethods__" ) {
188
+ if let Ok ( _) = unbound_func. getattr ( py, intern ! ( py , "__abstractmethods__" ) ) {
165
189
state. cache_token = Some ( get_abc_cache_token ( py) . unbind ( ) ) ;
166
190
}
167
191
}
@@ -178,7 +202,7 @@ impl SingleDispatch {
178
202
cls : Bound < ' _ , PyAny > ,
179
203
func : Bound < ' _ , PyAny > ,
180
204
) -> PyResult < PyObject > {
181
- match func. getattr ( "__annotations__" ) {
205
+ match func. getattr ( intern ! ( _py , "__annotations__" ) ) {
182
206
Ok ( _annotations) => Err ( PyNotImplementedError :: new_err ( "Oops!" ) ) ,
183
207
Err ( _) => Err ( PyTypeError :: new_err (
184
208
format ! ( "Invalid first argument to `register()`: {cls}. Use either `@register(some_class)` or plain `@register` on an annotated function." ) ,
@@ -213,22 +237,24 @@ impl SingleDispatch {
213
237
args : & Bound < ' _ , PyTuple > ,
214
238
kwargs : Option < & Bound < ' _ , PyDict > > ,
215
239
) -> PyResult < Py < PyAny > > {
216
- match obj. getattr ( "__class__" ) {
240
+ eprintln ! ( "Calling" ) ;
241
+ match obj. getattr ( intern ! ( py, "__class__" ) ) {
217
242
Ok ( cls) => {
218
243
let mut all_args = Vec :: with_capacity ( 1 + args. len ( ) ) ;
219
244
all_args. insert ( 0 , obj) ;
220
245
all_args. extend ( args) ;
221
246
222
247
match self . dispatch ( py, cls) {
223
248
Ok ( handler) => handler. call ( py, PyTuple :: new ( py, all_args) ?, kwargs) ,
224
- Err ( _ ) => panic ! ( "no handler for singledispatch" ) ,
249
+ Err ( e ) => Err ( e ) ,
225
250
}
226
251
}
227
252
Err ( _) => Err ( PyTypeError :: new_err ( "expected __class__ attribute for obj" ) ) ,
228
253
}
229
254
}
230
255
231
256
fn dispatch ( & self , py : Python < ' _ > , cls : Bound < ' _ , PyAny > ) -> PyResult < PyObject > {
257
+ eprintln ! ( "Dispatching" ) ;
232
258
match self . lock . lock ( ) {
233
259
Ok ( mut state) => {
234
260
match & state. cache_token {
0 commit comments