Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/scyjava/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@
"""

import logging
from collections.abc import Callable
from functools import lru_cache
from typing import Any, Callable, Dict
from typing import Any

from . import config, inspect
from ._arrays import is_arraylike, is_memoryarraylike, is_xarraylike
Expand All @@ -112,7 +113,7 @@
jreflect,
jsource,
)
from ._jvm import ( # noqa: F401
from ._jvm import (
available_processors,
gc,
is_awt_initialized,
Expand Down Expand Up @@ -161,7 +162,7 @@
_logger = logging.getLogger(__name__)

# Set of module properties
_CONSTANTS: Dict[str, Callable] = {}
_CONSTANTS: dict[str, Callable] = {}


def constant(func: Callable[[], Any], cache=True) -> Callable[[], Any]:
Expand Down
79 changes: 40 additions & 39 deletions src/scyjava/_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import logging
import math
from bisect import insort
from collections.abc import Callable
from importlib.util import find_spec
from pathlib import Path
from typing import Any, Callable, Dict, List, NamedTuple
from typing import Any, NamedTuple

from jpype import JBoolean, JByte, JChar, JDouble, JFloat, JInt, JLong, JShort

Expand Down Expand Up @@ -52,14 +53,14 @@ class Converter(NamedTuple):
priority: float = Priority.NORMAL
name: str = "<unnamed>"

def supports(self, obj: Any, **hints: Dict) -> bool:
def supports(self, obj: Any, **hints: dict) -> bool:
return (
self.predicate(obj, **hints)
if _has_kwargs(self.predicate)
else self.predicate(obj)
)

def convert(self, obj: Any, **hints: Dict) -> Any:
def convert(self, obj: Any, **hints: dict) -> Any:
return (
self.converter(obj, **hints)
if _has_kwargs(self.converter)
Expand All @@ -82,7 +83,7 @@ def __str__(self):
return self.name


def _convert(obj: Any, converters: List[Converter], **hints: Dict) -> Any:
def _convert(obj: Any, converters: list[Converter], **hints: dict) -> Any:
# NB: The given converters are assumed to be sorted ascending by priority,
# meaning lower-priority items appear earlier than higher-priority ones.
# But we want to try the higher priority converters first, so we
Expand Down Expand Up @@ -132,7 +133,7 @@ def _convertIterable(obj: collections.abc.Iterable):
return jlist


java_converters: List[Converter] = []
java_converters: list[Converter] = []


def add_java_converter(converter: Converter) -> None:
Expand All @@ -143,7 +144,7 @@ def add_java_converter(converter: Converter) -> None:
insort(java_converters, converter)


def to_java(obj: Any, **hints: Dict) -> Any:
def to_java(obj: Any, **hints: dict) -> Any:
"""
Recursively convert a Python object to a Java object.

Expand Down Expand Up @@ -197,7 +198,7 @@ def to_java(obj: Any, **hints: Dict) -> Any:
return _convert(obj, java_converters, **hints)


def _stock_java_converters() -> List[Converter]:
def _stock_java_converters() -> list[Converter]:
"""
Construct the Python-to-Java converters supported out of the box.
:return: A list of Converters
Expand Down Expand Up @@ -366,7 +367,7 @@ def _jstr(data):
if isinstance(data, JavaObject):
return str(data)
# NB: We want Python strings to render in single quotes.
return "{!r}".format(data)
return f"{data!r}"


class JavaObject:
Expand Down Expand Up @@ -526,7 +527,7 @@ def __str__(self):
return "{" + ", ".join(_jstr(v) for v in self) + "}"


py_converters: List[Converter] = []
py_converters: list[Converter] = []


def add_py_converter(converter: Converter) -> None:
Expand Down Expand Up @@ -566,13 +567,13 @@ def to_python(data: Any, gentle: bool = False) -> Any:
start_jvm()
try:
return _convert(data, py_converters)
except TypeError as exc:
except TypeError:
if gentle:
return data
raise exc
raise


def _stock_py_converters() -> List:
def _stock_py_converters() -> list:
"""
Construct the Java-to-Python converters supported out of the box.
:return: A list of Converters
Expand Down Expand Up @@ -842,7 +843,7 @@ def _is_table(obj: Any) -> bool:
"""Check if obj is a table."""
try:
return jinstance(obj, "org.scijava.table.Table")
except BaseException:
except BaseException: # noqa: BLE001
# No worries if scijava-table is not available.
return False

