Self-referential values in an R config file - r

Using the config package, I'd like elements to reference other elements,
like how path_file_a references path_directory.
config.yml file in the working directory:
default:
path_directory : "data-public"
path_file_a : "{path_directory}/a.csv"
path_file_b : "{path_directory}/b.csv"
path_file_c : "{path_directory}/c.csv"
# recursive : !expr file.path(config::get("path_directory"), "c.csv")
Code:
config <- config::get()
config$path_file_a
# Returns: "{path_directory}/a.csv"
glue::glue(config$path_file_a, .envir = config)
# Returns: "data-public/a.csv"
I can use something like glue::glue() on the value returned by config$path_file_a.
But I'd prefer to have the value already substituted so config$path_file_a contains the actual value (not the template for the value).
As you might expect, uncommenting the recursive line creates an endless self-referential loop.
Are there better alternatives to glue::glue(config$path_file_a, .envir = config)?

I came across the same problem and I've written a wrapper around config and glue.
The package is called gonfig and has been submitted to CRAN.
With it you would have:
config.yml
default:
path_directory : "data-public"
path_file_a : "{path_directory}/a.csv"
path_file_b : "{path_directory}/b.csv"
path_file_c : "{path_directory}/c.csv"
And in your R script:
config <- gonfig::get()
config$path_file_c
#> "data-public/c.csv"

Related

Providing header dependency in meson

I am using meson build system 0.49.0 on ubuntu 18.04. My project has some idl files and i want to include header files from another folder. How do I add provide include_directories in meson.
idl_compiler = find_program('widl')
idl_generator = generator(idl_compiler,
output : [ '#BASENAME#.h' ],
arguments : [ '-h', '-o', '#OUTPUT#', '#INPUT#' ])
idl_files = [ .... ]
header_files = idl_generator.process(idl_files)
You can add include directories directly to generator() arguments:
idl_generator = generator(idl_compiler,
output : '#BASENAME#.h',
arguments : [
'-h',
'-o', '#OUTPUT#',
'-I', '#0#/src/'.format(meson.current_source_dir()),
'#INPUT#' ])
I added -I option which according to docs can be used to
Add a header search directory to path. Multiple search directories are
allowed.
and used meson's string formatting together with meson's object method current_source_dir() which
returns a string to the current source directory.
Note also that output argument is string, not list.
Or, for example, if you have several of them and need to use them as dependency later, you can have array:
my_inc_dirs = ['.', 'include/xxx', 'include']
generate args for generator:
idl_gen_args = [ '-h', '-o', '#OUTPUT#', '#INPUT#' ]
foreach dir : my_inc_dirs
idl_gen_args += ['-I', '#0#/#1#'.format(meson.current_source_dir(), dir)]
endforeach
idl_generator = generator(idl_compiler,
output : '#BASENAME#.h',
arguments : idl_gen_args)
and use later for dependency:
my_exe = executable(
...
include_directories : [my_inc_dirs],
...)

Why does lintr say "warning: no visible binding for global variable ‘Cloaked’"?

