Problems with using both unregistered and registered modules

The actual behaviour of using/include doesn’t seem to match the documentation, so clearly I do ot understand it. Here is a MWE to explain. In a clean environment (new empty folder and fresh REPL) create the following two modules and save as mytest.jl and myothertest.jl respectively:

module mytest
using myothertest
const VAR = 42
println(OTHERVAR)
export VAR
end  # module mytest
module myothertest
const OTHERVAR = 999
export OTHERVAR 
end  # module myothertest

To run the module mytest I need to cd to the new folder and do push!(LOAD_PATH, pwd()) in the REPL. This all works. ‘999’ is printed in the REPL and I have access to both VAR and OTHERVAR.

Next I activate the package manager and at the Pkg prompt I do add CSV (any registered package will do). Now when I try to run mytest as before (no changes to the LOAD_PATH or code whatsoever), it now fails with the error ERROR: LoadError: ArgumentError: Package myothertest not found in current path.

So adding external repositories suddenly prevents Julia looking in the PWD even when it is part of the LOAD_PATH. This is unexpected behavior.

I can get to myothertest by adding include("myothertest.jl") above the using myothertest statement, but I don’t understand why Julia suddenly requires me to use include where it didn’t before. Am I doing something wrong? Is this normal behavior and if so, why?

I’ve struggled with all this, too. I think the answer depends on how you are running your test.

Adding a package to your project will cause the file project.toml to be created. That tries to describe everything that is needed for someone to independently download, test, and run your project. The project file works on the assumption that there is a module with the same name as your project (the directory name). So far as I can see, you can’t specify multiple local modules in that file.

If you run your tests using Pkg.test() the tests will run with just the environment specified in project.toml - so it will look for a single module with the project name, and just the libraries you’ve explicitly added. If you just run your test script from the command line or REPL, you can add any paths you like & you should be fine.

With a package configured the ‘official’ way - which you’ll likely need if you’re planning on sharing it - one approach is to use child modules - so you have a module with the same name as the project which includes each of mytest and myothertest modules., so something like:

module MyProject

include( "mytest.jl" )
export mytest

include( "myothertest.jl" )
export myothertest

end

your 2 modules can then talk to one another, though you’ll have to qualify the import statements in each.

I hope that makes a little sense. Trying to explain it out loud helps me understand it myself! I’m sure developers with more experience can put this better than I can.

Graham

I wonder how you added CSV.

If you simply do

(@v1.4) pkg> add CSV

CSV is added to your “base” environment (v1.4 in my case). You should not have a Project.toml in your previously empty directory.

But if you

(@v1.4) pkg> activate .
 Activating new environment at `~/Documents/julia/test1/Project.toml`
(test1) pkg> add CSV

then what @grahamstark mentioned would happen and you would end up with Project.toml in your new environment. Now using mytest will fail.

1 Like