How to add dependencies to my Julia package? - julia

I have created a package (let's call it package_name) in Julia; the file structure is already generated along with the Project.toml and Manifest.toml files and I have already added some dependencies when I created the package.
I forgot to add a dependency and I would like to get the REPL to show:
(package_name) pkg >
so that I may type
add dependency_name
How do I get the REPL to show this? I think I need to go to the package folder and (re) activate the package but I am unable to navigate to it with cd.
Showing the exact commands I should type in the REPL would be helpful.

In order to get the package REPL mode, you should type a closing bracket ] when your cursor is at the beginning of the line. Likewise, when in package REPL mode, you need to type BackSpc right after the prompt in order to get back to standard REPL mode:
julia> # type ] here to enter the Pkg REPL
# We're now in the Pkg REPL, but the default environment is active
# Let's activate the environment we want
# (replace the path below with "." to activate the environment defined in the current working directory)
(#v1.5) pkg> activate /path/to/package
# Now we see that the correct environment is active
# This is where new dependencies will be added
(package_name) pkg> add DepName
(package_name) pkg> # type BackSpace here to get back to the standard REPL
julia>
Additionally, you could achieve the same thing without entering the Pkg REPL mode, by using the pkg"..." string macro defined in the Pkg library:
julia> using Pkg
julia> pkg"activate /path/to/package"
julia> pkg"add DepName"

You can also add deps manually to your project.toml file like
name = "MyPackage"
uuid = "e91191c6-8984-4a4d-b031-ef6fb65a77ca"
authors = ["Shep Bryan IV and contributors"]
version = "0.1.0"
[deps]
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
This requires that you be able to find the corresponding uuid codes for each package you use. Currently there is no simple function to do this, but if you really want to do it manually you can find a complete list of uuids for registered packages here.
Alternatively you can use this crude script to get the uuids from within Julia:
using Downloads
function get_uuid_from_registry(modulename)
# Download the registry to temporary file
tempfile = Downloads.download("https://github.com/JuliaRegistries/General/blob/master/Registry.toml")
# Open the tempfile
f = open(tempfile, "r")
# Loop through the lines in the file
for line in readlines(f)
if occursin(">$(modulename)<", line)
# Cut out uuid from HTML file
uuid = split(split(line, "<span class=\"pl-smi\">")[2], "</span>")[1]
return uuid
end
end
println("No module found")
return
end
uuid = get_uuid_from_registry("HDF5")

Related

list packages available for download/install in Julia version 1.0

In version 0.4 there was Pkg.available() which I used to look at what packages were available for download/install. How do you do this in v1.0?
Yes, I have read the documentation and searched extensively.
Assuming you are keeping your package repository in a standard location you can use
using Pkg
Pkg.update()
reg = "~/.julia/registries/General/Registry.toml"
regdict = Pkg.TOML.parsefile(reg)
pkg_list = getindex.(values(regdict["packages"]), "name")
If you use a non-standard location of the Registry.toml file then you can see it e.g. when you run Pkg.update() command or get it using Pkg.Types.registries() (the directory where this file lies should be the first entry in the list).
Finally you can fetch Registry.toml from https://github.com/JuliaRegistries/General GitHub repository.
EDIT:
Using standard functions you could do it as follows
using Pkg
reg = joinpath(Pkg.Types.registries()[1], "Registry.toml")
regdict = Pkg.Types.read_registry(reg)
pkg_list = getindex.(values(regdict["packages"]), "name")
You can just use tab-completion in the Pkg REPL mode.
For example:
(v1.0) pkg> add JS[TAB]
JSON JSONWebTokens JSON2 JSExpr JSONSchema
(Where [TAB] represents a key-press, not literal characters)

Does working directory change inside of a function?

I am using Julia 1.0.1 with the Juno IDE.
I wrote a module MyModule,
myModule
using Gadfly, DataFrames, Cairo, Fontconfig
function foo(N::Int64)
grid = 1:N
df = DataFrame(x = grid, y = grid .^2)
p = plot(x = "x", y = "y");
draw(PNG("figures/plot.png", 6inch, 3inch), p)
end
end
Let's call the parent directory "Top". I have a file named main.jl located in Top/Julia. I also have some auxiliary functions located in Top/Julia/functions. The script main.jl consists of the following commands:
using MyModule
include("functions/auxiliaryFunction.jl")
N = 10
foo(10)
When I run this code,
The include("functions/auxiliaryFunction.jl") command works perfectly.
The file plot.png is created inside the directory Top/figures instead of inside of Top/Julia/figures
If I run pwd() in the REPL, it returns ".../Top". So what appears to be happening is that the working directory in the main script is the location of the file itself (or, of the "project" in Juno...kind of confused about that), whereas the working directory of the functions it calls in the modules it imports is the working directory of the REPL. Is this correct or am I missing something? What is the standard solution to this problem - add the working directory as an argument to the function?
Edit 1: If I add
a = pwd()
println("$a")
to the script main.jl, it returns
.../Top
Edit 2: When main.jl is open in Atom, the top bar displays "main.jl --- ~/Top"
I noticed that Atom/Juno IDE can sometimes have some weird effect on the working dir. I think this has to do with the project management. Have you tried closing Juno, and restarting it by opening main.jl in the (...)/top/Julia folder? Code seems fine to me.

Julia Documenter: missing docstring

I have a Julia module file with a function, a doc-string, and a doc-test. I load it and the doc-string shows in the Julia help, but Documenter.jl cannot find the doc-string.
An example module file, src/my_module.jl, is:
module my_module
"""
add(x, y)
Dummy function
# Examples
```jldoctest
julia> add(1, 2)
3
```
"""
function add(x::Number, y::Number)
return x + y
end
end
The make file docs/make.jl is:
using Documenter, my_module
makedocs(
modules = [my_module],
format = :html,
sitename = "my_module.jl",
authors = "unknown",
doctest = true
)
The ouptut of include("src/my_module.jl"), then ?, then my_module.add, shows that the Julia REPL found the docstring:
help?> my_module.add
add(x, y)
Dummy function
Examples
≡≡≡≡≡≡≡≡≡≡
julia> add(1, 2)
3
The output of include("docs/make.jl") shows that Documenter did not:
Documenter: setting up build directory.
Documenter: expanding markdown templates.
Documenter: building cross-references.
Documenter: running document checks.
> checking for missing docstrings.
!! 1 docstring potentially missing:
my_module.add :: Tuple{Number,Number}
> running doctests.
> checking footnote links.
Documenter: populating indices.
Documenter: rendering document.
How come the Julia REPL finds the docstring and not Documenter?
Notes: I ran Pkg.update() before running the code. Documenter has version 0.18.0, Julia has version 0.6.3.
As mentioned in the comments of #fredrikekre, I was missing #autodocs and some other details. Here is a complete setup for doc-testing in Julia with Documenter.jl.
Directory structure of my_module (from command tree, reordered for clarity):
.
|____src
| |____my_module.jl
| |____my_functions.jl
|____docs
| |____make.jl
| |____src
| | |____index.md
|____README.md
|____REQUIRE
The file src/my_module.jl is:
module my_module
# export functions you want to call without qualifications
export add_exported
using DataFrames # or any other module
# Include functions
include("my_functions.jl")
end
The file src/my_functions.jl contains exported and non-exported functions. Note how the doc-test of exported functions has no qualification, and the doc-test of non-exported functions does:
"""
add_exported(x, y)
Dummy function, exported
# Examples
```jldoctest
julia> add_exported(1, 2)
3
```
"""
function add_exported(x::Number, y::Number)
return x + y
end
"""
add_not_exported(x, y)
Dummy function, not exported
# Examples
```jldoctest
julia> my_module.add_not_exported(1, 2)
3
```
"""
function add_not_exported(x::Number, y::Number)
return x + y
end
The file docs/make.jl is:
using Documenter, my_module
makedocs(
modules = [my_module],
format = :html,
sitename = "my_module.jl",
doctest = true
)
The file docs/src/index.md contains using my_module, which brings exported functions into scope:
# Documentation
```#meta
CurrentModule = my_module
DocTestSetup = quote
using my_module
end
```
```#autodocs
Modules = [my_module]
```
The last two files are optional. The file REQUIRE serves only for remote installation of package. It contains:
julia 0.6.3
DataFrames 0.11.6
The file README.md contains a description in Markdown:
# my_module and its description
Finally, change directory to the root of the package, start a Julia session, and type:
julia> include("src/my_module.jl");include("docs/make.jl");
Documenter: setting up build directory.
Documenter: expanding markdown templates.
Documenter: building cross-references.
Documenter: running document checks.
> checking for missing docstrings.
> running doctests.
> checking footnote links.
Documenter: populating indices.
Documenter: rendering document.
If you change the result of add in the doc-test from 3 to any other number, the Documenter will show an error and show that it is working.

RUnit: could not find function "checkEquals"

I am creating an R package with the standard directory hierarchy. Inside the R directory, I create a test subdirectory.
In the R directory, I create a uTest.R file containing:
uTest <- function() {
test.suite <- defineTestSuite('test',
dirs = file.path('R/test'))
test.result <- runTestSuite(test.suite)
printTextProtocol(test.result)
}
In the R/test directory, I create a runit.test.R file containing:
test.validDim <- function() {
testFile <- "test/mat.csv"
generateDummyData(testFile,
10,
10)
checkEquals(validDim(testFile), TRUE)
}
I build and install my package using R CMD INSTALL --no-multiarch --with-keep.source RMixtComp in Rstudio. When I try to launch the function uTest(), I get this error message:
1 Test Suite :
test - 1 test function, 1 error, 0 failures
ERROR in test.validDim: Error in func() : could not find function "checkEquals"
However, if I call library(RUnit) prior to calling uTest(), everything works fine. In the import field of the DESCRIPTION file, I added RUnit, and in the NAMESPACE file I added import(RUnit).
How can I call uTest() directly after loading my package, without manually loading RUnit ?
You should not add RUnit to the Depends (or Imports) field in the DESCRIPTION file (despite the comment to the contrary). Doing so implies that the RUnit package is necessary in order to use your package, which is likely not the case. In other words, putting RUnit in Depends or Imports implies RUnit needs to be installed (Imports) and on the users' search path (Depends) in order for them to use your package.
You should add RUnit to the Suggests field in the DESCRIPTION file, then modify your uTest function as below:
uTest <- function() {
stopifnot(requireNamespace("RUnit"))
test.suite <- RUnit::defineTestSuite('test', dirs = file.path('R/test'))
test.result <- RUnit::runTestSuite(test.suite)
RUnit::printTextProtocol(test.result)
}
Doing this allows you to use RUnit for your tests, but does not require users to have RUnit installed (and possibly on their search path) in order to use your package. Obviously, they'll need RUnit if they wish to run your tests.

Determine version of a specific package

How can I get the version number for a specific package?
The obvious way is to get the dictionary with all installed packages, and then filter for the one of interest:
pkgs = Pkg.installed();
pkgs["Datetime"]
Getting the list of all installed packages is very slow though, especially if there are many packages.
EDIT: For Julia version 1.1+
Use the Pkg REPL notation:
] status # Show every installed package version
] status pkgName # Show the specific version of the package
] status pkgName1 pkgName2 # Show the named packages. You can continue the list.
The ] enters the Pkg REPL, so you basically write status ...
So in your case, write after entering the Pkg REPL:
status DataFrame
Or use the object-oriented approach (NB: Here you don't enter the Pkg REPL, i.e. DON'T use ]:
Pkg.status("DataFrame")
EDIT: For Julia version 1.0
Pkg.installed seems to have "regressed" with the new package system. There are no arguments for Pkg.installed. So, the OP's original method seems to be about the best you can do at the moment.
pkgs = Pkg.installed();
pkgs["Datetime"]
EDIT: For Julia version upto 0.6.4
You can pass a string to Pkg.installed. For example:
pkgs = Pkg.installed("JuMP")
I often check available calling arguments with methods. For example:
julia> methods(Pkg.installed)
# 2 methods for generic function "installed":
installed() at pkg/pkg.jl:122
installed(pkg::AbstractString) at pkg/pkg.jl:129
or
julia> Pkg.installed |> methods
# 2 methods for generic function "installed":
installed() at pkg/pkg.jl:122
installed(pkg::AbstractString) at pkg/pkg.jl:129
I would try Pkg.status("PackageName")
This will print out a little blurb giving the package name.
Here is an example
julia> Pkg.status("QuantEcon")
- QuantEcon 0.0.1 master
In Julia 1.1 you can use
(v1.1) pkg> status "name_of_the_package"
to find the version of any package in a given environment.
In order to look of a version of an indirectly included package (e.g. top-level project includes Module A which depends on Module B, where you need to know info about Module B), you have to pull the info either from the Manifest.toml directly, or you have to bring in the Context object in from Pkg.
Below is done with Julia 1.3.1 ... there may be changes to Pkg's internals since then.
using Pkg
ctx = Pkg.Operations.Context()
# Get the version of CSV.jl
version = ctx.env.manifest[UUID("336ed68f-0bac-5ca0-87d4-7b16caf5d00b")].version
if version <= v"0.5.24"
# handle some uniqueness about the specific version of CSV.jl here
end
UPDATE: Or without a UUID and just the package name (thanks #HHFox):
using Pkg
pkg_name = "Observables"
m = Pkg.Operations.Context().env.manifest
v = m[findfirst(v->v.name == pkg_name, m)].version
or to do the same with the Manifest.toml
using Pkg
# given the path to the Manifest.toml file...
manifest_dict = Pkg.TOML.parsefile(manifest_path)
# look for a named package like `CSV`
package_dict = manifest_dict[package_name][1]
#show package_dict
Well this didn't print well in the comment section...
Here is a version that matches the name rather than the UUID
using Pkg
m = Pkg.Operations.Context().env.manifest
v = m[findfirst(v -> v.name == "CSV", m)].version
For packages which are dependencies of the specified packages in the project file one can use status -m <packageName> or shorter st -m <packageName> in package mode (After ]`).
For a full list, just use st -m.
This is an extension to https://stackoverflow.com/a/25641957.

Resources