I'm sure that this is a misunderstanding of mine, since I'm not really an R programmer...
I have my code here: https://gist.github.com/bnsh/3839c4eb2c6b31e32c39ec312014b2b8
#! /usr/bin/env Rscript
library(R6)
Cloaked <- R6::R6Class("Cloaked",
public = list(
msg = function() {
return(paste(
"this code _works_, but lintr (https://github.com/jimhester/lintr)",
"complains that cloak_class.R:19:8: warning: no visible binding for",
"global variable ‘Cloaked’ when I try to use Cloaked within a",
"function. It's fine tho, if I use it _outside_ a function."
))
}
)
)
main <- function() {
c <- Cloaked$new()
c$msg()
}
main()
It works... But, lintr complains: "cloak_class.R:19:8: warning: no visible binding for global variable ‘Cloaked’"
Actually, it's not about a class, really, because this also complains:
#! /usr/bin/env Rscript
cloaked <- function() {
return(paste(
"this code _works_, but lintr (https://github.com/jimhester/lintr)",
"complains that cloak_function.R:13:3: warning: no visible global",
"function definition for ‘cloaked’ when I try to use cloaked within",
"a function. It's fine tho, if I use it _outside_ a function."
))
}
main <- function() {
cloaked()
}
main()
This code also runs, but lintr says:
cloak_function.R:13:3: warning: no visible global function definition for ‘cloaked’
Why? Short of doing something blunt instrument like # nolint start/# nolint end, what can I do to satisfy lintr?
Thanks!
I've just started with lintr and had the same problem. It appears to be a bug.
https://github.com/REditorSupport/atom-ide-r/issues/7
and the actual issue
https://github.com/jimhester/lintr/issues/27
The only workaround for now (short of fixing the bug within lintr) is to disable the object linter (which is not all that ideal as it will not catch genuine errors of this form). e.g.
with_defaults(object_usage_linter=NULL)
(I don't think the object usage linter is intended for scripts but rather packages - as far as I can tell, to work it will eval the entire script (!) to see what globals are defined. For a package where the R files are all function definitions that's fine, but for a script you don't really want to run the whole script every time you lint the file)
Using the linters argument in the lintr functions:
lint("myfile.R", linters = linters_with_defaults(
object_length_linter = NULL,
object_name_linter = NULL,
object_usage_linter = NULL))

NoSuchMethodException when calling sendKeys on object of class org.openqa.selenium.remote.RemoteWebElement via R package rJava

I am trying to use the selenium webdriver API directly from R using rJava. I am subject to a fairly restrictive IT environment, so I can't access a remote driver currently (hence why I'm not currently using the Rselenium package), and I don't have either Chrome or Firefox availaible--just phantomjs. I am able to get this working okay from the Scala REPL. I used sbt to get all the dependenices--build.sbt contains, for example:
retrieveManaged := true
libraryDependencies ++= Seq (
"org.seleniumhq.selenium" % "selenium-java" % "3.9.1",
"com.codeborne" % "phantomjsdriver" % "1.4.4"
)
(Note that I have phantomjs installed as /usr/local/bin/phantomjs, and it is
version 2.1.1).
I then copied all the jar files to a single-level folder via cp jars/*/*/*.jar alljars/ containing the following:
animal-sniffer-annotations-1.14.jar httpcore-4.4.6.jar selenium-api-3.9.1.jar
byte-buddy-1.7.9.jar j2objc-annotations-1.1.jar selenium-chrome-driver-3.9.1.jar
checker-compat-qual-2.0.0.jar jline-2.14.5.jar selenium-edge-driver-3.9.1.jar
commons-codec-1.10.jar jsr305-1.3.9.jar selenium-firefox-driver-3.9.1.jar
commons-exec-1.3.jar okhttp-3.9.1.jar selenium-ie-driver-3.9.1.jar
commons-logging-1.2.jar okio-1.13.0.jar selenium-java-3.9.1.jar
error_prone_annotations-2.1.3.jar phantomjsdriver-1.4.4.jar selenium-opera-driver-3.9.1.jar
gson-2.8.2.jar scala-compiler-2.12.4.jar selenium-remote-driver-3.9.1.jar
guava-23.6-jre.jar scala-library-2.12.4.jar selenium-safari-driver-3.9.1.jar
httpclient-4.5.3.jar scala-reflect-2.12.4.jar selenium-support-3.9.1.jar
I start Scala via scala -cp "alljars/*" and can the do following:
val drv = new org.openqa.selenium.phantomjs.PhantomJSDriver
drv.get("https://www.google.com")
val q = drv.findElementByName("q")
q.sendKeys("rJava selenium")
q.submit
drv.getTitle
I think the following is roughly the same thing in R using rJava:
library(rJava)
.jinit()
jars <- dir("alljars", pattern = "*.jar", full.names = TRUE)
.jaddClassPath(jars)
drv <- .jnew('org/openqa/selenium/phantomjs/PhantomJSDriver')
drv$get("https://www.google.com")
q <- drv$findElementByName("q")
q$sendKeys("rJava selenium")
q$submit()
drv$getTitle()
This fails at the point q$sendKeys("rJava selenium") with the following error:
Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, :
java.lang.NoSuchMethodException: No suitable method for the given parameters
In RStudio, if I type q$ and press TAB, sendKeys is definitely in the list of available methods. I tried to be explicit about this, and tried:
keys <- .jnew("java/lang/String", "rJava selenium")
keys <- .jcast(keys, "java/lang/CharSequence", check = TRUE)
q <- .jcast(q, "org/openqa/selenium/WebElement", check = TRUE)
.jcall(q, "V", "sendKeys", keys)
which resulted in the following error:
Error in .jcall(q, "V", "sendKeys", keys) :
method sendKeys with signature (Ljava/lang/CharSequence;)V not found
q has class org/openqa/selenium/remote/RemoteWebElement in R, and org/openqa/selenium/WebElement in Scala; but in both cases the return is void and the required argument is CharSequence according to the javadocs. I tried a few variations of this--java.lang.String instead of CharSequence, RemoteWebElement instead of WebElement, etc., but no joy.
I doubt this is a problem with rJava, but I'm stumped nonetheless and need help!
Oh good grief. I didn't know about .jmethods. Running this:
> .jmethods(q, "sendKeys")
[1] "public void org.openqa.selenium.remote.RemoteWebElement.sendKeys(java.lang.CharSequence[])"
So, basically, my problem was that I was passing String instead of String[]. That is, instead of:
q$sendKeys("rJava selenium")
I can use:
q$sendKeys(.jarray("rJava selenium"))
The more you know...

