scyjava 1.12.0__tar.gz → 1.12.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {scyjava-1.12.0 → scyjava-1.12.2}/Makefile +2 -12
  2. {scyjava-1.12.0/src/scyjava.egg-info → scyjava-1.12.2}/PKG-INFO +20 -13
  3. {scyjava-1.12.0 → scyjava-1.12.2}/README.md +19 -1
  4. scyjava-1.12.2/bin/check.sh +6 -0
  5. {scyjava-1.12.0 → scyjava-1.12.2}/bin/clean.sh +1 -1
  6. scyjava-1.12.0/bin/setup.sh → scyjava-1.12.2/bin/dist.sh +1 -1
  7. scyjava-1.12.2/bin/lint.sh +22 -0
  8. scyjava-1.12.2/bin/test.sh +49 -0
  9. {scyjava-1.12.0 → scyjava-1.12.2}/pyproject.toml +3 -7
  10. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_cjdk_fetch.py +1 -1
  11. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_convert.py +59 -42
  12. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_introspect.py +1 -1
  13. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_jvm.py +19 -4
  14. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/config.py +6 -6
  15. {scyjava-1.12.0 → scyjava-1.12.2/src/scyjava.egg-info}/PKG-INFO +20 -13
  16. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava.egg-info/SOURCES.txt +1 -4
  17. scyjava-1.12.2/src/scyjava.egg-info/requires.txt +3 -0
  18. {scyjava-1.12.0 → scyjava-1.12.2}/tests/it/jvm_version.py +3 -2
  19. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_introspect.py +3 -1
  20. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_pandas.py +6 -6
  21. scyjava-1.12.0/bin/check.sh +0 -10
  22. scyjava-1.12.0/bin/fmt.sh +0 -11
  23. scyjava-1.12.0/bin/lint.sh +0 -13
  24. scyjava-1.12.0/bin/test.sh +0 -107
  25. scyjava-1.12.0/dev-environment.yml +0 -41
  26. scyjava-1.12.0/environment.yml +0 -30
  27. scyjava-1.12.0/src/scyjava.egg-info/requires.txt +0 -15
  28. {scyjava-1.12.0 → scyjava-1.12.2}/MANIFEST.in +0 -0
  29. {scyjava-1.12.0 → scyjava-1.12.2}/UNLICENSE +0 -0
  30. {scyjava-1.12.0 → scyjava-1.12.2}/setup.cfg +0 -0
  31. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/__init__.py +0 -0
  32. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_arrays.py +0 -0
  33. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_script.py +0 -0
  34. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_types.py +0 -0
  35. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/_versions.py +0 -0
  36. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava/inspect.py +0 -0
  37. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava.egg-info/dependency_links.txt +0 -0
  38. {scyjava-1.12.0 → scyjava-1.12.2}/src/scyjava.egg-info/top_level.txt +0 -0
  39. {scyjava-1.12.0 → scyjava-1.12.2}/tests/it/awt.py +0 -0
  40. {scyjava-1.12.0 → scyjava-1.12.2}/tests/it/headless.py +0 -0
  41. {scyjava-1.12.0 → scyjava-1.12.2}/tests/it/java_heap.py +0 -0
  42. {scyjava-1.12.0 → scyjava-1.12.2}/tests/it/script_scope.py +0 -0
  43. {scyjava-1.12.0 → scyjava-1.12.2}/tests/it/scripting.py +0 -0
  44. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_arrays.py +0 -0
  45. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_basics.py +0 -0
  46. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_convert.py +0 -0
  47. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_inspect.py +0 -0
  48. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_types.py +0 -0
  49. {scyjava-1.12.0 → scyjava-1.12.2}/tests/test_versions.py +0 -0
@@ -1,32 +1,22 @@
1
1
  help:
2
2
  @echo "Available targets:\n\
3
3
  clean - remove build files and directories\n\
4
- setup - create mamba developer environment\n\
5
4
  lint - run code formatters and linters\n\
6
5
  test - run automated test suite\n\
7
6
  dist - generate release archives\n\
8
- \n\
9
- Remember to 'mamba activate scyjava-dev' first!"
7
+ "
10
8
 
11
9
  clean:
12
10
  bin/clean.sh
13
11
 
14
- setup:
15
- bin/setup.sh
16
-
17
12
  check:
18
13
  @bin/check.sh
19
14
 
20
15
  lint: check
21
16
  bin/lint.sh
22
17
 
23
- fmt: check
24
- bin/fmt.sh
25
-
26
18
  test: check
27
19
  bin/test.sh
28
20
 
29
21
  dist: check clean
30
- python -m build
31
-
32
- .PHONY: test
22
+ bin/dist.sh
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scyjava
3
- Version: 1.12.0
3
+ Version: 1.12.2
4
4
  Summary: Supercharged Java access from Python
5
5
  Author-email: SciJava developers <ctrueden@wisc.edu>
6
6
  License-Expression: Unlicense
@@ -32,17 +32,6 @@ Description-Content-Type: text/markdown
32
32
  Requires-Dist: jpype1>=1.3.0
33
33
  Requires-Dist: jgo
34
34
  Requires-Dist: cjdk
35
- Provides-Extra: dev
36
- Requires-Dist: assertpy; extra == "dev"
37
- Requires-Dist: build; extra == "dev"
38
- Requires-Dist: jep; extra == "dev"
39
- Requires-Dist: pytest; extra == "dev"
40
- Requires-Dist: pytest-cov; extra == "dev"
41
- Requires-Dist: numpy; extra == "dev"
42
- Requires-Dist: pandas; extra == "dev"
43
- Requires-Dist: ruff; extra == "dev"
44
- Requires-Dist: toml; extra == "dev"
45
- Requires-Dist: validate-pyproject[all]; extra == "dev"
46
35
 
