Skip to content

Commit f512615

Browse files
committed
Give converters a name property
And make str(Converter) yield a representation helpful for debugging.
1 parent e614bb9 commit f512615

2 files changed

Lines changed: 56 additions & 46 deletions

File tree

src/scyjava/_convert.py

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Converter(NamedTuple):
5555
predicate: Callable[[Any], bool]
5656
converter: Callable[[Any], Any]
5757
priority: float = Priority.NORMAL
58+
name: str = "<unnamed>"
5859

5960
def supports(self, obj: Any, **hints: Dict) -> bool:
6061
return (
@@ -82,6 +83,9 @@ def __gt__(self, other):
8283
def __ge__(self, other):
8384
return self.priority >= _priority(other)
8485

86+
def __str__(self):
87+
return self.name
88+
8589

8690
def _convert(obj: Any, converters: List[Converter], **hints: Dict) -> Any:
8791
# NB: The given converters are assumed to be sorted ascending by priority,
@@ -198,79 +202,79 @@ def _stock_java_converters() -> List[Converter]:
198202
"""
199203
start_jvm()
200204
return [
201-
# Other (Exceptional) converter
202205
Converter(
206+
name="Other (Exceptional) converter",
203207
predicate=lambda obj: True,
204208
converter=_raise_type_exception,
205209
priority=Priority.EXTREMELY_LOW - 1,
206210
),
207-
# None -> None
208211
Converter(
212+
name="None -> None",
209213
predicate=lambda obj: obj is None,
210214
converter=lambda obj: None,
211215
priority=Priority.EXTREMELY_HIGH + 1,
212216
),
213-
# Java object identity
214217
Converter(
218+
name="Java object identity",
215219
predicate=isjava,
216220
converter=lambda obj: obj,
217221
priority=Priority.EXTREMELY_HIGH,
218222
),
219-
# str -> java.lang.String
220223
Converter(
224+
name="str -> java.lang.String",
221225
predicate=lambda obj: isinstance(obj, str),
222226
converter=lambda obj: _jc.String(obj.encode("utf-8"), "utf-8"),
223227
),
224-
# bool -> java.lang.Boolean
225228
Converter(
229+
name="bool -> java.lang.Boolean",
226230
predicate=lambda obj: isinstance(obj, bool),
227231
converter=_jc.Boolean,
228232
# NB: Must be higher priority than the int converters,
229233
# because the bool type extends the int type!
230234
priority=Priority.NORMAL + 1,
231235
),
232-
# int -> java.lang.Byte
233236
Converter(
237+
name="int -> java.lang.Byte",
234238
predicate=lambda obj, **hints: isinstance(obj, int)
235239
and ("type" in hints and hints["type"] in ("b", "byte", "Byte"))
236240
and _jc.Byte.MIN_VALUE <= obj <= _jc.Byte.MAX_VALUE,
237241
converter=_jc.Byte,
238242
priority=Priority.HIGH,
239243
),
240-
# int -> java.lang.Short
241244
Converter(
245+
name="int -> java.lang.Short",
242246
predicate=lambda obj, **hints: isinstance(obj, int)
243247
and ("type" in hints and hints["type"] in ("s", "short", "Short"))
244248
and _jc.Short.MIN_VALUE <= obj <= _jc.Short.MAX_VALUE,
245249
converter=_jc.Short,
246250
priority=Priority.HIGH,
247251
),
248-
# int -> java.lang.Integer
249252
Converter(
253+
name="int -> java.lang.Integer",
250254
predicate=lambda obj, **hints: isinstance(obj, int)
251255
and ("type" not in hints or hints["type"] in ("i", "int", "Integer"))
252256
and _jc.Integer.MIN_VALUE <= obj <= _jc.Integer.MAX_VALUE,
253257
converter=_jc.Integer,
254258
),
255-
# int -> java.lang.Long
256259
Converter(
260+
name="int -> java.lang.Long",
257261
predicate=lambda obj, **hints: isinstance(obj, int)
258262
and ("type" not in hints or hints["type"] in ("j", "l", "long", "Long"))
259263
and _jc.Long.MIN_VALUE <= obj <= _jc.Long.MAX_VALUE,
260264
converter=_jc.Long,
261265
priority=Priority.NORMAL - 1,
262266
),
263-
# int -> java.math.BigInteger
264267
Converter(
268+
name="int -> java.math.BigInteger",
265269
predicate=lambda obj, **hints: isinstance(obj, int)
266270
and (
267271
"type" not in hints or hints["type"] in ("bi", "bigint", "BigInteger")
268272
),
269273
converter=lambda obj: _jc.BigInteger(str(obj)),
270274
priority=Priority.NORMAL - 2,
271275
),
272-
# float -> java.lang.Float
273276
Converter(
277+
name="float -> java.lang.Float",
274278
predicate=lambda obj, **hints: isinstance(obj, float)
275279
and ("type" not in hints or hints["type"] in ("f", "float", "Float"))
276280
and (
@@ -280,8 +284,8 @@ def _stock_java_converters() -> List[Converter]:
280284
),
281285
converter=_jc.Float,
282286
),
283-
# float -> java.lang.Double
284287
Converter(
288+
name="float -> java.lang.Double",
285289
predicate=lambda obj, **hints: isinstance(obj, float)
286290
and ("type" not in hints or hints["type"] in ("d", "double", "Double"))
287291
and (
@@ -292,42 +296,42 @@ def _stock_java_converters() -> List[Converter]:
292296
converter=_jc.Double,
293297
priority=Priority.NORMAL - 1,
294298
),
295-
# float -> java.math.BigDecimal
296299
Converter(
300+
name="float -> java.math.BigDecimal",
297301
predicate=lambda obj, **hints: isinstance(obj, float)
298302
and (
299303
"type" not in hints or hints["type"] in ("bd", "bigdec", "BigDecimal")
300304
),
301305
converter=lambda obj: _jc.BigDecimal(str(obj)),
302306
priority=Priority.NORMAL - 2,
303307
),
304-
# pathlib.Path -> java.nio.file.Path
305308
Converter(
309+
name="pathlib.Path -> java.nio.file.Path",
306310
predicate=lambda obj: isinstance(obj, Path),
307311
# Pass an empty String array in addition to our path
308312
# To make it clear to jep that we want the string-args version
309313
# JPype is smart enough to know that, but it doesn't mind the extra args
310314
converter=lambda obj: _jc.Paths.get(str(obj), jarray(_jc.String, [0])),
311315
priority=Priority.NORMAL + 1,
312316
),
313-
# pandas.DataFrame -> org.scijava.table.Table
314317
Converter(
318+
name="pandas.DataFrame -> org.scijava.table.Table",
315319
predicate=lambda obj: type(obj).__name__ == "DataFrame",
316320
converter=_pandas_to_table,
317321
priority=Priority.NORMAL + 1,
318322
),
319-
# collections.abc.Mapping -> java.util.Map
320323
Converter(
324+
name="collections.abc.Mapping -> java.util.Map",
321325
predicate=lambda obj: isinstance(obj, collections.abc.Mapping),
322326
converter=_convertMap,
323327
),
324-
# collections.abc.Set -> java.util.Set
325328
Converter(
329+
name="collections.abc.Set -> java.util.Set",
326330
predicate=lambda obj: isinstance(obj, collections.abc.Set),
327331
converter=_convertSet,
328332
),
329-
# collections.abc.Iterable -> java.util.Iterable
330333
Converter(
334+
name="collections.abc.Iterable -> java.util.Iterable",
331335
predicate=lambda obj: isinstance(obj, collections.abc.Iterable),
332336
converter=_convertIterable,
333337
priority=Priority.NORMAL - 1,
@@ -553,160 +557,165 @@ def _stock_py_converters() -> List:
553557
start_jvm()
554558

555559
converters = [
556-
# Other (Exceptional) converter
557560
Converter(
561+
name="Other (Exceptional) converter",
558562
predicate=lambda obj: True,
559563
converter=_raise_type_exception,
560564
priority=Priority.EXTREMELY_LOW - 1,
561565
),
562-
# Python object identity
563566
Converter(
567+
name="Python object identity",
564568
predicate=lambda obj: not isjava(obj),
565569
converter=lambda obj: obj,
566570
priority=Priority.EXTREMELY_HIGH,
567571
),
568-
# java.lang.Boolean -> bool
569572
Converter(
573+
name="java.lang.Boolean -> bool",
570574
predicate=lambda obj: jinstance(obj, _jc.Boolean),
571575
converter=lambda obj: obj.booleanValue(),
572576
),
573-
# java.lang.Byte -> int
574577
Converter(
578+
name="java.lang.Byte -> int",
575579
predicate=lambda obj: jinstance(obj, _jc.Byte),
576580
converter=lambda obj: int(obj.byteValue()),
577581
),
578-
# java.lang.Character -> str
579582
Converter(
583+
name="java.lang.Character -> str",
580584
predicate=lambda obj: jinstance(obj, _jc.Character),
581585
converter=lambda obj: str,
582586
),
583-
# java.lang.Double -> float
584587
Converter(
588+
name="java.lang.Double -> float",
585589
predicate=lambda obj: jinstance(obj, _jc.Double),
586590
converter=lambda obj: float(obj.doubleValue()),
587591
),
588-
# java.lang.Float -> float
589592
Converter(
593+
name="java.lang.Float -> float",
590594
predicate=lambda obj: jinstance(obj, _jc.Float),
591595
converter=lambda obj: float(obj.floatValue()),
592596
),
593-
# java.lang.Integer -> int
594597
Converter(
598+
name="java.lang.Integer -> int",
595599
predicate=lambda obj: jinstance(obj, _jc.Integer),
596600
converter=lambda obj: int(obj.intValue()),
597601
),
598-
# java.lang.Long -> int
599602
Converter(
603+
name="java.lang.Long -> int",
600604
predicate=lambda obj: jinstance(obj, _jc.Long),
601605
converter=lambda obj: int(obj.longValue()),
602606
),
603-
# java.lang.Short -> int
604607
Converter(
608+
name="java.lang.Short -> int",
605609
predicate=lambda obj: jinstance(obj, _jc.Short),
606610
converter=lambda obj: int(obj.shortValue()),
607611
),
608-
# java.lang.String -> str
609612
Converter(
613+
name="java.lang.String -> str",
610614
predicate=lambda obj: jinstance(obj, _jc.String),
611615
converter=lambda obj: str(obj),
612616
),
613-
# java.math.BigInteger -> int
614617
Converter(
618+
name="java.math.BigInteger -> int",
615619
predicate=lambda obj: jinstance(obj, _jc.BigInteger),
616620
converter=lambda obj: int(str(obj)),
617621
),
618-
# java.math.BigDecimal -> float
619622
Converter(
623+
name="java.math.BigDecimal -> float",
620624
predicate=lambda obj: jinstance(obj, _jc.BigDecimal),
621625
converter=lambda obj: float(str(obj)),
622626
),
623-
# java.util.List -> scyjava.JavaList (list-like)
624627
Converter(
628+
name="java.util.List -> scyjava.JavaList (list-like)",
625629
predicate=lambda obj: jinstance(obj, _jc.List),
626630
converter=JavaList,
627631
),
628-
# java.util.Map -> scyjava.JavaMap (dict-like)
629632
Converter(
633+
name="java.util.Map -> scyjava.JavaMap (dict-like)",
630634
predicate=lambda obj: jinstance(obj, _jc.Map),
631635
converter=JavaMap,
632636
),
633-
# java.util.Set -> scyjava.JavaSet (set-like)
634637
Converter(
638+
name="java.util.Set -> scyjava.JavaSet (set-like)",
635639
predicate=lambda obj: jinstance(obj, _jc.Set),
636640
converter=JavaSet,
637641
),
638-
# java.util.Collection -> scyjava.JavaCollection (collections.abc.Collection)
639642
Converter(
643+
name="java.util.Collection -> "
644+
"scyjava.JavaCollection (collections.abc.Collection)",
640645
predicate=lambda obj: jinstance(obj, _jc.Collection),
641646
converter=JavaCollection,
642647
priority=Priority.NORMAL - 1,
643648
),
644-
# java.lang.Iterable -> scyjava.JavaIterable (collections.abc.Iterable)
645649
Converter(
650+
name="java.lang.Iterable -> "
651+
"scyjava.JavaIterable (collections.abc.Iterable)",
646652
predicate=lambda obj: jinstance(obj, _jc.Iterable),
647653
converter=JavaIterable,
648654
priority=Priority.NORMAL - 1,
649655
),
650-
# java.util.Iterator -> scyjava.JavaIterator (collections.abc.Iterator)
651656
Converter(
657+
name="java.util.Iterator -> "
658+
"scyjava.JavaIterator (collections.abc.Iterator)",
652659
predicate=lambda obj: jinstance(obj, _jc.Iterator),
653660
converter=JavaIterator,
654661
priority=Priority.NORMAL - 1,
655662
),
656-
# java.nio.file.Path -> pathlib.Path
657663
Converter(
664+
name="java.nio.file.Path -> pathlib.Path",
658665
predicate=lambda obj: jinstance(obj, _jc.Path),
659666
converter=lambda obj: Path(str(obj)),
660667
priority=Priority.NORMAL + 1,
661668
),
662-
# jarray -> list
663669
Converter(
670+
name="jarray -> list",
664671
predicate=lambda obj: is_jarray(obj),
665672
converter=lambda obj: [to_python(o) for o in obj],
666673
priority=Priority.VERY_LOW,
667674
),
668675
]
669676
if _import_pandas(required=False):
670-
# org.scijava.table.Table -> pandas.DataFrame
671677
converters.append(
672678
Converter(
673-
predicate=_is_table, converter=_convert_table, priority=Priority.HIGH
679+
name="org.scijava.table.Table -> pandas.DataFrame",
680+
predicate=_is_table,
681+
converter=_convert_table,
682+
priority=Priority.HIGH,
674683
)
675684
)
676685

677686
if mode == Mode.JPYPE:
678687
converters.extend(
679688
[
680-
# JBoolean -> bool
681689
Converter(
690+
name="JBoolean -> bool",
682691
predicate=lambda obj: isinstance(obj, JBoolean),
683692
converter=bool,
684693
priority=Priority.NORMAL + 1,
685694
),
686-
# JByte/JInt/JLong/JShort -> int
687695
Converter(
696+
name="JByte/JInt/JLong/JShort -> int",
688697
predicate=lambda obj: isinstance(obj, (JByte, JInt, JLong, JShort)),
689698
converter=int,
690699
priority=Priority.NORMAL + 1,
691700
),
692-
# JDouble/JFloat -> float
693701
Converter(
702+
name="JDouble/JFloat -> float",
694703
predicate=lambda obj: isinstance(obj, (JDouble, JFloat)),
695704
converter=float,
696705
priority=Priority.NORMAL + 1,
697706
),
698-
# JChar -> str
699707
Converter(
708+
name="JChar -> str",
700709
predicate=lambda obj: isinstance(obj, JChar),
701710
converter=str,
702711
priority=Priority.NORMAL + 1,
703712
),
704713
]
705714
)
706715
if _import_numpy(required=False):
707-
# primitive array -> numpy.ndarray
708716
converters.append(
709717
Converter(
718+
name="primitive array -> numpy.ndarray",
710719
predicate=_supports_jarray_to_ndarray,
711720
converter=_jarray_to_ndarray,
712721
)

tests/test_convert.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ def test_conversion_priority(self):
343343
invader = "Not Hello World"
344344

345345
bad_converter = Converter(
346+
name=f"test_conversion_priority: str -> '{invader}'",
346347
predicate=lambda obj: isinstance(obj, str),
347348
converter=lambda obj: String(invader.encode("utf-8"), "utf-8"),
348349
priority=100,

0 commit comments

Comments
 (0)