What is the proper way to organize a Julia source tree?

I am trying to figure the proper way to organize the source tree for a Julia application seqscan. For now I have the following tree:
$ tree seqscan/
seqscan/
├── LICENSE
├── README.md
├── benchmark
├── doc
├── examples
├── src
│   └── seq.jl
└── test
└── test_seq.jl
5 directories, 4 files
The file seq.jl contains
module SeqScan
module Seq
export SeqEntry
type SeqEntry
id
seq
scores
seq_type
end
end
end
and test_seq.jl contains:
module TestSeq
using Base.Test
using SeqScan.Seq
#testset "Testing SeqEntry" begin
#testset "test SeqEntry creation" begin
seq_entry = SeqEntry("test", "atcg")
#test seq_entry.id == "test"
#test seq_entry.seq == "atcg"
end
end
end
However, running the test code yields an error:
ERROR: LoadError: ArgumentError: Module SeqScan not found in current path.
even after setting the JULIA_LOAD_PATH environment variable to include seqscan or seqscan/src, so I must be doing something wrong?
The name of your package (the root of your local tree) needs to match the name of a file that exists under the src directory. Try this:
SeqScan/
|-- src/
|-- SeqScan.jl (your seq.jl)
I don't know why you are enclosing the module Seq in SeqScan. If there is no important reason to do that, you could access the type more directly. You could remove "module Seq" and the paired "end". Then just "using SeqScan" would bring in the type SeqEntry.
The type, SeqEntry, as written knows what to do when given four field values, one for each of the defined fields. If you want to initialize that type with just the first two fields, you need to include a two-argument constructor. For example, assuming seq is a vector of some numeric type and scores is also a vector of that numeric type and and seq_type is a numeric type:
function SeqEntry(id, seq)
seq_type = typeof(seq[1])
scores = zeros(seq_type, length(seq))
return SeqEntry(id, seq, scores, seq_type)
end
An example of a package with internal modules, for Julia v0.5.
The package is named MyPackage.jl; it incorporates two internal modules: TypeModule and FuncModule; each module has its own file: TypeModule.jl and FuncModule.jl.
TypeModule contains a new type, MyType. FuncModule contains a new function, MyFunc, which operates on variable[s] of MyType. There are two forms of that function, a 1-arg and a 2-arg version.
MyPackage uses both internal modules. It incorporates each for immediate use and initializes two variables of MyType. Then MyPackage applies MyFunc to them and prints the results.
I assume Julia's package directory is "/you/.julia/v0.5" (Windows: "c:\you.julia\v0.5"), and refer to it as PkgDir. You can find the real package directory by typing Pkg.dir() at Julia's interactive prompt. The first thing to do make sure Julia's internal information is current: > Pkg.update() and then get a special package call PkgDev: > Pkg.add("PkgDev")
You might start your package on GitHub. If you are starting it locally, you should use PkgDev because it creates the essential package file (and others) using the right structure:
> using PkgDev then > PkgDev.generate("MyPackage","MIT")
This also creates a file, LICENSE.md, with Julia's go-to license. You can keep it, replace it or remove it.
In the directory PkgDir/MyPackage/src, create a subdirectory "internal". In the directory PkgDir/MyPackage/src/internal, create two files: "TypeModule.jl" and "FuncModule.jl", these:
TypeModule.jl:
module TypeModule
export MyType
type MyType
value::Int
end
end # TypeModule
FuncModule.jl:
module FuncModule
export MyFunc
#=
!important!
TypeModule is included in MyPackage.jl before this module
This module gets MyType from MyPackage.jl, not directly.
Getting it directly would create mismatch of module indirection.
=#
import ..MyPackage: MyType
function MyFunc(x::MyType)
return x.value + 1
end
function MyFunc(x::MyType, y::MyType)
return x.value + y.value + 1
end
end # FuncModule
And in the src directory, edit MyPackage.jl so it matches this:
MyPackage.jl:
module MyPackage
export MyType, MyFunc
#=
!important! Do this before including FuncModule
because FuncModule.jl imports MyType from here.
MyType must be in use before including FuncModule.
=#
include( joinpath("internal", "TypeModule.jl") )
using .TypeModule # prefix the '.' to use an included module
include( joinpath("internal", "FuncModule.jl") )
using .FuncModule # prefix the '.' to use an included module
three = MyType(3)
five = MyType(5)
four = MyFunc(three)
eight = MyFunc(three, five)
# show that everything works
println()
println( string("MyFunc(three) = ", four) )
println( string("MyFunc(three, five) = ", eight) )
end # MyPackage
Now, running Julia entering > using MyPackage should show this:
julia> using MyPackage
4 = MyFunc(three)
9 = MyFunc(three, five)
julia>