47
36
  [![build status](https://github.com/scijava/scyjava/actions/workflows/build.yml/badge.svg)](https://github.com/scijava/scyjava/actions/workflows/build.yml)
48
37
  [![codecov](https://codecov.io/gh/scijava/scyjava/branch/main/graph/badge.svg?token=NLK3ADZUCU)](https://codecov.io/gh/scijava/scyjava)
@@ -131,6 +120,24 @@ u'1.8.0_152-release'
131
120
 
132
121
  See the [jgo documentation](https://github.com/scijava/jgo) for more about Maven endpoints.
133
122
 
123
+ ## Bootstrap a Java installation
124
+
125
+ ```python
126
+ >>> from scyjava import config, jimport
127
+ >>> config.set_java_constraints(fetch=True, vendor='zulu', version='17')
128
+ >>> System = jimport('java.lang.System')
129
+ cjdk: Installing JDK zulu:17.0.15 to /home/chuckles/.cache/cjdk
130
+ Download 100% of 189.4 MiB |##########| Elapsed Time: 0:00:02 Time: 0:00:02
131
+ Extract | | # | 714 Elapsed Time: 0:00:01
132
+ cjdk: Installing Maven to /home/chuckles/.cache/cjdk
133
+ Download 100% of 8.7 MiB |##########| Elapsed Time: 0:00:00 Time: 0:00:00
134
+ Extract | |# | 102 Elapsed Time: 0:00:00
135
+ >>> System.getProperty('java.vendor')
136
+ 'Azul Systems, Inc.'
137
+ >>> System.getProperty('java.version')
138
+ '17.0.15'
139
+ ```
140
+
134
141
  ## Convert between Python and Java data structures
135
142
 
136
143
  ### Convert Java collections to Python
@@ -398,7 +405,7 @@ FUNCTIONS
398
405
  jvm_started() -> bool
399
406
  Return true iff a Java virtual machine (JVM) has been started.
400
407
 
401
- jvm_version() -> str
408
+ jvm_version() -> tuple[int, ...]
402
409
  Gets the version of the JVM as a tuple, with each dot-separated digit
403
410
  as one element. Characters in the version string beyond only numbers
404
411
  and dots are ignored, in line with the java.version system property.
@@ -85,6 +85,24 @@ u'1.8.0_152-release'
85
85
 
86
86
  See the [jgo documentation](https://github.com/scijava/jgo) for more about Maven endpoints.
87
87
 
88
+ ## Bootstrap a Java installation
89
+
90
+ ```python
91
+ >>> from scyjava import config, jimport
92
+ >>> config.set_java_constraints(fetch=True, vendor='zulu', version='17')
93
+ >>> System = jimport('java.lang.System')
94
+ cjdk: Installing JDK zulu:17.0.15 to /home/chuckles/.cache/cjdk
95
+ Download 100% of 189.4 MiB |##########| Elapsed Time: 0:00:02 Time: 0:00:02
96
+ Extract | | # | 714 Elapsed Time: 0:00:01
97
+ cjdk: Installing Maven to /home/chuckles/.cache/cjdk
98
+ Download 100% of 8.7 MiB |##########| Elapsed Time: 0:00:00 Time: 0:00:00
99
+ Extract | |# | 102 Elapsed Time: 0:00:00
100
+ >>> System.getProperty('java.vendor')
101
+ 'Azul Systems, Inc.'
102
+ >>> System.getProperty('java.version')
103
+ '17.0.15'
104
+ ```
105
+
88
106
  ## Convert between Python and Java data structures
89
107
 
90
108
  ### Convert Java collections to Python
@@ -352,7 +370,7 @@ FUNCTIONS
352
370
  jvm_started() -> bool
353
371
  Return true iff a Java virtual machine (JVM) has been started.
354
372
 
355
- jvm_version() -> str
373
+ jvm_version() -> tuple[int, ...]
356
374
  Gets the version of the JVM as a tuple, with each dot-separated digit
357
375
  as one element. Characters in the version string beyond only numbers
358
376
  and dots are ignored, in line with the java.version system property.
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+
3
+ if ! command -v uv >/dev/null 2>&1; then
4
+ echo "Please install uv (https://docs.astral.sh/uv/getting-started/installation/)."
5
+ exit 1
6
+ fi
@@ -6,4 +6,4 @@ cd "$dir/.."
6
6
  find . -name __pycache__ -type d | while read d
7
7
  do rm -rfv "$d"
8
8
  done
9
- rm -rfv .pytest_cache build dist src/*.egg-info
9
+ rm -rfv .pytest_cache build dist src/*.egg-info tests/.pytest_cache
@@ -3,4 +3,4 @@
3
3
  dir=$(dirname "$0")
4
4
  cd "$dir/.."
5
5
 
6
- mamba env create -f dev-environment.yml
6
+ uv run python -m build
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+
3
+ dir=$(dirname "$0")
4
+ cd "$dir/.."
5
+
6
+ exitCode=0
7
+
8
+ # Check for errors and capture non-zero exit codes.
9
+ uv run validate-pyproject pyproject.toml
10
+ code=$?; test $code -eq 0 || exitCode=$code
11
+ uv run ruff check >/dev/null 2>&1
12
+ code=$?; test $code -eq 0 || exitCode=$code
13
+ uv run ruff format --check >/dev/null 2>&1
14
+ code=$?; test $code -eq 0 || exitCode=$code
15
+
16
+ # Do actual code reformatting.
17
+ uv run ruff check --fix
18
+ code=$?; test $code -eq 0 || exitCode=$code
19
+ uv run ruff format
20
+ code=$?; test $code -eq 0 || exitCode=$code
21
+
22
+ exit $exitCode
@@ -0,0 +1,49 @@
1
+ #!/bin/sh
2
+
3
+ # Runs the unit tests.
4
+ #
5
+ # Usage examples:
6
+ # bin/test.sh
7
+ # bin/test.sh tests/test_basics.py
8
+ # bin/test.sh tests/test_convert.py::TestConvert::test2DStringArray
9
+
10
+ set -e
11
+
12
+ dir=$(dirname "$0")
13
+ cd "$dir/.."
14
+
15
+ echo
16
+ echo "----------------------"
17
+ echo "| Running unit tests |"
18
+ echo "----------------------"
19
+
20
+ if [ $# -gt 0 ]
21
+ then
22
+ uv run python -m pytest -v -p no:faulthandler $@
23
+ else
24
+ uv run python -m pytest -v -p no:faulthandler tests/
25
+ fi
26
+ jpypeCode=$?
27
+
28
+ echo
29
+ echo "-----------------------------"
30
+ echo "| Running integration tests |"
31
+ echo "-----------------------------"
32
+ itCode=0
33
+ for t in tests/it/*.py
34
+ do
35
+ uv run python "$t"
36
+ code=$?
37
+ printf -- "--> %s " "$t"
38
+ if [ "$code" -eq 0 ]
39
+ then
40
+ echo "[OK]"
41
+ else
42
+ echo "[FAILED]"
43
+ itCode=$code
44
+ fi
45
+ done
46
+
47
+ test "$jpypeCode" -ne 0 && exit "$jpypeCode"
48
+ test "$itCode" -ne 0 && exit "$itCode"
49
+ exit 0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "scyjava"
7
- version = "1.12.0"
7
+ version = "1.12.2"
8
8
  description = "Supercharged Java access from Python"
9
9
  license = "Unlicense"
10
10
  authors = [{name = "SciJava developers", email = "ctrueden@wisc.edu"}]
@@ -30,7 +30,6 @@ classifiers = [
30
30
  "Topic :: Utilities",
31
31
  ]
32
32
 
33
- # NB: Keep this in sync with environment.yml AND dev-environment.yml!
34
33
  requires-python = ">=3.9"
35
34
  dependencies = [
36
35
  "jpype1 >= 1.3.0",
@@ -38,19 +37,17 @@ dependencies = [
38
37
  "cjdk",
39
38
  ]
40
39
 
41
- [project.optional-dependencies]
42
- # NB: Keep this in sync with dev-environment.yml!
40
+ [dependency-groups]
43
41
  dev = [
44
42
  "assertpy",
45
43
  "build",
46
- "jep",
47
44
  "pytest",
48
45
  "pytest-cov",
49
46
  "numpy",
50
47
  "pandas",
51
48
  "ruff",
52
49
  "toml",
53
- "validate-pyproject[all]"
50
+ "validate-pyproject[all]",
54
51
  ]
55
52
 
56
53
  [project.urls]
@@ -68,7 +65,6 @@ include-package-data = false
68
65
  where = ["src"]
69
66
  namespaces = false
70
67
 
71
- # ruff configuration
72
68
  [tool.ruff]
73
69
  line-length = 88
74
70
  src = ["src", "tests"]
@@ -47,7 +47,7 @@ def is_jvm_available() -> bool:
47
47
  try:
48
48
  with patch.object(subprocess, "check_output", new=_silent_check_output):
49
49
  jpype.getDefaultJVMPath()
50
- # on Darwin, may raise a CalledProcessError when invoking `/user/libexec/java_home`
50
+ # on Darwin, may raise a CalledProcessError when invoking `/usr/libexec/java_home`
51
51
  except (jpype.JVMNotFoundException, subprocess.CalledProcessError):
52
52
  return False
53
53
  return True
@@ -7,6 +7,7 @@ import inspect
7
7
  import logging
8
8
  import math
9
9
  from bisect import insort
10
+ from importlib.util import find_spec
10
11
  from pathlib import Path
11
12
  from typing import Any, Callable, Dict, List, NamedTuple
12
13
 
@@ -236,72 +237,90 @@ def _stock_java_converters() -> List[Converter]:
236
237
  ),
237
238
  Converter(
238
239
  name="int -> java.lang.Byte",
239
- predicate=lambda obj, **hints: isinstance(obj, int)
240
- and ("type" in hints and hints["type"] in ("b", "byte", "Byte"))
241
- and _jc.Byte.MIN_VALUE <= obj <= _jc.Byte.MAX_VALUE,
240
+ predicate=lambda obj, **hints: (
241
+ isinstance(obj, int)
242
+ and ("type" in hints and hints["type"] in ("b", "byte", "Byte"))
243
+ and _jc.Byte.MIN_VALUE <= obj <= _jc.Byte.MAX_VALUE
244
+ ),
242
245
  converter=_jc.Byte,
243
246
  priority=Priority.HIGH,
244
247
  ),
245
248
  Converter(
246
249
  name="int -> java.lang.Short",
247
- predicate=lambda obj, **hints: isinstance(obj, int)
248
- and ("type" in hints and hints["type"] in ("s", "short", "Short"))
249
- and _jc.Short.MIN_VALUE <= obj <= _jc.Short.MAX_VALUE,
250
+ predicate=lambda obj, **hints: (
251
+ isinstance(obj, int)
252
+ and ("type" in hints and hints["type"] in ("s", "short", "Short"))
253
+ and _jc.Short.MIN_VALUE <= obj <= _jc.Short.MAX_VALUE
254
+ ),
250
255
  converter=_jc.Short,
251
256
  priority=Priority.HIGH,
252
257
  ),
253
258
  Converter(
254
259
  name="int -> java.lang.Integer",
255
- predicate=lambda obj, **hints: isinstance(obj, int)
256
- and ("type" not in hints or hints["type"] in ("i", "int", "Integer"))
257
- and _jc.Integer.MIN_VALUE <= obj <= _jc.Integer.MAX_VALUE,
260
+ predicate=lambda obj, **hints: (
261
+ isinstance(obj, int)
262
+ and ("type" not in hints or hints["type"] in ("i", "int", "Integer"))
263
+ and _jc.Integer.MIN_VALUE <= obj <= _jc.Integer.MAX_VALUE
264
+ ),
258
265
  converter=_jc.Integer,
259
266
  ),
260
267
  Converter(
261
268
  name="int -> java.lang.Long",
262
- predicate=lambda obj, **hints: isinstance(obj, int)
263
- and ("type" not in hints or hints["type"] in ("j", "l", "long", "Long"))
264
- and _jc.Long.MIN_VALUE <= obj <= _jc.Long.MAX_VALUE,
269
+ predicate=lambda obj, **hints: (
270
+ isinstance(obj, int)
271
+ and ("type" not in hints or hints["type"] in ("j", "l", "long", "Long"))
272
+ and _jc.Long.MIN_VALUE <= obj <= _jc.Long.MAX_VALUE
273
+ ),
265
274
  converter=_jc.Long,
266
275
  priority=Priority.NORMAL - 1,
267
276
  ),
268
277
  Converter(
269
278
  name="int -> java.math.BigInteger",
270
- predicate=lambda obj, **hints: isinstance(obj, int)
271
- and (
272
- "type" not in hints or hints["type"] in ("bi", "bigint", "BigInteger")
279
+ predicate=lambda obj, **hints: (
280
+ isinstance(obj, int)
281
+ and (
282
+ "type" not in hints
283
+ or hints["type"] in ("bi", "bigint", "BigInteger")
284
+ )
273
285
  ),
274
286
  converter=lambda obj: _jc.BigInteger(str(obj)),
275
287
  priority=Priority.NORMAL - 2,
276
288
  ),
277
289
  Converter(
278
290
  name="float -> java.lang.Float",
279
- predicate=lambda obj, **hints: isinstance(obj, float)
280
- and ("type" not in hints or hints["type"] in ("f", "float", "Float"))
281
- and (
282
- math.isinf(obj)
283
- or math.isnan(obj)
284
- or -_jc.Float.MAX_VALUE <= obj <= _jc.Float.MAX_VALUE
291
+ predicate=lambda obj, **hints: (
292
+ isinstance(obj, float)
293
+ and ("type" not in hints or hints["type"] in ("f", "float", "Float"))
294
+ and (
295
+ math.isinf(obj)
296
+ or math.isnan(obj)
297
+ or -_jc.Float.MAX_VALUE <= obj <= _jc.Float.MAX_VALUE
298
+ )
285
299
  ),
286
300
  converter=_jc.Float,
287
301
  ),
288
302
  Converter(
289
303
  name="float -> java.lang.Double",
290
- predicate=lambda obj, **hints: isinstance(obj, float)
291
- and ("type" not in hints or hints["type"] in ("d", "double", "Double"))
292
- and (
293
- math.isinf(obj)
294
- or math.isnan(obj)
295
- or -_jc.Double.MAX_VALUE <= obj <= _jc.Double.MAX_VALUE
304
+ predicate=lambda obj, **hints: (
305
+ isinstance(obj, float)
306
+ and ("type" not in hints or hints["type"] in ("d", "double", "Double"))
307
+ and (
308
+ math.isinf(obj)
309
+ or math.isnan(obj)
310
+ or -_jc.Double.MAX_VALUE <= obj <= _jc.Double.MAX_VALUE
311
+ )
296
312
  ),
297
313
  converter=_jc.Double,
298
314
  priority=Priority.NORMAL - 1,
299
315
  ),
300
316
  Converter(
301
317
  name="float -> java.math.BigDecimal",
302
- predicate=lambda obj, **hints: isinstance(obj, float)
303
- and (
304
- "type" not in hints or hints["type"] in ("bd", "bigdec", "BigDecimal")
318
+ predicate=lambda obj, **hints: (
319
+ isinstance(obj, float)
320
+ and (
321
+ "type" not in hints
322
+ or hints["type"] in ("bd", "bigdec", "BigDecimal")
323
+ )
305
324
  ),
306
325
  converter=lambda obj: _jc.BigDecimal(str(obj)),
307
326
  priority=Priority.NORMAL - 2,
@@ -677,7 +696,7 @@ def _stock_py_converters() -> List:
677
696
  priority=Priority.VERY_LOW,
678
697
  ),
679
698
  ]
680
- if _import_pandas(required=False):
699
+ if find_spec("pandas"):
681
700
  converters.append(
682
701
  Converter(
683
702
  name="org.scijava.table.Table -> pandas.DataFrame",
@@ -716,7 +735,7 @@ def _stock_py_converters() -> List:
716
735
  ),
717
736
  ]
718
737
  )
719
- if _import_numpy(required=False):
738
+ if find_spec("numpy"):
720
739
  converters.append(
721
740
  Converter(
722
741
  name="primitive array -> numpy.ndarray",
@@ -803,16 +822,15 @@ def _jarray_shape(jarr):
803
822
  return shape
804
823
 
805
824
 
806
- def _import_numpy(required=True):
825
+ def _import_numpy():
807
826
  try:
808
827
  import numpy as np
809
828
 
810
829
  return np
811
830
  except ImportError as e:
812
- if required:
813
- msg = "The NumPy library is missing (https://numpy.org/). "
814
- msg += "Please install it before using this function."
815
- raise RuntimeError(msg) from e
831
+ msg = "The NumPy library is missing (https://numpy.org/). "
832
+ msg += "Please install it before using this function."
833
+ raise RuntimeError(msg) from e
816
834
 
817
835
 
818
836
  ######################################
@@ -838,16 +856,15 @@ def _convert_table(obj: Any):
838
856
  return None
839
857
 
840
858
 
841
- def _import_pandas(required=True):
859
+ def _import_pandas():
842
860
  try:
843
861
  import pandas as pd
844
862
 
845
863
  return pd
846
864
  except ImportError as e:
847
- if required:
848
- msg = "The Pandas library is missing (http://pandas.pydata.org/). "
849
- msg += "Please install it before using this function."
850
- raise RuntimeError(msg) from e
865
+ msg = "The Pandas library is missing (http://pandas.pydata.org/). "
866
+ msg += "Please install it before using this function."
867
+ raise RuntimeError(msg) from e
851
868
 
852
869
 
853
870
  def _table_to_pandas(table):
@@ -100,7 +100,7 @@ def jsource(data) -> str:
100
100
 
101
101
  # Discern the Java version.
102
102
  jv_digits = jvm_version()
103
- assert jv_digits is not None and len(jv_digits) > 1
103
+ assert jv_digits is not None and len(jv_digits) > 0
104
104
  java_version = jv_digits[1] if jv_digits[0] == 1 else jv_digits[0]
105
105
 
106
106
  # Note: some classes (e.g. corba and jaxp) will not be located correctly before
@@ -70,8 +70,14 @@ def jvm_version() -> tuple[int, ...]:
70
70
  default_jvm_path = jpype.getDefaultJVMPath()
71
71
  if not default_jvm_path:
72
72
  raise RuntimeError("Cannot glean the default JVM path")
73
+ _logger.debug(f"Default JVM path from JPype: {default_jvm_path}")
73
74
 
74
- p = Path(default_jvm_path)
75
+ # Good ol' macOS! Nothing beats macOS.
76
+ jvm_path = default_jvm_path.replace(
77
+ "/Contents/MacOS/libjli.dylib", "/Contents/Home/lib/libjli.dylib"
78
+ )
79
+
80
+ p = Path(jvm_path)
75
81
  if not p.exists():
76
82
  raise RuntimeError(f"Invalid default JVM path: {p}")
77
83
 
@@ -93,6 +99,7 @@ def jvm_version() -> tuple[int, ...]:
93
99
  if java is None:
94
100
  raise RuntimeError(f"No java executable found inside: {p}")
95
101
 
102
+ _logger.debug(f"Invoking `{java} -version`...")
96
103
  try:
97
104
  output = subprocess.check_output(
98
105
  [str(java), "-version"], stderr=subprocess.STDOUT
@@ -101,11 +108,19 @@ def jvm_version() -> tuple[int, ...]:
101
108
  raise RuntimeError("System call to java failed") from e
102
109
 
103
110
  output = output.replace("\n", " ").replace("\r", "")
104
- m = re.match('.*version "(([0-9]+\\.)+[0-9]+)', output)
111
+ m = re.match('.* version "([^"]*)"', output)
105
112
  if not m:
106
- raise RuntimeError(f"Inscrutable java command output:\n{output}")
113
+ raise RuntimeError(
114
+ f"Inscrutable java command output:\n$ {java} -version\n{output}"
115
+ )
107
116
 
108
- return tuple(map(int, m.group(1).split(".")))
117
+ v = m.group(1)
118
+ _logger.debug(f"Got Java version: {v}")
119
+
120
+ try:
121
+ return tuple(map(int, v.split(".")))
122
+ except ValueError:
123
+ raise RuntimeError(f"Inscrutable java version: {v}")
109
124
 
110
125
 
111
126
  def start_jvm(options: Sequence[str] = None) -> None:
@@ -13,10 +13,10 @@ from jgo import maven_scijava_repository as _scijava_public
13
13
  _logger = _logging.getLogger(__name__)
14
14
 
15
15
  # Constraints on the Java installation to be used.
16
- _fetch_java: str = "auto"
16
+ _fetch_java: str = "always"
17
17
  _java_vendor: str = "zulu-jre"
18
18
  _java_version: str = "11"
19
- _maven_url: str = "tgz+https://dlcdn.apache.org/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz" # noqa: E501
19
+ _maven_url: str = "tgz+https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz" # noqa: E501
20
20
  _maven_sha: str = "a555254d6b53d267965a3404ecb14e53c3827c09c3b94b5678835887ab404556bfaf78dcfe03ba76fa2508649dca8531c74bca4d5846513522404d48e8c4ac8b" # noqa: E501
21
21
 
22
22
  endpoints: list[str] = []
@@ -55,10 +55,10 @@ def set_java_constraints(
55
55
  Set constraints on the version of Java to be used.
56
56
 
57
57
  :param fetch:
58
- If "auto" (default), when a JVM/or maven cannot be located on the system,
59
- [`cjdk`](https://github.com/cachedjdk/cjdk) will be used to download
60
- a JDK/JRE distribution and set up the JVM.
61
- If "always", cjdk will always be used; if "never", cjdk will never be used.
58
+ If "always" (default), cjdk will always be used; if "never", cjdk will
59
+ never be used. If "auto", when a JVM/or maven cannot be located on the system,
60
+ [`cjdk`](https://github.com/cachedjdk/cjdk) will be used to download a
61
+ JDK/JRE distribution and set up the JVM.
62
62
  :param vendor:
63
63
  The vendor of the JDK/JRE distribution for cjdk to download and cache.
64
64
  Defaults to "zulu-jre". See the cjdk documentation for details.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scyjava
3
- Version: 1.12.0
3
+ Version: 1.12.2
4
4
  Summary: Supercharged Java access from Python
5
5
  Author-email: SciJava developers <ctrueden@wisc.edu>
6
6
  License-Expression: Unlicense
@@ -32,17 +32,6 @@ Description-Content-Type: text/markdown
32
32
  Requires-Dist: jpype1>=1.3.0
33
33
  Requires-Dist: jgo
34
34
  Requires-Dist: cjdk
35
- Provides-Extra: dev
36
- Requires-Dist: assertpy; extra == "dev"
37
- Requires-Dist: build; extra == "dev"
38
- Requires-Dist: jep; extra == "dev"
39
- Requires-Dist: pytest; extra == "dev"
40
- Requires-Dist: pytest-cov; extra == "dev"
41
- Requires-Dist: numpy; extra == "dev"
42
- Requires-Dist: pandas; extra == "dev"
43
- Requires-Dist: ruff; extra == "dev"
44
- Requires-Dist: toml; extra == "dev"
45
- Requires-Dist: validate-pyproject[all]; extra == "dev"
46
35
 
47
36
  [![build status](https://github.com/scijava/scyjava/actions/workflows/build.yml/badge.svg)](https://github.com/scijava/scyjava/actions/workflows/build.yml)
48
37
  [![codecov](https://codecov.io/gh/scijava/scyjava/branch/main/graph/badge.svg?token=NLK3ADZUCU)](https://codecov.io/gh/scijava/scyjava)
@@ -131,6 +120,24 @@ u'1.8.0_152-release'
131
120
 
132
121
  See the [jgo documentation](https://github.com/scijava/jgo) for more about Maven endpoints.
133
122
 
123
+ ## Bootstrap a Java installation
124
+
125
+ ```python
126
+ >>> from scyjava import config, jimport
127
+ >>> config.set_java_constraints(fetch=True, vendor='zulu', version='17')
128
+ >>> System = jimport('java.lang.System')
129
+ cjdk: Installing JDK zulu:17.0.15 to /home/chuckles/.cache/cjdk
130
+ Download 100% of 189.4 MiB |##########| Elapsed Time: 0:00:02 Time: 0:00:02
131
+ Extract | | # | 714 Elapsed Time: 0:00:01
132
+ cjdk: Installing Maven to /home/chuckles/.cache/cjdk
133
+ Download 100% of 8.7 MiB |##########| Elapsed Time: 0:00:00 Time: 0:00:00
134
+ Extract | |# | 102 Elapsed Time: 0:00:00
135
+ >>> System.getProperty('java.vendor')
136
+ 'Azul Systems, Inc.'
137
+ >>> System.getProperty('java.version')
138
+ '17.0.15'
139
+ ```
140
+
134
141
  ## Convert between Python and Java data structures
135
142
 
136
143
  ### Convert Java collections to Python
@@ -398,7 +405,7 @@ FUNCTIONS
398
405
  jvm_started() -> bool
399
406
  Return true iff a Java virtual machine (JVM) has been started.
400
407
 
401
- jvm_version() -> str
408
+ jvm_version() -> tuple[int, ...]
402
409
  Gets the version of the JVM as a tuple, with each dot-separated digit
403
410
  as one element. Characters in the version string beyond only numbers
404
411
  and dots are ignored, in line with the java.version system property.
@@ -2,14 +2,11 @@ MANIFEST.in
2
2
  Makefile
3
3
  README.md
4
4
  UNLICENSE
5
- dev-environment.yml
6
- environment.yml
7
5
  pyproject.toml
8
6
  bin/check.sh
9
7
  bin/clean.sh
10
- bin/fmt.sh
8
+ bin/dist.sh
11
9
  bin/lint.sh
12
- bin/setup.sh
13
10
  bin/test.sh
14
11
  src/scyjava/__init__.py
15
12
  src/scyjava/_arrays.py
@@ -0,0 +1,3 @@
1
+ jpype1>=1.3.0
2
+ jgo
3
+ cjdk
@@ -10,15 +10,16 @@ assert_that(scyjava.jvm_started()).is_false()
10
10
 
11
11
  before_version = scyjava.jvm_version()
12
12
  assert_that(before_version).is_not_none()
13
- assert_that(len(before_version)).is_greater_than_or_equal_to(3)
13
+ assert_that(len(before_version)).is_greater_than_or_equal_to(1)
14
14
  assert_that(before_version[0]).is_greater_than(0)
15
15
 
16
+ scyjava.config.set_java_constraints(fetch="never")
16
17
  scyjava.config.enable_headless_mode()
17
18
  scyjava.start_jvm()
18
19
 
19
20
  after_version = scyjava.jvm_version()
20
21
  assert_that(after_version).is_not_none()
21
- assert_that(len(after_version)).is_greater_than_or_equal_to(3)
22
+ assert_that(len(after_version)).is_greater_than_or_equal_to(1)
22
23
  assert_that(after_version[0]).is_greater_than(0)
23
24
 
24
25
  assert_that(before_version).is_equal_to(after_version)
@@ -53,7 +53,9 @@ class TestIntrospection(object):
53
53
  arraylist_Obj = scyjava.jreflect(ArrayList, "constructors")
54
54
  assert len(str_Obj) == len(arraylist_Obj) == 3
55
55
  arraylist_Obj.sort(
56
- key=lambda row: f"{row['type']}:{row['name']}:{','.join(str(row['arguments']))}"
56
+ key=lambda row: (
57
+ f"{row['type']}:{row['name']}:{','.join(str(row['arguments']))}"
58
+ )
57
59
  )
58
60
  assert arraylist_Obj == [
59
61
  {
@@ -60,11 +60,11 @@ class TestPandas(object):
60
60
  df = pd.DataFrame(array, columns=columns)
61
61
 
62
62
  # Convert column 0 to integer
63
- df.iloc[:, 0] = (df.iloc[:, 0] * 100).astype("int")
63
+ df[columns[0]] = (df[columns[0]] * 100).astype("int")
64
64
  # Convert column 1 to bool
65
- df.iloc[:, 1] = df.iloc[:, 1] > 0.5
65
+ df[columns[1]] = df[columns[1]] > 0.5
66
66
  # Convert column 2 to string
67
- df.iloc[:, 2] = df.iloc[:, 2].to_string(index=False).split("\n")
67
+ df[columns[2]] = df[columns[2]].to_string(index=False).split("\n")
68
68
 
69
69
  table = to_java(df)
70
70
 
@@ -137,11 +137,11 @@ class TestPandas(object):
137
137
 
138
138
  # fill mixed table
139
139
  for i in range(table.getRowCount()):
140
- table.set(0, i, Float(float(array_float[i])))
140
+ table.set(0, i, Float(float(array_float[i].item())))
141
141
  table.set(1, i, Integer(int(array_int[i].item())))
142
- table.set(2, i, Boolean(bool(array_bool[i])))
142
+ table.set(2, i, Boolean(bool(array_bool[i].item())))
143
143
  table.set(3, i, String(array_str[i]))
144
- table.set(4, i, Double(float(array_double[i])))
144
+ table.set(4, i, Double(float(array_double[i].item())))
145
145
 
146
146
  df = to_python(table)
147
147
  # Table types cannot be the same here, unless we want to cast.
@@ -1,10 +0,0 @@
1
- #!/bin/sh
2
-
3
- case "$CONDA_PREFIX" in
4
- */scyjava-dev)
5
- ;;
6
- *)
7
- echo "Please run 'make setup' and then 'mamba activate scyjava-dev' first."
8
- exit 1
9
- ;;
10
- esac
scyjava-1.12.0/bin/fmt.sh DELETED
@@ -1,11 +0,0 @@
1
- #!/bin/sh
2
-
3
- dir=$(dirname "$0")
4
- cd "$dir/.."
5
-
6
- exitCode=0
7
- ruff check --fix
8
- code=$?; test $code -eq 0 || exitCode=$code
9
- ruff format
10
- code=$?; test $code -eq 0 || exitCode=$code
11
- exit $exitCode
@@ -1,13 +0,0 @@
1
- #!/bin/sh
2
-
3
- dir=$(dirname "$0")
4
- cd "$dir/.."
5
-
6
- exitCode=0
7
- ruff check
8
- code=$?; test $code -eq 0 || exitCode=$code
9
- ruff format --check
10
- code=$?; test $code -eq 0 || exitCode=$code
11
- validate-pyproject pyproject.toml
12
- code=$?; test $code -eq 0 || exitCode=$code
13
- exit $exitCode
@@ -1,107 +0,0 @@
1
- #!/bin/sh
2
-
3
- # Executes the pytest framework in both JPype and Jep modes.
4
- #
5
- # Usage examples:
6
- # bin/test.sh
7
- # bin/test.sh tests/test_basics.py
8
- # bin/test.sh tests/test_convert.py::TestConvert::test2DStringArray
9
-
10
- set -e
11
-
12
- dir=$(dirname "$0")
13
- cd "$dir/.."
14
-
15
- echo
16
- echo "-------------------------------------------"
17
- echo "| Testing JPype mode (Java inside Python) |"
18
- echo "-------------------------------------------"
19
-
20
- if [ $# -gt 0 ]
21
- then
22
- python -m pytest -p no:faulthandler $@
23
- else
24
- python -m pytest -p no:faulthandler tests/
25
- fi
26
- jpypeCode=$?
27
-
28
- echo
29
- echo "-------------------------------------------"
30
- echo "| Running integration tests (JPype only) |"
31
- echo "-------------------------------------------"
32
- itCode=0
33
- for t in tests/it/*.py
34
- do
35
- python "$t"
36
- code=$?
37
- printf -- "--> %s " "$t"
38
- if [ "$code" -eq 0 ]
39
- then
40
- echo "[OK]"
41
- else
42
- echo "[FAILED]"
43
- itCode=$code
44
- fi
45
- done
46
-
47
- echo
48
- echo "-------------------------------------------"
49
- echo "| Testing Jep mode (Python inside Java) |"
50
- echo "-------------------------------------------"
51
-
52
- # Discern the Jep installation.
53
- site_packages=$(python -c 'import sys; print(next(p for p in sys.path if p.endswith("site-packages")))')
54
- test -d "$site_packages/jep" || {
55
- echo "[ERROR] Failed to detect Jep installation in current environment!" 1>&2
56
- exit 1
57
- }
58
-
59
- # We execute the pytest framework through Jep via jgo, so that
60
- # the surrounding JVM includes scijava-table on the classpath.
61
- #
62
- # Arguments to the shell script are translated into an argument
63
- # list to the pytest.main function. A weak attempt at handling
64
- # special characters, e.g. single quotation marks and backslashes,
65
- # is made, but there are surely other non-working cases.
66
-
67
- if [ $# -gt 0 ]
68
- then
69
- a=$(echo "$@" | sed 's/\\/\\\\/g') # escape backslashes
70
- a=$(echo "$a" | sed 's/'\''/\\'\''/g') # escape single quotes
71
- a=$(echo "$a" | sed 's/ /'\'','\''/g') # replace space with ','
72
- argString="['-v', '$a']"
73
- else
74
- argString=""
75
- fi
76
- if ! java -version 2>&1 | grep -q '^openjdk version "\(1\.8\|9\|10\|11\|12\|13\|14\|15\|16\)\.'
77
- then
78
- echo "Skipping jep tests due to unsupported Java version:"
79
- java -version || true
80
- jepCode=0
81
- elif [ "$(uname -s)" = "Darwin" ]
82
- then
83
- echo "Skipping jep tests on macOS due to flakiness"
84
- jepCode=0
85
- else
86
- echo "# AUTOGENERATED test file for jep; safe to delete.
87
- import logging, sys, pytest, scyjava
88
- scyjava._logger.addHandler(logging.StreamHandler(sys.stderr))
89
- scyjava._logger.setLevel(logging.INFO)
90
- scyjava.config.set_verbose(2)
91
- result = pytest.main($argString)
92
- if result:
93
- sys.exit(result)
94
- " > jep_test.py
95
- jgo -vv \
96
- -r scijava.public=https://maven.scijava.org/content/groups/public \
97
- -Djava.library.path="$site_packages/jep" \
98
- black.ninia:jep:jep.Run+org.scijava:scijava-table \
99
- jep_test.py
100
- jepCode=$?
101
- rm -f jep_test.py
102
- fi
103
-
104
- test "$jpypeCode" -ne 0 && exit "$jpypeCode"
105
- test "$itCode" -ne 0 && exit "$itCode"
106
- test "$jepCode" -ne 0 && exit "$jepCode"
107
- exit 0
@@ -1,41 +0,0 @@
1
- # Use this file to construct an environment
2
- # for developing scyjava from source.
3
- #
4
- # First, install mambaforge:
5
- #
6
- # https://github.com/conda-forge/miniforge#mambaforge
7
- #
8
- # Then run:
9
- #
10
- # mamba env create -f dev-environment.yml
11
- # conda activate scyjava-dev
12
- #
13
- # In addition to the dependencies needed for using scyjava, it
14
- # includes tools for developer-related actions like running
15
- # automated tests (pytest) and linting the code (ruff). If you
16
- # want an environment without these tools, use environment.yml.
17
- name: scyjava-dev
18
- channels:
19
- - conda-forge
20
- dependencies:
21
- - python = 3.9
22
- # Project dependencies
23
- - jpype1 >= 1.3.0
24
- - jgo
25
- - cjdk
26
- # Test dependencies
27
- - numpy
28
- - pandas
29
- # Developer tools
30
- - assertpy
31
- - pytest
32
- - pytest-cov
33
- - python-build
34
- - ruff
35
- - toml
36
- - validate-pyproject
37
- # Project from source
38
- - pip
39
- - pip:
40
- - git+https://github.com/ninia/jep.git@cfca63f8b3398daa6d2685428660dc4b2bfab67d
41
- - -e .
@@ -1,30 +0,0 @@
1
- # Use this file to construct an environment for
2
- # working with scyjava in a runtime setting.
3
- #
4
- # First, install mambaforge:
5
- #
6
- # https://github.com/conda-forge/miniforge#mambaforge
7
- #
8
- # Then run:
9
- #
10
- # mamba env create
11
- # mamba activate scyjava
12
- #
13
- # It includes the dependencies needed for using scyjava, but not tools
14
- # for developer-related actions like running automated tests (pytest),
15
- # linting the code (ruff), and generating the API documentation (sphinx).
16
- # If you want an environment including these tools, use dev-environment.yml.
17
-
18
- name: scyjava
19
- channels:
20
- - conda-forge
21
- dependencies:
22
- - python >= 3.9
23
- # Project dependencies
24
- - jpype1 >= 1.3.0
25
- - jgo
26
- - cjdk
27
- # Project from source
28
- - pip
29
- - pip:
30
- - -e .
@@ -1,15 +0,0 @@
1
- jpype1>=1.3.0
2
- jgo
3
- cjdk
4
-
5
- [dev]
6
- assertpy
7
- build
8
- jep
9
- pytest
10
- pytest-cov
11
- numpy
12
- pandas
13
- ruff
14
- toml
15
- validate-pyproject[all]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes