Skip to content

Commit f029611

Browse files
committed
Initial version
1 parent d62af2f commit f029611

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1021
-0
lines changed

README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Program Package Development
2+
This program package guides you through how to develop
3+
programs for WPS Hub Deployment Services within a
4+
program package.
5+
6+
Program packages are stored in git, and are edited using
7+
normal editors and a standard git client. The program package
8+
git repository can be hosted by the Hub itself, or it
9+
can he hosted on a site such as Github.
10+
11+
When using program packages, the package becomes the unit
12+
of deployment. So all programs within a package are deployed
13+
together to an environment.
14+
15+
## Package structure
16+
A package can be structured in any way you choose. Programs
17+
can be placed in directories for organisation if necessary.
18+
However, it is important to note that the complete git repository
19+
is deployed together. The package becomes the unit of deployment.
20+
So make sure that the git repository only contains resources
21+
that are necessary for deployment. It is not possible to deploy
22+
only part of a repository.
23+
24+
In simple terms, if there is a file called "hello.sas" in the
25+
package, it can be invoked using a URL of `deployed-package-name/hello.sas`.
26+
27+
28+
## Package Descriptor File
29+
There is an optional file, `package.yaml` that can exist
30+
in the root directory of a package. This describes, amongst
31+
other things, the programs within the package that should be
32+
published to the directory. Note that publication of programs
33+
in the directory is not required for invocation. Programs can be
34+
invoked directly if the URL is known ('ex-directory' programs).
35+
Publication in the directory is necessary in order for the program
36+
to be invoked using an invocation interface such as the Excel plugin.
37+
38+
### Syntax
39+
The package.yaml file is a YAML file with the following fields:
40+
41+
| Field | Type | Description |
42+
| ----- | ---- | ----------- |
43+
| publishInDirectory | Array of string | A list of the relative paths to the programs to publish in the directory |
44+
45+
## Program Descriptor
46+
In order to be able to invoke a program it is necessary to have a description of its interface and invocation options. This information is stored in the program descriptor that is associated with a program.
47+
48+
The program descriptor is placed in a separate YAML file alongside the program source file. The program descriptor should have the same name as the program source file, with an additional ".yaml" extension. So for a program source file called "hello.sas", the program descriptor should be in a file called "hello.sas.yaml".
49+
50+
Note that a program descriptor isn't strictly necessary. For a program that has no parameters, and uses all of the default execution options, no descriptor is required. In all but the simplest of cases though the descriptor is required.
51+
52+
### Program Descriptor Syntax
53+
The descriptor is a YAML formatted file with the following base properties:
54+
55+
| Field | Type | Description |
56+
| ----- | ---- | ----------- |
57+
| label | string | The label under which this program is published in the directory. This is only relevant if the program is included in the list of programs to be published within the package descriptor file. If not specified, the program's file name, without extension, is used.
58+
| description | string | A description of the program to place in the directory. This is only relevant if the program is included in the list of programs to be published within the package descriptor file.
59+
| categories | array of string | A list of categories under which the program will be listed in the directory, if it is to be published.
60+
| parameters | array of object | A list of the parameters for the program.
61+
62+
#### SAS Language Programs
63+
In addition, for SAS language programs, the following properties can be specified:
64+
65+
| Field | Type | Description |
66+
| ----- | ---- | ----------- |
67+
| resultType | string | One of the values `stream` or `dataset`.
68+
| resultContentType | string | The media type of the output in the case of `resultType` being set to `stream`
69+
| resultDatasetName | string | The name of the data set to be returned in the case of `resultType` being set to `dataset`
70+
| resultFormat | string | One of the values `json`, `csv` or `xml`. Determines how data sets are converted to text when generating the response.
71+
| parameterStyle | string | One of the values `macroVars` or `dataset`. Determines how parameters are passed into the program.
72+
73+
These settings are described by way of the examples
74+
75+
#### R Language Programs
76+
In addition, for R language programs, the following properties can be specified:
77+
78+
| Field | Type | Description |
79+
| ----- | ---- | ----------- |
80+
| resultType | string | One of the values `stream`, `object` or `console`.
81+
| resultContentType | string | The media type of the output in the case of `resultType` being set to `stream`
82+
| resultObjectName | string | The name of the R object to be returned in the case of `resultType` being set to `object`
83+
| resultFormat | string | One of the values `json`, `csv`, `print` or `tab`. Determines how the result object is converted to text when generating the response.
84+
| parameterStyle | string | One of the values `macroVars` or `dataset`. Determines how parameters are passed into the program.
85+
| initText | string | A set of R program statements that are invoked once within the R runtime that will be used to invoke this program.
86+
87+
These settings are described by way of the examples
88+
89+
## Examples
90+
There are two sets of examples, one in the SAS language and one in the R language.
91+
92+
* [SAS Language examples](sas/README.md)
93+
* [R Language examples](r/README.md)
94+
95+
96+

