@@ -8,15 +8,16 @@ use pyo3::prelude::*;
88use crate :: singledispatch:: builtins:: Builtins ;
99use pyo3:: types:: { PyDict , PyTuple , PyType } ;
1010use 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 ,
1213} ;
1314use std:: collections:: HashMap ;
1415use std:: sync:: Mutex ;
1516
1617fn get_abc_cache_token ( py : Python ) -> Bound < ' _ , PyAny > {
17- py. import ( "abc" )
18+ py. import ( intern ! ( py , "abc" ) )
1819 . unwrap ( )
19- . getattr ( "get_cache_token" )
20+ . getattr ( intern ! ( py , "get_cache_token" ) )
2021 . unwrap ( )
2122 . call0 ( )
2223 . unwrap ( )
@@ -74,8 +75,12 @@ struct SingleDispatchState {
7475impl SingleDispatchState {
7576 fn find_impl ( & mut self , py : Python , cls : Bound < ' _ , PyAny > ) -> PyResult < PyObject > {
7677 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+ } ;
7882 let mut mro_match: Option < PyTypeReference > = None ;
83+ eprintln ! ( "Finding impl for {cls}" ) ;
7984 for typ in mro. iter ( ) {
8085 if self . registry . contains_key ( typ) {
8186 mro_match = Some ( typ. clone_ref ( py) ) ;
@@ -95,31 +100,50 @@ impl SingleDispatchState {
95100 ) ) ) ;
96101 }
97102 mro_match = Some ( m. clone_ref ( py) ) ;
103+ eprintln ! ( "MRO match: {m}" ) ;
98104 break ;
99105 }
100106 }
101- match mro_match {
107+ let impl_fn = match mro_match {
102108 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 ,
105111 } ,
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+ }
107126 }
108127 }
109128
110129 fn get_or_find_impl ( & mut self , py : Python , cls : Bound < ' _ , PyAny > ) -> PyResult < PyObject > {
111130 let free_cls = cls. unbind ( ) ;
112131 let type_reference = PyTypeReference :: new ( free_cls. clone_ref ( py) ) ;
132+ eprintln ! ( "Finding impl {type_reference}" ) ;
113133
114134 match self . cache . get ( & type_reference) {
115135 Some ( handler) => Ok ( handler. clone_ref ( py) ) ,
116136 None => {
117137 let handler_for_cls = match self . registry . get ( & type_reference) {
118138 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+ } ,
120143 } ;
121144 self . cache
122145 . insert ( type_reference, handler_for_cls. clone_ref ( py) ) ;
146+ eprintln ! ( "Found new handler {handler_for_cls}" ) ;
123147 Ok ( handler_for_cls)
124148 }
125149 }
@@ -161,7 +185,7 @@ impl SingleDispatch {
161185 ) ;
162186 }
163187 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__" ) ) {
165189 state. cache_token = Some ( get_abc_cache_token ( py) . unbind ( ) ) ;
166190 }
167191 }
@@ -178,7 +202,7 @@ impl SingleDispatch {
178202 cls : Bound < ' _ , PyAny > ,
179203 func : Bound < ' _ , PyAny > ,
180204 ) -> PyResult < PyObject > {
181- match func. getattr ( "__annotations__" ) {
205+ match func. getattr ( intern ! ( _py , "__annotations__" ) ) {
182206 Ok ( _annotations) => Err ( PyNotImplementedError :: new_err ( "Oops!" ) ) ,
183207 Err ( _) => Err ( PyTypeError :: new_err (
184208 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 {
213237 args : & Bound < ' _ , PyTuple > ,
214238 kwargs : Option < & Bound < ' _ , PyDict > > ,
215239 ) -> PyResult < Py < PyAny > > {
216- match obj. getattr ( "__class__" ) {
240+ eprintln ! ( "Calling" ) ;
241+ match obj. getattr ( intern ! ( py, "__class__" ) ) {
217242 Ok ( cls) => {
218243 let mut all_args = Vec :: with_capacity ( 1 + args. len ( ) ) ;
219244 all_args. insert ( 0 , obj) ;
220245 all_args. extend ( args) ;
221246
222247 match self . dispatch ( py, cls) {
223248 Ok ( handler) => handler. call ( py, PyTuple :: new ( py, all_args) ?, kwargs) ,
224- Err ( _ ) => panic ! ( "no handler for singledispatch" ) ,
249+ Err ( e ) => Err ( e ) ,
225250 }
226251 }
227252 Err ( _) => Err ( PyTypeError :: new_err ( "expected __class__ attribute for obj" ) ) ,
228253 }
229254 }
230255
231256 fn dispatch ( & self , py : Python < ' _ > , cls : Bound < ' _ , PyAny > ) -> PyResult < PyObject > {
257+ eprintln ! ( "Dispatching" ) ;
232258 match self . lock . lock ( ) {
233259 Ok ( mut state) => {
234260 match & state. cache_token {
0 commit comments