Requires.jl icon indicating copy to clipboard operation
Requires.jl copied to clipboard

Warnings to Errors?

Open sbromberger opened this issue 10 years ago • 5 comments

julia> @require Base.Test begin
       foobarbaz()
       end
WARNING: Error requiring Base.Test from Main:
UndefVarError: foobarbaz not defined
 in anonymous at /Users/bromberger1/.julia/v0.4/Requires/src/require.jl:60
 in err at /Users/bromberger1/.julia/v0.4/Requires/src/require.jl:47
 in anonymous at /Users/bromberger1/.julia/v0.4/Requires/src/require.jl:59
 in withpath at /Users/bromberger1/.julia/v0.4/Requires/src/require.jl:37
 in anonymous at /Users/bromberger1/.julia/v0.4/Requires/src/require.jl:58
 in listenmod at /Users/bromberger1/.julia/v0.4/Requires/src/require.jl:21

This is a bit dangerous (and causes tests to succeed when the functions that are being tested have errors). Is there a way to specify "rethrow errors"?

sbromberger avatar Dec 04 '15 22:12 sbromberger

The tricky part is making this consistent. If Foo requires Bar, which module throws an error depends on the order they are loaded, and to my mind it makes less sense for using Bar to throw an error because of a problem with Foo. Basically, any plan to change the current behaviour needs a solid plan to cover all bases.

MikeInnes avatar Dec 07 '15 12:12 MikeInnes

I'm not sure I understand - in the case above, where we're using @require as a conditional dependency loader, if there's an error in a function within the block it's not thrown. For testing, the error will never be caught since @require will throw a warning instead of an error. The above was a minimal test case, but let me show you how I'm using it:

in test/imports.jl

# if MatrixDepot is available, test somefn()
@require MatrixDepot begin
@test LightGraphs.somefn()
end

somefn() has an error it in, but this code will not cause a testing failure so it can go undetected unless someone's paying attention to warnings.

sbromberger avatar Dec 07 '15 13:12 sbromberger

In that case you should use if isdefined(Main, :MatrixDepot) ... or something similar – you want conditional evaluation, not delayed evaluation.

What @require is doing here is setting up some code if and when MatrixDepot is loaded. So the following sequence of events is possible:

# No error here since MatrixDepot is not loaded
@require MatrixDepot begin
  @test LightGraphs.somefn()
end

using MatrixDepot
# Require block executes, `somefun()` is not defined

If we were to throw an error here, it would indicate that using MatrixDepot has failed, when in fact the error comes from another package.

MikeInnes avatar Dec 07 '15 13:12 MikeInnes

In that case you should use if isdefined(Main, :MatrixDepot) ... or something similar – you want conditional evaluation, not delayed evaluation.

Unfortunately that won't work if the package you want uses macros... this is why Requires.jl is so cool :)

sbromberger avatar Dec 07 '15 15:12 sbromberger

Fair enough – in that case I think you probably want something bespoke ;) How about something like

if isdefined(Main, :MatrixDepot)
  eval(quote
    using MatrixDepot
    # ....
  end)
end

You could macroify that and it wouldn't be so bad.

MikeInnes avatar Dec 07 '15 15:12 MikeInnes