Closed ivarref closed 6 years ago
I'm no expert on classpath loading etc, but I propose the following change to source.clj
:
(defn filepath->buffered-reader
[filepath]
(when-let [strm (io/input-stream (io/file filepath))]
(BufferedReader. (InputStreamReader. strm StandardCharsets/UTF_8))))
which fixes the above issue for me (using Oracle JDK). This also seems more standard than using RT/baseloader. Will this break anything?
Thanks and regards.
Interesting problem.
I don't think your solution is the right one, but it's a good starting point for consideration. I don't think we want to use io/file
because we want to be able to load Clojure source that might be packaged in a jar or otherwise on our resource path but isn't on the direct filepath.
I also think using load-file
is a little non-idiomatic - typically you'd require
a namespace. load-file
is one of those vestigial bits from Clojure 1.0 that isn't really in practical use as far as I know, but I might be wrong about that.
Regardless, Pyro should support your use case without throwing an NPE. I'll need to do some more work here - there are a few different options, from just silently failing to retrieve the source file to first trying to load it using baseLoader and then trying to load it using a file loader.
Thanks for the feedback. You are of course correct about loading files inside JARs.
I was just using load-file
to reproduce the issue. The same problem occurs in Cursive IDE using REPL -> Load file in REPL
, so while I'm not sure exactly what Cursive does under the hood, it seems that the namespace path loading is the same as load-file
and thus this will affect Cursive users.
(meta (resolve (symbol "demo.core" "foo"))) ; demo/core.clj loaded using Cursive
=>
{:arglists ([x]),
:line 6,
:column 1,
:file "/Users/ivref/clojure/demo/src/demo/core.clj",
:name foo,
:ns #object[clojure.lang.Namespace 0x734a2101 "demo.core"]}
The following code handles both absolute paths and classpath resources:
(defn filepath->buffered-reader
[filepath]
(when-let [strm (or (.getResourceAsStream (RT/baseLoader) filepath)
(io/input-stream (io/file filepath)))]
(BufferedReader. (InputStreamReader. strm StandardCharsets/UTF_8))))
That meta
printout is actually quite helpful as it highlights the problem - the :file
key is being set differently by load-file
than by require
.
If we require the namespace instead, we get the following:
user=> (meta #'demo.core/foo)
{:arglists ([x]),
:line 6,
:column 1,
:file "demo/core.clj",
:name foo,
:ns #object[clojure.lang.Namespace 0x5fdb9c46 "demo.core"]}
So there's a bit of work to be done here but basically the path forward seems clear. I think the default behavior should still be to try to load it as a resource, but if that returns nil then we should check for the existence of the file in the file system, and if it exists we can try to load that using the mechanism you've described.
And in both mechanisms we should actually handle the nil return value instead of throwing an NPE down the line.
Hopefully resolved by #15.
Hi, and thanks for a library that looks very promising!
I do have some problem to get started though.
To reproduce this problem:
And the stacktrace will be like this:
I'm guessing this is not the expected output. Any ideas on what might be wrong?
I'm using Mac OS X High Sierra. Did I miss something obvious somewhere?
Kind regards