Julia Documenter: missing docstring - julia

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.

Related

Beginner package developer fails to knitr its first README.Rmd due to "could not find function"

I have a package for some tasks,
containing some files such as like, foo.R and README.Rmd.
Now foo.R has a simple function, like:
#' Hello, world!
#'
#' #export
hello <- function() {
print("Hello, world!")
}
And in README.Rmd , I describe how foo.R works, like:
library(test) # suppose the package name is `test`
hello()
Suppose other part typically required in README.Rmd (e.g. yaml) is
written as default.
And I excute (in R Studio) Ctrl + Shift + D (devtools::document()) and Ctrl + Shift + B,
Then I knitr it (Ctrl + Shift + K), and get error with message:
Error in hello() : could not find function "hello"
I've tried many other way (like actually uploading it to github and installing it), but it doesn't help.
Please tell me what is wrong!

How to add dependencies to my Julia package?

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")

What's the most simple approach to name-spacing R files with `file::function`

Criteria for answer to this question
Given the following function (within its own script)
# something.R
hello <- function(x){
paste0("hello ", x)
}
What is the most minimal amount of setup which will enable the following
library(something)
x <- something::hello('Sue')
# x now has value: "hello Sue"
Context
In python it's very simple to have a directory containing some code, and utilise it as
# here foo is a directory
from foo import bar
bar( ... )
I'm not sure how to do something similar in R though.
I'm aware there's source(file.R), but this puts everything into the global namespace. I'm also aware that there's library(package) which provides package::function. What I'm not sure about is whether there's a simple approach to using this namespacing within R. The packaging tutorials that I've searched for seem to be quite involved (in comparison to Python).
I don't know if there is a real benefit in creating a namespace just for one quick function. It is just not the way it is supposed to be (I think).
But anyway here is a rather minimalistic solution:
First install once: install.packages("namespace")
The function you wanted to call in the namespace:
hello <- function(x){
paste0("hello ", x)
}
Creating your namespace, assigning the function and exporting
ns <- namespace::makeNamespace("newspace")
assign("hello",hello ,env = ns)
base::namespaceExport(ns, ls(ns))
Now you can call your function with your new namespace
newspace::hello("you")
Here's the quickest workflow I know to produce a package, using RStudio. The default package already contains a hello function, that I overwrote with your code.
Notice there was also a box "create package based on source files", which I didn't use but you might.
A package done this way will contain exported undocumented untested functions.
If you want to learn how to document, export or not, write tests and run checks, include other objects than functions, include compiled code, share on github, share on CRAN.. This book describes the workflow used by thousands of users, and is designed so you can usually read sections independently.
If you don't want to do it from GUI you can useutils::package.skeleton() to build a package folder, and remotes::install_local() to install it :
Reproducible setup
# create a file containing function definition
# where your current function is located
function_path <- tempfile(fileext = ".R")
cat('
hello <- function(x){
paste0("hello ", x)
}
', file = function_path)
# where you store your package code
package_path <- tempdir()
Solution :
# create package directory at given location
package.skeleton("something", code_file = file_path, path = package_path)
# remove sample doc to make remotes::install_local happy
unlink(file.path(package_path, "something", "man/"), TRUE)
# install package
remotes::install_local(file.path(package_path, "something"))

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.

calling an Rscript from node.js

I have been trying to execute an Rscript from my node.js server. tried to follow an example online, but i keep getting a null returned object or sometimes the process keeps running forever. I have mentioned the code snippet below. Thank you.
example.js ::
var R = require("r-script");
var out = R("scripts/testScript.R")
.data("hello world", 20)
.callSync(function(err,resp){
console.log(out);
});
testScript.R file :::
needs(magrittr)
set.seed(512)
do.call(rep, input) %>%
strsplit(NULL) %>%
sapply(sample) %>%
apply(2, paste, collapse = "")
For windows users:
You need to add the environment variable to Windows's %PATH% variable. R-script package needs to call "R" command from the CMD. If R.exe is not set as a environment vairable, then it will never be able to call the "R" command from anywhere.
Look up how to add environment variables to Windows, and remember: if the path to the folder containing the executables has a white space, it must be added between double quotes. "C:\Program Files\R\R-3.3.2\bin\x64"
If you have already done this but the problem persists, I can only think of two reasons:
There's something wrong with your R method and it's giving an internal exception inside the R session.
The system can't find the file. Maybe check the filepath.
You can use child processes in node to call other languages. I find it easiest to call Python from node, and use Python's subprocess module to then call R:
NODE
var spawn = require("child_process").spawn
var process = spawn('python',["call_r.py", script_choice, function_choice]);
This calls our call_r.py file passing along our script and function choices:
PYTHON (call_r.py)
import subprocess
import sys
script_choice = sys.argv[1]
function_choice = sys.argv[2]
call_script = 'R_Scripts/' + script_choice + '.R'
cmd = ['Rscript', call_script] + [function_choice]
result = subprocess.check_output(cmd, universal_newlines=True)
print(result)
sys.stdout.flush()
This parses the passed script and function choices, calling R via Python's subprocess module.
R (script that was chosen)
myArgs <- commandArgs(trailingOnly = TRUE)
function_choice <- myArgs[1]
# add your R functions here
eval(parse(text=function_choice))
Here, R parses the passed function choice and evaluates it. Note that arguments can be passed to the R function of choice by simply including them in the function argument (e.g. my_function('hey there'))

Resources