[rkward-cvs] SF.net SVN: rkward:[3142] trunk/rkward
m-eik at users.sourceforge.net
m-eik at users.sourceforge.net
Sun Oct 24 21:14:08 UTC 2010
Revision: 3142
http://rkward.svn.sourceforge.net/rkward/?rev=3142&view=rev
Author: m-eik
Date: 2010-10-24 21:14:08 +0000 (Sun, 24 Oct 2010)
Log Message:
-----------
rkwardtests: moved temporary information into one designated environment; updated writing_plugins_introduction.docbook, new chapter on external plugins
Modified Paths:
--------------
trunk/rkward/doc/rkward/writing_plugins_introduction.docbook
trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rktest.runRKTestSuite.R
trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rkwardtests-internal.R
Modified: trunk/rkward/doc/rkward/writing_plugins_introduction.docbook
===================================================================
--- trunk/rkward/doc/rkward/writing_plugins_introduction.docbook 2010-10-24 19:05:08 UTC (rev 3141)
+++ trunk/rkward/doc/rkward/writing_plugins_introduction.docbook 2010-10-24 21:14:08 UTC (rev 3142)
@@ -44,7 +44,7 @@
<legalnotice>&FDLNotice;</legalnotice>
<date>2010-09-10</date>
-<releaseinfo>0.5.4.00</releaseinfo>
+<releaseinfo>0.5.5.00</releaseinfo>
<abstract>
<para>
@@ -1355,6 +1355,141 @@
</chapter>
+<chapter id="external_plugins">
+<title>External plugins</title>
+ <para>As of version 0.5.5, &kapp; provides a confortable way to install additional third party plugins which do not belong to the core package itself. We call these "external plugins". They come in form of a .tar.gz archive and can be managed directly via a dialoge in &kapp;’s configuration. </para>
+ <para>This section of the documentation describes how external plugin archives are to be packaged, so that &kapp; can use them. The plugin creation itself is of course identical to the previous sections. That is, you should probably first write a working plugin, and then check back here to learn how to distribute it. </para>
+ <para>Since external plugins are a relatively young feature, details of this might probably change in future releases. You’re welcome to contribute your ideas to improve the process. </para>
+
+ <section id="why_external_plugins">
+ <title>Why external plugins?</title>
+ <para>The number of packages to extend the functionality of R is immense already, and climbing. On one hand, we want to encourage you to write plugins for even the most specialised tasks you need solved. On the other hand, the average user should not get lost in huge menu trees full of unknown statistical terms. Therefore it seemed reasonable to keep the plugin handling in &kapp; quite modular as well. </para>
+ <para>As a rule of thumb, plugins that seem to serve a widely used purpose (e.g. t-Tests) should become part of the core package, while those who serve a rather limited group of people with special interests should be provided as an optional package. For you as a plugin author it’s best practice to just start with an external plugin. </para>
+ </section>
+
+ <section id="structure_of_a_package_archive">
+ <title>Structure of a package archive</title>
+ <para>For external plugins to install and work propperly, they must follow some structural guidelines regarding their file hierarchy and archive naming. </para>
+
+ <section id="file_hierarchy"><title>File hierarchy</title>
+ <para>Lets have a look at the prototypic file hierarchy of an elaborate plugin archive. You don’t have to include all of these directories and/or files for a plugin to work (read on to learn what’s absolutely neccessary), consider this a "best practice" example: </para>
+ <programlisting>
+ plugin_name/
+ plugins/
+ plugin_name.xml
+ plugin_name.js
+ plugin_name.rkh
+ ...
+ tests/
+ testsuite_name/
+ RKTestStandards.sometest_name.rkcommands.R
+ RKTestStandards.sometest_name.rkout
+ ...
+ testsuite.R
+ plugin_name.pluginmap
+ ChangeLog
+ README
+ AUTHORS
+ LICENSE
+ ...
+ </programlisting>
+ <para>(Please note: In this example, all occasions of "plugin_name", "testsuite_name" and "sometest_name" are to be replaced with their correct names, accordingly.) </para>
+ <section id="basic_plugin_components">
+ <title>Basic plugin components</title>
+ <para>It is mandatory to include at least three files: a .pluginmap, a plugin .xml description and a plugin .js file. That is, even the "plugins" directory is optional. It might just help to give your files some order, especially if you include more that one plugin/dialog in the archive, which is of course no problem. You can have as many directories for the actual plugin files as you see fit, they just have to resemble the .pluginmap, respectively. It is also possible to even include several .pluginmap files, if it fits your needs. </para>
+ </section>
+ <section id="additional_information">
+ <title>Additional information (optional)</title>
+ <para>ChangeLog, README, AUTHORS, LICENSE should be self-explaining and are entirely optional. Actually, they won’t be interpreted by &kapp;, so they are rather meant to carry additional information that might be relevant e.g. for distributors. Most of their relevant content (author credits, licence terms etc.) will be included in the actual plugin files anyway, though (see the section on meta-information below). </para>
+ </section>
+ <section id="automated_plugin_testing">
+ <title>Automated plugin testing (optional)</title>
+ <para>Another optional directory is "tests", which is meant to provide files needed for automated plugin testing. These tests are helpful to quickly check if your plugins still work with new versions of R or &kapp;. If you want to include tests, you should really restrain yourself to the naming scheme and hierarchy shown here. That is, tests should reside in a directory called "tests", which includes a file "testsuite.R" and a folder with tests standards named after the appropriate test suite. You can, however, provide more than one test suite; in that case, if you don’t want to append them all in the one "testsuite.R" file, you can split them in e.g. one file for each test suite and create one "testsuite.R" with "source()" calls for each suite file. In either case, create seperate subdirectories with test standards for each defined suite. </para>
+ <para>The benefits of upholding to this structure is that plugin tests can be run simply by calling "rktests.makplugintests()" from the tests directory without additional arguments. </para>
+
+ <para>Naming the archive An external plugin should follow the naming convention "plugin_name-version.tar.gz". "plugin_name" should be replaced with a proper name, which shouldn’t contain strange symbols or space characters, and definitely mustn’t contain any occurrence of the minus sign "-". That’s important because internally anything after the first "-" is interpreted as the version number of your plugin archive. </para>
+ <para>That said, versioning begins with a "-" and might also contain additional dashes, so "squaring_circles-0.2-3b.tar.gz" would be a valid archive name, whereas "squaring-circles_0.2-3b.tar.gz" would not. </para>
+ </section>
+ </section>
+ </section>
+
+ <section id="meta-information">
+ <title>Meta-information</title>
+ <para>Each plugin archive should provide some basic meta information on what it deals with, where to find more information, who maintians it, if it relies on specific R packages or other plugins, etc. </para>
+ <para>This information is given at least once in your .pluginmap, and can then be included or overwritten in each plugin .xml file (which might be useful if that particular plugin file was contributed by someone else, for instance). </para>
+ <para>To achieve this, the <about> tag is used. The overall structure of this tag looks something like this: </para>
+ <programlisting>
+ <about>
+ <author />
+ <author />
+ ...
+ <dependencies>
+ <package />
+ <package />
+ ...
+ <pluginmap />
+ <pluginmap />
+ ...
+ </dependencies>
+ </about>
+ </programlisting>
+ <para>That is, the <about> tag contains <author> and <dependencies>, and <dependencies> contains <package> and <pluginmap>. Each of these five tags knows in turn several further arguments (see below). </para>
+ <para>As you can see, you can have more than one entry on authors, needed R packages and &kapp; pluginmaps. </para>
+ <para>A full-blown example would look like this: </para>
+ <programlisting>
+<document base_prefix="" namespace="rkward"
+ id="squaring_circles">
+<about
+ name="Square the circle"
+ shortinfo="Squares the circle using Heisenberg compensation."
+ version="0.1-3"
+ releasedate="2010-10-20"
+ url="http://eternalwondermaths.example.org/23/stc.html"
+ license="GPL"
+ category="Geometry">
+
+ <author
+ name="E.A Dölle"
+ email="doelle at eternalwondermaths.example.org"
+ url="http://eternalwondermaths.example.org"
+ />
+ <author
+ name="Timothy Struppi"
+ email="struppi at eternalwondermaths.example.org"
+ url="http://eternalwondermaths.example.org/~staff"
+ />
+
+ <dependencies
+ rkward_min_version="0.5.3"
+ rkward_max_version=""
+ R_min_verion="2.10"
+ R_max_verion="">
+
+ <package
+ name="heisenberg"
+ min_version="0.11-2"
+ max_version=""
+ repository="http://rforge.r-project.org"
+ />
+
+ <pluginmap
+ id="dreams_of_pi"
+ min_version="0.11-2"
+ max_version=""
+ url="http://eternalwondermaths.example.org/23/stc.html"
+ />
+ </dependencies>
+</about>
+</programlisting>
+ <para>Most of this should explain itself, so we’ll not discuss each and every tag element. But let’s look at some details that probably need some commentary for easier understanding. </para>
+ <para>The "category" element in <about> can be defined rather freely, but should be meaningful, as it’s thought to be used to order plugins into groups. All elements in this opening tag are mandatory and must be filled with reasonable content. </para>
+ <para>At least one <author> with a valid e-mail address must also be given. In case your plugin causes problems or someone would like to share its gratitude with you, it should be easy to contact someone who’s involved. However, the URL element can be omitted. </para>
+ <para>Actually the whole <dependencies> might be left empty if your plugin is supposed to run with any &kapp; version and standard R installation. But please be reasonable here as well. The inclusion of any <package> or <pluginmap> tags is of course optional as well, depending on the needs of your plugins. All the "min_version" and "max_version" information can be omitted, as well. They are obviously useful if your plugin is known to rely on certain versions of an R package, for instance. </para>
+ <para>If you need an R package that is probably not hosted on an official CRAN mirror, you can specify a repository where it can be found in the <package> tag. &kapp; will check whether this repository is already defined in its configuration, and if not, add it, but only after the user has given its explicit permission to that. </para>
+ <para>The "id" element in the <pluginmap> tag refers to the ID given in the top level <document> tag of the pluginmap that you need. </para>
+</section>
+</chapter>
+
<appendix id="reference">
<title>Reference</title>
Modified: trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rktest.runRKTestSuite.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rktest.runRKTestSuite.R 2010-10-24 19:05:08 UTC (rev 3141)
+++ trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rktest.runRKTestSuite.R 2010-10-24 21:14:08 UTC (rev 3142)
@@ -22,7 +22,7 @@
rktest.runRKTestSuite <- function (suite, basedir=getwd (), test.id=NULL) {
# check wheter test environment is already set,
# otherwise initialize
- if(!exists(".rktest.tmp.dump", where=globalenv())){
+ if(!exists(".rktest.tmp.storage", where=globalenv())){
rktest.initializeEnvironment()
on.exit(rktest.resetEnvironment())
}
Modified: trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rkwardtests-internal.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rkwardtests-internal.R 2010-10-24 19:05:08 UTC (rev 3141)
+++ trunk/rkward/rkward/rbackend/rpackages/rkwardtests/R/rkwardtests-internal.R 2010-10-24 21:14:08 UTC (rev 3142)
@@ -154,23 +154,28 @@
}
## Convenience functions for replacing / restoring functions for the test runs
-.rktest.backups <- new.env()
rktest.replace <- function (name, replacement, envir=as.environment ("package:rkward"), backup.name=name) {
- if (exists (backup.name, envir=.rktest.backups, inherits=FALSE)) {
+ if(!exists(".rktest.tmp.storage", where=globalenv())){
+ assign(".rktest.tmp.storage", new.env(), pos=globalenv())
+ } else{}
+ if (exists (backup.name, envir=.rktest.tmp.storage, inherits=FALSE)) {
message ("Is looks like ", name, " has already been replaced. Not replacing it again.")
} else {
- assign (backup.name, get (name, envir), envir=.rktest.backups)
+ assign (backup.name, get (name, envir), envir=.rktest.tmp.storage)
assign (name, replacement, envir)
}
}
rktest.restore <- function (name, envir=as.environment ("package:rkward"), backup.name=name) {
- if (exists (backup.name, envir=.rktest.backups, inherits=FALSE)) {
- assign (name, get (backup.name, envir=.rktest.backups), envir=envir)
+ if (exists (backup.name, envir=.rktest.tmp.storage, inherits=FALSE)) {
+ assign (name, get (backup.name, envir=.rktest.tmp.storage), envir=envir)
} else {
message ("No backup available for ", name, ". Already restored?")
}
- rm (list=backup.name, envir=.rktest.backups)
+ rm (list=backup.name, envir=.rktest.tmp.storage)
+ if(length(.rktest.tmp.storage) == 0){
+ rm(".rktest.tmp.storage", pos=globalenv())
+ } else{}
}
## Initialize test environment
@@ -219,8 +224,8 @@
## handling of temporary directories
# get the path to the recent temporary directory, if exists
rktest.getTempDir <- function(){
- if(exists(".rktest.temp.dir", where=globalenv())){
- temp.dir <- get(".rktest.temp.dir", pos=globalenv())
+ if(exists(".rktest.tmp.storage", where=globalenv()) && exists(".rktest.temp.dir", where=.rktest.tmp.storage)){
+ temp.dir <- get(".rktest.temp.dir", pos=.rktest.tmp.storage)
if(file_test("-d", temp.dir)) {
return(temp.dir)
}
@@ -247,7 +252,10 @@
stop(simpleError("Couldn't create temporary directory!"))
}
else {
- assign(".rktest.temp.dir", new.temp.dir, envir=globalenv())
+ if(!exists(".rktest.tmp.storage", where=globalenv())){
+ assign(".rktest.tmp.storage", new.env(), pos=globalenv())
+ } else{}
+ assign(".rktest.temp.dir", new.temp.dir, envir=.rktest.tmp.storage)
return(new.temp.dir)
}
}
@@ -258,7 +266,10 @@
if(is.character(temp.dir)){
unlink(temp.dir, recursive=TRUE)
# should the function stop here if unlink() failed?
- rm(".rktest.temp.dir", envir=globalenv())
+ rm(".rktest.temp.dir", envir=.rktest.tmp.storage)
+ if(length(.rktest.tmp.storage) == 0){
+ rm(".rktest.tmp.storage", pos=globalenv())
+ } else{}
return(TRUE)
}
else {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the rkward-tracker
mailing list