Expand All @@ -851,7 +852,7 @@ def _convert_table(obj: Any):
"""Convert obj to a table."""
try:
return _table_to_pandas(obj)
except BaseException:
except BaseException: # noqa: BLE001
# No worries if scijava-table is not available.
return None

Expand Down Expand Up @@ -894,8 +895,8 @@ def _pandas_to_table(df):
elif table_type.name.startswith("bool"):
TableClass = jimport("org.scijava.table.DefaultBoolTable")
else:
msg = "The type '{}' is not supported.".format(table_type.name)
raise Exception(msg)
msg = f"The type '{table_type.name}' is not supported."
raise ValueError(msg)

table = TableClass(*df.shape[::-1])

Expand All @@ -913,51 +914,51 @@ def _pandas_to_table(df):
# fmt: off
class _JavaClasses(JavaClasses):
@JavaClasses.java_import
def Boolean(self): return "java.lang.Boolean" # noqa: E272
def Boolean(self): return "java.lang.Boolean"
@JavaClasses.java_import
def Byte(self): return "java.lang.Byte" # noqa: E272
def Byte(self): return "java.lang.Byte"
@JavaClasses.java_import
def Character(self): return "java.lang.Character" # noqa: E272
def Character(self): return "java.lang.Character"
@JavaClasses.java_import
def Double(self): return "java.lang.Double" # noqa: E272
def Double(self): return "java.lang.Double"
@JavaClasses.java_import
def Float(self): return "java.lang.Float" # noqa: E272
def Float(self): return "java.lang.Float"
@JavaClasses.java_import
def Integer(self): return "java.lang.Integer" # noqa: E272
def Integer(self): return "java.lang.Integer"
@JavaClasses.java_import
def Iterable(self): return "java.lang.Iterable" # noqa: E272
def Iterable(self): return "java.lang.Iterable"
@JavaClasses.java_import
def Long(self): return "java.lang.Long" # noqa: E272
def Long(self): return "java.lang.Long"
@JavaClasses.java_import
def Object(self): return "java.lang.Object" # noqa: E272
def Object(self): return "java.lang.Object"
@JavaClasses.java_import
def Short(self): return "java.lang.Short" # noqa: E272
def Short(self): return "java.lang.Short"
@JavaClasses.java_import
def String(self): return "java.lang.String" # noqa: E272
def String(self): return "java.lang.String"
@JavaClasses.java_import
def BigDecimal(self): return "java.math.BigDecimal" # noqa: E272
def BigDecimal(self): return "java.math.BigDecimal"
@JavaClasses.java_import
def BigInteger(self): return "java.math.BigInteger" # noqa: E272
def BigInteger(self): return "java.math.BigInteger"
@JavaClasses.java_import
def Path(self): return "java.nio.file.Path" # noqa: E272
def Path(self): return "java.nio.file.Path"
@JavaClasses.java_import
def Paths(self): return "java.nio.file.Paths" # noqa: E272
def Paths(self): return "java.nio.file.Paths"
@JavaClasses.java_import
def ArrayList(self): return "java.util.ArrayList" # noqa: E272
def ArrayList(self): return "java.util.ArrayList"
@JavaClasses.java_import
def Collection(self): return "java.util.Collection" # noqa: E272
def Collection(self): return "java.util.Collection"
@JavaClasses.java_import
def Iterator(self): return "java.util.Iterator" # noqa: E272
def Iterator(self): return "java.util.Iterator"
@JavaClasses.java_import
def LinkedHashMap(self): return "java.util.LinkedHashMap" # noqa: E272
def LinkedHashMap(self): return "java.util.LinkedHashMap"
@JavaClasses.java_import
def LinkedHashSet(self): return "java.util.LinkedHashSet" # noqa: E272
def LinkedHashSet(self): return "java.util.LinkedHashSet"
@JavaClasses.java_import
def List(self): return "java.util.List" # noqa: E272
def List(self): return "java.util.List"
@JavaClasses.java_import
def Map(self): return "java.util.Map" # noqa: E272
def Map(self): return "java.util.Map"
@JavaClasses.java_import
def Set(self): return "java.util.Set" # noqa: E272
def Set(self): return "java.util.Set"
# fmt: on