package.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This is a package descriptor file for the
2+
# package. It describes, amonst other things,
3+
# the list of programs to publish in the directory
4+
publishInDirectory:
5+
- sas/ExploringBooleanParameters.sas
6+
- sas/ExploringDateParameters.sas
7+
- sas/ExploringDatetimeParameters.sas
8+
- sas/ExploringIntParameters.sas
9+
- sas/ExploringTimeParameters.sas
10+
- sas/HelloWorld.sas
11+
- sas/HelloWithParameter.sas
12+
- sas/ParametersAsDataset.sas
13+
- sas/ReturnDataset.sas
14+
- sas/ReturningGraphics.sas
15+
- sas/ReturningHtml.sas
16+
- sas/ReturningListing.sas
17+
- sas/ReturningPdf.sas
18+
- sas/ReturnParametersAsDataset.sas
19+
- r/HelloWorld.r
20+
- r/ReturningDataFrame.r
21+
- r/ReturningDataFrameAsCsv.r
22+
- r/ReturningDataFrameAsPrint.r
23+
- r/ReturningConsoleOutput.r
24+
- r/ReturningStreamOutput.r
25+
- r/PassingParameters.r
26+
- r/BooleanParameters.r
27+
- r/IntegerParameters.r
28+
- r/DateParameters.r
29+
- r/TimeParameters.r
30+
- r/DatetimeParameters.r
31+
- r/ProcessingRequestBody.r
32+
- r/InitProgram.r

r/BooleanParameters.r

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
result <- data.frame(
2+
boolOptionalNoDefault,
3+
boolOptionalDefaultFalse,
4+
boolOptionalDefaultTrue,
5+
boolRequiredNoDefault,
6+
boolRequiredDefaultFalse,
7+
boolRequiredDefaultTrue)

r/BooleanParameters.r.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
label: PKGR07c - Exploring Boolean parameters
2+
categories:
3+
- Example
4+
- R Language Example
5+
- Package Example
6+
description: |
7+
This example demonstrates use of a boolean parameter
8+
9+
The program has parameters that are required and optional,
10+
and with default values of true and false.
11+
12+
The HTTP query parameters are converted from strings to
13+
boolean values using the `as.logical` function.
14+
15+
resultFormat: print
16+
resultObjectName: result
17+
parameters:
18+
boolOptionalNoDefault:
19+
label: Boolean Optional No Default
20+
datatype: bool
21+
22+
boolOptionalDefaultFalse:
23+
label: Boolean Optional Default False
24+
datatype: bool
25+
defaultValue: false
26+
27+
boolOptionalDefaultTrue:
28+
label: Boolean Optional Default true
29+
datatype: bool
30+
defaultValue: true
31+
32+
boolRequiredNoDefault:
33+
label: Boolean Required No Default
34+
datatype: bool
35+
required: true
36+
37+
boolRequiredDefaultFalse:
38+
label: Boolean Required Default false
39+
datatype: bool
40+
defaultValue: false
41+
required: true
42+
43+
boolRequiredDefaultTrue:
44+
label: Boolean Required Default true
45+
datatype: bool
46+
defaultValue: true
47+
required: true

r/DateParameters.r

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
result <- data.frame(
2+
dateRequired, dateOptional
3+
)

r/DateParameters.r.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
label: PKGR07e - Exploring Date parameters
2+
categories:
3+
- Example
4+
- R Language Example
5+
- Package Example
6+
description: |
7+
This example demonstrates use of date parameters.
8+
9+
Dates have different representations in different
10+
programming languages. A client making a request
11+
to execute a program (be that programatically through
12+
something like cURL, or manually through an invocation
13+
user interface) shouldn't have to worry about those
14+
differences.
15+
16+
The format of a date value on a request is therefore
17+
fixed and not dependent on the language in which the
18+
program may have been written.
19+
20+
The HTTP query parameters are converted from strings to
21+
date values by first using `as.numeric` to convert the
22+
value into a numeric, then using the `as.Date` function.
23+
24+
resultFormat: print
25+
resultObjectName: result
26+
27+
parameters:
28+
dateRequired:
29+
label: Date Required
30+
datatype: date
31+
prompt: Enter a date
32+
required: true
33+
dateOptional:
34+
label: Date Optional
35+
datatype: date
36+
prompt: Enter a date

r/DatetimeParameters.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
result <- data.frame(datetimeParm)

