10. More on Option Typing¶
This chapter is dedicated entirely to typing of job script input options. Some exax-specific types are introduced, followed by a list of common typing examples, and at the end is a set of formal typing rules.
10.1. Additional Option Types¶
Exax can use most of Python’s basic datatypes, and in addition it defines a few more for convenience and stricter type checking.
10.1.1. Additional Option Type: OptionString¶
A common special case is to hava a mandatory string option. The
OptionStrin() function is designed for this.
from accelerator import OptionString
options={
'name1': OptionString,
'name2': OptionString('example'),
}
Both rows mean the same thing. The string 'example' is just that: an
example of what is expected. It is not used as default
value. OptionString does not accept None as input.
10.1.2. Additional Option Type: RequiredOption¶
If an option (of arbitrary type) is mandatory, this can be specified
using the RequiredOption() function:
from accelerator import RequiredOption
options={
'age': RequiredOption(int),
}
Using this definition, execution will stop if age is left
unassigned, and a helpful error message will appear.
By default, it is not okay to set the option to None, but permission
is given by setting none_ok=True:
options={
'maybeage': RequiredOption(int, none_ok=True),
}
in this case is accept an explicit None as well, but it is not
allowed to leave the option unassigned.
10.1.3. Additional Option Type: OptionEnum¶
Alternatively, if the expected values belong to a closed set, one can
use the OptionEnum() function:
from accelerator import OptionEnum
options={
'colour': OptionEnum('red green blue')
# or
'color': OptionEnum(['red', 'green', 'blue'])
}
This will throw an error if the option is not set to one of these three alternatives.
OptionEnum also accepts a none_ok=True parameter, allowing the
parameter to be set explicitly to None as well.
An OptionEnum cannot be left unassigned, unless a default value is
specified, like this
options={
'color': OptionEnum(['red', 'green', 'blue']).green
}
10.1.4. Additional Option Type: JobWithFile¶
It is possible to explicitly specify explicit files from specific jobs
in a build() call using the JobWithFile class. Here is an example
def main(urd):
job1 = urd.build('example1')
job2 = urd.build('example2')
urd.build('example3',
firstfile=job1.withfile('myfile1', sliced=True),
secondfile=job2.withfile('myfile2')
)
where the options definition part of the job script for example3
looks like this
from accelerator import JobWithFile
options=dict(
firstfile=JobWithFile,
secondfile=JobWithFile
)
The .withfile() function takes a filename argument, and in
addition two optional arguments: sliced and extras. The
extras argument is used to pass any kind of information that is
helpful when using the specified file, and sliced tells that the
file is stored in parallel slices.
The files are loaded usinf .load(), like this
def analysis(sliceno):
print(options.firstfile.load(sliceno=sliceno))
def synthesis():
print(options.secondfile.load())
The .load() function assumes that the file is in Python Pickle
format, and there is also an .json_load() function for
JSON-files. To get the full filename of the file, use .filename()
print(options.firstfile.filename(sliceno=3))
print(options.secondfile.filename())
There is also the wrapper around open(), so it is possible to use open()
with(options.firstfile.open(), 'rb') as fh:
data = fh.read()
and have full flexibility.
10.2. Typing Examples¶
from datetime import datetime, date, time, timedelta
from accelerator import OptionString, OptionEnum, RequiredOption
options = dict(
# no type
length=None # accepts anything, default is None
# scalar
length=int # requires intable or None, default is None
length=3 # requires intable or None, default is 3
# string
name=str # requires string or None, default is None
name='foo' # requires string or None, default is 'foo'
name=OptionString # requires non-empty string
# same, but with a guiding example, NOT a default value
name=OptionString('example')
# enums
foo=OptionEnum('a b c') # requires 'a', 'b', or 'c'
foo=OptionEnum(['a', 'b', 'c']) # same
foo=OptionEnum('a b c').a # requires 'a', 'b', or 'c', default is 'a'
foo=OptionEnum('a b c', none_ok=True) # requires 'a', 'b', 'c' or None
# lists and sets
bar=[int] # requires list of intables or None, defaults to []
bar={int} # same, but for set
# dates, times, datetimes, and timedeltas
ts=datetime # a datetimeable object or None
ts=datetime(1972, 1, 1) # with default value
# date, time. timedelta are similar
# types containing types
baz={str: str} # requires dict of string to string or None
baz={str: {str: int}} # requires dicto of string to dict of string to int or None
# Containers with types default to empty containers
frob=RequiredOption(int) # requires an int
frob=RequiredOption(int, none_ok=True) # requires an int or None
)
10.3. Option Typing Formal Rules¶
This section outlines all typing rules. Consider the following example:
options = dict(
# types to input = 3 input = 3.3 input = '3' input='3.3'
a = 3, # int 3 3 3 ERROR
b = int, # int 3 ERROR 3 ERROR
c = 3.14, # float 3.0 3.3 ERROR 3.3
d = '' # str '3' '3.3' '3' '3.3'
Typing may be specified using a class name (i.e.
b = int) or as a value belonging to the intended class (i.e.a = 3).An input is required to be of the correct type. Values are accepted if they are valid input to the type’s constructor. For example
int(3),int(3.3), andint('3')are okay, butint('3.3')is not.Default values
If values are specified, like for
a,c, anddabove, these values are default values and will be used if the option is omitted in thebuild()-call.If the type is specified as a class, like for
b = intabove, the default value will beNone.
Noneis always accepted, unless the type isRequiredOptions(..., none_ok=False)OptionEnum(..., none_ok=False)OptionString()
- Inputs can be left unassigned, unless the type is
RequiredOption()OptionEnum()without a default value.OptionString
Containers.
{}specifies adictetc.