55import collections
66import inspect
77import math
8+ from bisect import insort
89from pathlib import Path
910from typing import Any , Callable , Dict , List , NamedTuple
1011
@@ -39,6 +40,10 @@ class Priority:
3940 LAST = - 1e300
4041
4142
43+ def _priority (thing ):
44+ return getattr (thing , "priority" , Priority .NORMAL )
45+
46+
4247def _has_kwargs (f ):
4348 return not isjava (f ) and any (
4449 p .kind == inspect .Parameter .VAR_KEYWORD
@@ -65,11 +70,27 @@ def convert(self, obj: Any, **hints: Dict) -> Any:
6570 else self .converter (obj )
6671 )
6772
73+ def __lt__ (self , other ):
74+ return self .priority < _priority (other )
75+
76+ def __le__ (self , other ):
77+ return self .priority <= _priority (other )
78+
79+ def __gt__ (self , other ):
80+ return self .priority > _priority (other )
81+
82+ def __ge__ (self , other ):
83+ return self .priority >= _priority (other )
84+
6885
6986def _convert (obj : Any , converters : List [Converter ], ** hints : Dict ) -> Any :
70- suitable_converters = [c for c in converters if c .supports (obj , ** hints )]
71- prioritized = max (suitable_converters , key = lambda c : c .priority )
72- return prioritized .convert (obj , ** hints )
87+ # NB: The given converters are assumed to be sorted ascending by priority,
88+ # meaning lower-priority items appear earlier than higher-priority ones.
89+ # But we want to try the higher priority converters first, so we
90+ # need to iterate the given converters list starting at the end.
91+ for converter in reversed (converters ):
92+ if converter .supports (obj , ** hints ):
93+ return converter .convert (obj , ** hints )
7394
7495
7596# -- Python to Java --
@@ -115,7 +136,7 @@ def add_java_converter(converter: Converter) -> None:
115136 Add a converter to the list used by to_java.
116137 :param converter: A Converter going from python to java
117138 """
118- java_converters . append ( converter )
139+ insort ( java_converters , converter )
119140
120141
121142def to_java (obj : Any , ** hints : Dict ) -> Any :
@@ -204,6 +225,9 @@ def _stock_java_converters() -> List[Converter]:
204225 Converter (
205226 predicate = lambda obj : isinstance (obj , bool ),
206227 converter = _jc .Boolean ,
228+ # NB: Must be higher priority than the int converters,
229+ # because the bool type extends the int type!
230+ priority = Priority .NORMAL + 1 ,
207231 ),
208232 # int -> java.lang.Byte
209233 Converter (
@@ -486,7 +510,7 @@ def add_py_converter(converter: Converter) -> None:
486510 Add a converter to the list used by to_python.
487511 :param converter: A Converter from java to python
488512 """
489- py_converters . append ( converter )
513+ insort ( py_converters , converter )
490514
491515
492516def to_python (data : Any , gentle : bool = False ) -> Any :
0 commit comments