Expand Down
8 changes: 4 additions & 4 deletions src/scyjava/_introspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
class methods, fields, and source code URL.
"""

from typing import Any, Dict, List
from typing import Any

from scyjava._jvm import jimport, jvm_version
from scyjava._types import isjava, jinstance, jclass
from scyjava._types import isjava, jclass, jinstance


def jreflect(data, aspect: str = "all") -> List[Dict[str, Any]]:
def jreflect(data, aspect: str = "all") -> list[dict[str, Any]]:
"""
Use Java reflection to introspect the given Java object,
returning a table of its available methods or fields.
Expand Down Expand Up @@ -91,7 +91,7 @@ def jsource(data) -> str:
try:
data = jimport(data) # check if data can be imported
except Exception as err:
raise ValueError(f"Not a Java object {err}")
raise ValueError(f"Not a Java object {err}") from err
jcls = data if jinstance(data, "java.lang.Class") else jclass(data)

if jcls.getClassLoader() is None:
Expand Down
4 changes: 2 additions & 2 deletions src/scyjava/_jdk_fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import logging
import os
from typing import TYPE_CHECKING, Union
from typing import TYPE_CHECKING

from jgo.exec import JavaLocator, JavaSource

Expand Down Expand Up @@ -64,7 +64,7 @@ def resolve_java(vendor: str | None = None, version: str | None = None) -> None:
os.environ["JAVA_HOME"] = str(java_home)


def _add_to_path(path: Union[Path, str], front: bool = False) -> None:
def _add_to_path(path: Path | str, front: bool = False) -> None:
"""Add a path to the PATH environment variable.

If front is True, the path is added to the front of the PATH.
Expand Down
28 changes: 15 additions & 13 deletions src/scyjava/_jvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
import re
import subprocess
import sys
from functools import lru_cache
from collections.abc import Sequence
from functools import cache
from importlib import import_module
from pathlib import Path
from typing import Sequence

import jgo
import jpype
import jpype.config
import jgo

import scyjava.config
from scyjava.config import Mode, mode
from scyjava._jdk_fetch import resolve_java
from scyjava.config import Mode, mode

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -130,11 +130,15 @@ def jvm_version() -> tuple[int, ...]:
except subprocess.CalledProcessError as e:
raise RuntimeError("System call to java failed") from e

output = output.replace("\n", " ").replace("\r", "")
m = re.match('.* version "([^"]*)"', output)
return _jvm_version_str_to_tuple(output, java)


def _jvm_version_str_to_tuple(java_version_output: str, java: str) -> tuple[int, ...]:
java_version_output = java_version_output.replace("\n", " ").replace("\r", "")
m = re.match(r'.*version "(\d+(?:\.\d+)*)', java_version_output)
if not m:
raise RuntimeError(
f"Inscrutable java command output:\n$ {java} -version\n{output}"
f"Inscrutable java command output:\n$ {java} -version\n{java_version_output}"
)

v = m.group(1)
Expand Down Expand Up @@ -172,7 +176,7 @@ def start_jvm(options: Sequence[str] | None = None) -> None:
repositories = scyjava.config.get_repositories()

# use the logger to notify user that endpoints are being added
_logger.debug("Adding jars from endpoints {0}".format(endpoints))
_logger.debug(f"Adding jars from endpoints {endpoints}")

# download Java as appropriate
resolve_java()
Expand Down Expand Up @@ -293,7 +297,7 @@ def shutdown_jvm() -> None:
for callback in _shutdown_callbacks:
try:
callback()
except Exception as e:
except Exception as e: # noqa: BLE001
_logger.error(f"Exception during shutdown callback: {e}")

# dispose AWT resources if applicable
Expand All @@ -305,7 +309,7 @@ def shutdown_jvm() -> None:
# okay to shutdown JVM
try:
jpype.shutdownJVM()
except Exception as e:
except Exception as e: # noqa: BLE001
_logger.error(f"Exception during JVM shutdown: {e}")


Expand Down Expand Up @@ -440,7 +444,6 @@ def when_jvm_starts(f) -> None:
f()
else:
# Add function to the list of callbacks to invoke upon start_jvm().
global _startup_callbacks
_startup_callbacks.append(f)


Expand All @@ -454,11 +457,10 @@ def when_jvm_stops(f) -> None:

:param f: Function to invoke when scyjava.shutdown_jvm() is called.
"""
global _shutdown_callbacks
_shutdown_callbacks.append(f)


@lru_cache(maxsize=None)
@cache
def jimport(class_name: str):
"""
Import a class from Java to Python.
Expand Down
Loading
Loading