8000 Let jsource also find Java library source code · scijava/scyjava@1d9b507 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1d9b507

Browse files
committed
Let jsource also find Java library source code
And do not try so hard with exception handling; it should be up to higher level functions like scyjava.inspect.src to catch such failures.
1 parent f4266c4 commit 1d9b507

File tree

3 files changed

+58
-30
lines changed

3 files changed

+58
-30
lines changed

src/scyjava/_introspect.py

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class methods, fields, and source code URL.
55

66
from typing import Any, Dict, List
77

8-
from scyjava._jvm import jimport
8+
from scyjava._jvm import jimport, jvm_version
99
from scyjava._types import isjava, jinstance, jclass
1010

1111

@@ -78,34 +78,49 @@ def jreflect(data, aspect: str = "all") -> List[Dict[str, Any]]:
7878
return table
7979

8080

81-
def jsource(data):
81+
def jsource(data) -> str:
8282
"""
83-
Try to find the source code using SciJava's SourceFinder.
83+
Try to find the source code URL for the given Java object, class, or class name.
84+
Requires org.scijava:scijava-search on the classpath.
8485
:param data:
85-
The object or class or fully qualified class name to check for source code.
86-
:return: The URL of the java class
86+
Object, class, or fully qualified class name for which to discern the source code location.
87+
:return: URL of the class's source code.
8788
"""
88-
Types = jimport("org.scijava.util.Types")
89+
90+
if not isjava(data) and isinstance(data, str):
91+
try:
92+
data = jimport(data) # check if data can be imported
93+
except Exception as err:
94+
raise ValueError(f"Not a Java object {err}")
95+
jcls = data if jinstance(data, "java.lang.Class") else jclass(data)
96+
97+
if jcls.getClassLoader() is None:
98+
# Class is from the Java standard library.
99+
cls_path = str(jcls.getName()).replace(".", "/")
100+
101+
# Discern the Java version.
102+
java_version = jvm_version()[0]
103+
104+
# Note: some classes (e.g. corba and jaxp) will not be located correctly before
105+
# Java 10, because they fall under a different subtree than `jdk`. But Java 11+
106+
# dispenses with such subtrees in favor of using only the module designations.
107+
if java_version <= 7:
108+
return f"https://github.com/openjdk/jdk/blob/jdk7-b147/jdk/src/share/classes/{cls_path}.java"
109+
elif java_version == 8:
110+
return f"https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/{cls_path}.java"
111+
else: # java_version >= 9
112+
module_name = jcls.getModule().getName()
113+
# if module_name is null, it's in the unnamed module
114+
if java_version == 9:
115+
suffix = "%2B181/jdk"
116+
elif java_version == 10:
117+
suffix = "%2B46"
118+
else:
119+
suffix = "-ga"
120+
return f"https://github.com/openjdk/jdk/blob/jdk-{java_version}{suffix}/src/{module_name}/share/classes/{cls_path}.java"
121+
122+
# Ask scijava-search for the source location.
89123
SourceFinder = jimport("org.scijava.search.SourceFinder")
90-
String = jimport("java.lang.String")
91-
try:
92-
if not isjava(data) and isinstance(data, str):
93-
try:
94-
data = jimport(data) # check if data can be imported
95-
except Exception as err:
96-
raise ValueError(f"Not a Java object {err}")
97-
jcls = data if jinstance(data, "java.lang.Class") else jclass(data)
98-
if Types.location(jcls).toString().startsWith(String("jrt")):
99-
# Handles Java RunTime (jrt) exceptions.
100-
raise ValueError("Java Builtin: GitHub source code not available")
101-
url = SourceFinder.sourceLocation(jcls, None)
102-
urlstring = url.toString()
103-
return urlstring
104-
except jimport("java.lang.IllegalArgumentException") as err:
105-
return f"Illegal argument provided {err=}, {type(err)=}"
106-
except ValueError as err:
107-
return f"{err}"
108-
except TypeError:
109-
return f"Not 8000 a Java class {str(type(data))}"
110-
except Exception as err:
111-
return f"Unexpected {err=}, {type(err)=}"
124+
url = SourceFinder.sourceLocation(jcls, None)
125+
urlstring = url.toString()
126+
return urlstring

tests/test_inspect.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ def test_inspect_members(self):
1818
members = []
1919
inspect.members("java.lang.Iterable", writer=members.append)
2020
expected = [
21-
"Source code URL: java.lang.NullPointerException",
21+
"Source code URL: "
22+
"https://github.com/openjdk/jdk/blob/jdk-11-ga/"
23+
"src/java.base/share/classes/java/lang/Iterable.java",
2224
" * indicates static modifier",
2325
"java.util.Iterator = iterator()",
2426
"java.util.Spliterator = spliterator()",
2527
"void = forEach(java.util.function.Consumer)",
2628
"",
2729
"",
2830
]
29-
assert expected == "".join(members).split("\n")
31+
assert "".join(members).split("\n") == expected

tests/test_introspect.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ def test_jsource(self):
5757
assert source_SF.startsWith(repo_path)
5858
assert source_strSF == source_SF
5959

60+
def test_jsource_jdk_class(self):
61+
if mode == Mode.JEP:
62+
# JEP does not support the jclass function.
63+
return
64+
jv = scyjava.jvm_version()[0]
65+
source = scyjava.jsource("java.util.List")
66+
assert (
67+
source == f"https://github.com/openjdk/jdk/blob/jdk-{jv}-ga/"
68+
"src/java.base/share/classes/java/util/List.java"
69+
)
70+
6071
def test_imagej_legacy(self):
6172
if mode == Mode.JEP:
6273
# JEP does not support the jclass function.

0 commit comments

Comments
 (0)
0