Building R package with Reference objects fails

I recently rewrote a package to use the new(er) R reference class objects. I've exported the three classes using export() in the NAMESPACE file so as far as I'm aware that should work. However when I test build the package I get an error at lazy loading stage:
** preparing package for lazy loading
Error in file(con, "rb") : invalid 'description' argument
ERROR: lazy loading failed for package ‘PACKAGE_NAME_HERE’
* removing ‘/Library/Frameworks/R.framework/Versions/3.0/Resources/library/PACKAGE_NAME_HERE’
I'm not sure what the problem is here. I don't know if it's relevant but the reference classes do store data on files in the tmp directory by having some fields set as accessor functions - I don't know if that's what s being complained about here when it says (con, "rb") which I guess is some connection thing. Does anybody have any ideas or advice for making sure reference classes get exported properly? My namespace is currently simple -
export(Main)
export(Mainseq)
export(Maintriplet)
Which are the three reference classes I exported by using #export tags in roxygen2.
What is it I'm doing (or not doing) that is throwing the lazy load error?
(ASIDE - I have no compiled code - all R, although the reference class methods do call some internal functions that are not exported, but these are supposed to be internal so I don't think I need to export them.
Thanks,
Ben.
EDIT:
My description file is as follows:
Package: HybRIDS
Type: Package
Title: Quick detection and dating of Recombinant Regions in DNA sequence data.
Version: 1.0
Date: 2013-03-13
Author: Ben J. Ward
Maintainer: Ben J. Ward <b.ward#uea.ac.uk>
Description: A simple R package for the quick detection and dating of Recombinant Regions in DNA sequence data.
License: GPL-2
Depends: ggplot2,grid,gridExtra,png,ape
I can't see what is wrong with this - the Depends are correct.
EDIT:
I've eliminated the first error with the description but I'm still getting the con error.
I think it's because the Mainseq class (which is nested in class Main) has some fields:
FullSequenceFile = "character",
FullSequence = function( value ) {
if( missing( value ) ){
as.character( read.dna( file = FullSequenceFile, format = "fasta", as.matrix = TRUE ) )
} else {
write.dna( value, file = FullSequenceFile, format = "fasta" )
}
},
InformativeSequenceFile = "character",
InformativeSequence = function( value ) {
if( missing( value ) ){
as.character( read.dna( file = InformativeSequenceFile, format = "fasta", as.matrix = TRUE ) )
} else {
write.dna( value, file = InformativeSequenceFile, format = "fasta" )
}
}
The idea being upon initialisation, the two character fields are filled with a path to a temp file in tmpdir, and when the variables are called or edited the files containing the variable data are read or written to. However it seems the variables are being accessed before this path is available because up package build the following happens:
** preparing package for lazy loading
Warning in file(con, "rb") :
cannot open file '/var/folders/kp/clkqvqn9739ffw2755zjwy74_skf_z/T//RtmpLB8ESC/FullSequenceaba52ac591f3': No such file or directory
Error in file(con, "rb") : cannot open the connection

Resources