librelist archives

« back to archive

Why can't I get at leiningen.core.main?

Why can't I get at leiningen.core.main?

From:
Brian Marick
Date:
2013-01-01 @ 00:34
Symptom: In the new lein-midje plugin, 
(:require [leiningen.core.main :as main])) leads to…
ClassNotFoundException: leiningen.core.main

Why?

---------


I want the exit status of lein-midje to be non-zero if there's a test 
failure. I believe the way to do that is this:

	(leiningen.core.main/abort …)

So I did that, with the `require` shown above. This works well in the 
lein-midje project itself. When I push it to clojars, download it, and use
it in other projects, I get the ClassNotFoundException. I don't 
understand.

Here's the start of the file:

> (ns leiningen.midje
>   (:use [leiningen.core.eval :only [eval-in-project]])
>   (:require [leiningen.core.main :as main]))

Here's the code that uses `abort`:

>  (eval-in-project project
>                      `(let [failure-count# (midje.repl/load-facts ~@(map
prepare-arg args))]
>                         (when (pos? failure-count#) (main/abort)))
>                      '(require 'midje.repl))))

Here's project.clj:

> (defproject lein-midje/lein-midje "3.0-alpha1"
>   :description "Run Midje and clojure.test tests"
>   :url "https://github.com/marick/lein-midje"
>   :author "See README"
>   :eval-in-leiningen true
>   :profiles {:dev {:dependencies [[midje "1.5-alpha5"]]}}
>   :license {:name "The MIT License (MIT)"
>             :url "http://opensource.org/licenses/mit-license.php"
>             :distribution :repo}
>   :min-lein-version "2.0.0")

The source is here: https://github.com/marick/lein-midje/tree/v3

--------
Occasional consulting on programming technique
Contract programming in Ruby and Clojure
Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo

Re: [leiningen] Why can't I get at leiningen.core.main?

From:
Brian Marick
Date:
2013-01-01 @ 01:47
Here is the code I'm using: 

>     (eval-in-project project
>                      `(System/exit (midje.repl/load-facts ~@(map 
prepare-arg args)))
>                      '(require 'midje.repl))))

Is this wrong?

--------
Occasional consulting on programming technique
Contract programming in Ruby and Clojure
Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo

Re: [leiningen] Why can't I get at leiningen.core.main?

From:
Brian Marick
Date:
2013-01-01 @ 01:46
On Dec 31, 2012, at 6:34 PM, Brian Marick <marick@exampler.com> wrote:

> Symptom: In the new lein-midje plugin, 
> (:require [leiningen.core.main :as main])) leads to…
> ClassNotFoundException: leiningen.core.main


Apparently, the `abort` has to be outside an `eval-in-project`. But that 
leaves me with the problem of how to communicate results outside 
`eval-in-project`:

* eval-in-project doesn't return the results of 
  the form it evals.
* The code within the eval-in-project can't see 
  external vars to set atoms.
* When I throw an exception to indicate the error, 
  I get a stack trace as part of the output, which is 
  ugly. 

For the moment, I'm just going to use System/exit, even though it seems to
be deprecated:



--------
Occasional consulting on programming technique
Contract programming in Ruby and Clojure
Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo

Re: [leiningen] Why can't I get at leiningen.core.main?

From:
Phil Hagelberg
Date:
2013-01-02 @ 03:59
Brian Marick <marick@exampler.com> writes:

> When I was investigating, I saw this in the Leiningen source:
>
>> (defn exit
>>   "Exit the process. Rebind *exit-process?* in order to suppress actual process
>>   exits for tools which may want to continue operating. Never call
>>   System/exit directly."
>
> … and assumed too much.

Ah, yes I could see how this could be interpreted that way. Calling
System/exit in Leiningen's own process would break things like CCW where
the JVM needs to stay resident after the task completes, but that
doesn't apply within the project.

-Phil

Re: [leiningen] Why can't I get at leiningen.core.main?

From:
Phil Hagelberg
Date:
2013-01-01 @ 19:18
Brian Marick <marick@exampler.com> writes:

> On Dec 31, 2012, at 6:34 PM, Brian Marick <marick@exampler.com> wrote:
>
>> Symptom: In the new lein-midje plugin, 
>> (:require [leiningen.core.main :as main])) leads to…
>> ClassNotFoundException: leiningen.core.main
>
> Apparently, the `abort` has to be outside an `eval-in-project`. 

Right; you can't call Leiningen functions from outside Leiningen. The
project's process is completely isolated from the JVM that started it to
prevent Leiningen's own dependencies from contaminating it.

> But that leaves me with the problem of how to communicate results
> outside `eval-in-project`:
>
> * eval-in-project doesn't return the results of 
>   the form it evals.
> * The code within the eval-in-project can't see 
>   external vars to set atoms.

It spins off a separate process, so really the only notion of a "return
value" that crosses process boundaries is the exit code.

> For the moment, I'm just going to use System/exit, even though it
> seems to be deprecated:

I can't find anything about System/exit being deprecated; could you
provide a citation for that? It's definitely the way I've been
recommending. If the process that's launched from eval-in-project exits
with nonzero then it will throw an ex-info; you can get the exit code
out of it using ex-data.

-Phil

Re: [leiningen] Why can't I get at leiningen.core.main?

From:
Brian Marick
Date:
2013-01-02 @ 00:13
On Jan 1, 2013, at 1:18 PM, Phil Hagelberg <phil@hagelb.org> wrote:

> I can't find anything about System/exit being deprecated; could you
> provide a citation for that? 

Sadly, I don't have a commit trail I can trace back to find it. It *might*
not have come from Leiningen, it occurs to me. When I was investigating, I
saw this in the Leiningen source:

> (defn exit
>   "Exit the process. Rebind *exit-process?* in order to suppress actual process
>   exits for tools which may want to continue operating. Never call
>   System/exit directly."


… and assumed too much. I now wonder if the message came from some other 
library. It was 2-3 lines long. Unfortunately, I zapped my shell buffer 
earlier, so I can't find the original message.

--------
Occasional consulting on programming technique
Contract programming in Ruby and Clojure
Latest book: /Functional Programming for the Object-Oriented Programmer/
https://leanpub.com/fp-oo