r/DatetimeParameters.r.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
label: PKGR07g - Exploring Datetime parameters
2+
categories:
3+
- Example
4+
- R Language Example
5+
- Package Example
6+
description: |
7+
This example demonstrates use of a Datetime parameter.
8+
9+
The HTTP query parameters are converted
10+
from strings by first using `as.numeric` to convert the
11+
value to numeric, then using `asPOSIXct` to convert
12+
the value into a datetime value.
13+
resultFormat: print
14+
resultObjectName: result
15+
16+
parameters:
17+
datetimeParm:
18+
label: Datetime Parm
19+
datatype: datetime
20+
prompt: Enter a datetime
21+
required: true

r/HelloWorld.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
result <- 'Hello World!'

r/HelloWorld.r.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
label: PKGR01 - Hello World
2+
categories:
3+
- Example
4+
- R Language Example
5+
- Package Example
6+
description: |
7+
This is the simplest possible example, a program
8+
that takes no input and produces a fixed output,
9+
'Hello World!'.
10+
11+
By default the result that is returned is the value of
12+
an R object, converted into text in one of a number of
13+
ways: JSON (resultFormat=json), CSV (resultFormat=csv),
14+
tab (tab separated, resultFormat=tab) and print (standard
15+
R print format, resultFormat=print). Here we use JSON.
16+
The object to return is named in the resultObjectName
17+
property.
18+
19+
R objects are always arrays, so in the case of returning
20+
JSON, you will always get a JSON array. In this case
21+
the R object is a vector, so the output is an array of
22+
strings.
23+
24+
The R object is converted to JSON using the jsonlite package,
25+
invoking `jsonlite::toJSON`
26+
programText: |
27+
result <- 'Hello World!'
28+
resultFormat: json
29+
resultObjectName: result

r/InitProgram.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
result <- a*2

r/InitProgram.r.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
label: PKGR09 - Use of initialisation program text
2+
categories:
3+
- Example
4+
- R Language Example
5+
- Package Example
6+
description: |
7+
This example demonstrates use of the initialisation
8+
program text.
9+
10+
The runtime server supports processing multiple requests
11+
through the same R runtime for efficiency. The runtime
12+
environment uses R environment objects to isolate each request
13+
and to avoid invocation of a program poluting other invocations.
14+
15+
A program can specify an initialisation program text that will
16+
be run only once per R runtime. This can be used to load
17+
complex models into memory and avoid the overhead of having to
18+
load a model on each request. The initialisation program text
19+
is run within the context of a separate R environment, and this
20+
environment is then locked to prevent further modification.
21+
22+
This example simply sets a variable in the initialisation text that
23+
is then referenced in the main program text.
24+
25+
Note that the set up of the 'Demo' Environment object in the Hub
26+
is such that a new worker process is created for each request. Since
27+
a new worker process is created for each request, a new R runtime
28+
is created per request anyway, so the initialisation program is
29+
execute for each request. In order to properly see the effect of
30+
the one-time execution of the initialisation program it is necessary
31+
to set the `Idle Timeout` value on the `Default R Processing Engine`
32+
engine of the Demo Environment to a value other than 0.
33+
34+
From the log it is possible to tell whether the initialisation
35+
program has been run or not.
36+
37+
resultFormat: json
38+
resultObjectName: result
39+
initProgramText: |
40+
a <- 42

r/IntegerParameters.r

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
result <- data.frame(
2+
intOptionalNoDefault,
3+
intOptionalDefault42,
4+
intOptionalMax42,
5+
intOptionalMin42,
6+
intRequiredNoDefault,
7+
intRequiredDefault42
8+
)

r/IntegerParameters.r.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
label: PKGR07d - Exploring Integer parameters
2+
categories:
3+
- Example
4+
- R Language Example
5+
- Package Example
6+
description: |
7+
This example demonstrates use of integer parameters
8+
9+
In the case of the SAS language there is no specific
10+
integer type, so all numeric values are passed to
11+
the program as doubles. However an invocation interface
12+
will use the integer type to provide suitable input validation.
13+
14+
The HTTP query parameters are converted from strings to
15+
integer values using the `as.integer` function.
16+
resultFormat: print
17+
resultObjectName: result
18+
parameters:
19+
intOptionalNoDefault:
20+
label: Int Optional No Default
21+
datatype: int
22+
intOptionalDefault42:
23+
label: Int Optional Default 42
24+
datatype: int
25+
defaultValue: 42
26+
intOptionalMax42:
27+
label: Int Optional Max 42
28+
datatype: int
29+
max: 42
30+
intOptionalMin42:
31+
label: Int Optional Min 42
32+
datatype: int
33+
min: 42
34+
intRequiredNoDefault:
35+
label: Int Required No Default
36+
datatype: int
37+
required: true
38+
intRequiredDefault42:
39+
label: Int Required Default 42
40+
datatype: int
41+
defaultValue: 42
42+
required: true
43+

r/PassingParameters.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
result <- paste('Hello', name)

0 commit comments

Comments
 (0)