Configuration Metadata
Configuration metadata uses the standard Rose Configuration Format. It is represented in a directory with the following:
rose-meta.conf
, the main metadata configuration file.opt/
directory (see Optional Configuration).Other files, e.g.:
lib/python/widget/my_widget.py
would be the location of a custom widget.lib/python/macros/my_macro_validator.py
would be the location of a custom macro.etc/
would contain any resources for the logics inlib/python/
, such as an icon for the custom widget.
Rose utilities will search for metadata using the following in order of precedence:
Configuration metadata embedded in the
meta/
directory of a suite or an application.The
--meta-path=PATH
option of relevant commands.The value of the
ROSE_META_PATH
environment variable.The
rose.conf|meta-path
setting (see Site And User Configuration).
Tip
See Appendix: Metadata Location for more details.
The configuration metadata that controls default behaviour will be located in
etc/rose-meta/
within the metomi.rose
Python installation.
Configuration Metadata File
The rose-meta.conf
contains a serialised data structure that is an
unordered map (sections=
) of unordered maps (keys=values
).
The section name in a configuration metadata file should be a unique ID to
the relevant configuration setting. The syntax of the ID is
SECTION-NAME=OPTION-NAME
or just SECTION-NAME
. For example,
env=MY_ENV_NAME
is the ID of an environment variable called
MY_ENV_NAME
in an application configuration file;
namelist:something_nl=variable_name1
is the ID of a
namelist variable called variable_name1
in a namelist group called
something_nl
in an application configuration file. If the configuration
metadata applies to a section in a configuration file, the ID is just the
section name.
Where multiple instances of a section are used in a configuration file,
ending in brackets with numbers, the metadata ID should just be based on the
original section name (for example namelist:extract_control(2)
should be
found in the metadata under namelist:extract_control
).
Finally, the configuration metadata may group settings in namespaces, which
may in turn have common configuration metadata settings. The ID for a
namespace set in the metadata is ns=NAME
, e.g.
ns=env/MyFavouriteEnvironmentVars
.
Metadata Inheritance (Import)
A root level import=MY_COMMAND1/VERSION1 MY_COMMAND2/VERSION2 ...
setting
in the rose-meta.conf
file will tell Rose metadata utilities to
locate the meta keys MY_COMMAND1/VERSION1
, MY_COMMAND2/VERSION2
(and
so on) and inherit their configuration and files if found.
For example, you might have a rose-meta
directory that contains the
following files and directories:
cheese_sandwich/
vn1.5/
rose-meta.conf
vn2.0/
rose-meta.conf
cheese/
vn1.0/
rose-meta.conf
and write an app referencing this rose-meta
directory that looks like
this:
meta=cheese_sandwich/vn2.0
[env]
CHEESE=camembert
SANDWICH_BREAD=brown
This will reference the metadata at rose-meta/cheese_sandwich/vn2.0
.
Now, we can write the rose-meta.conf
file using an import:
import=cheese/vn1.0
[env=SANDWICH_BREAD]
values=white,brown,seeded
which will inherit metadata from metadata from
rose-meta/cheese/vn1.0/rose-meta.conf
.
Metadata Options
The metadata options for a configuration fall into four categories: sorting, values, behaviour and help as outlined below.
- Rose Configuration rose-meta.conf
- Config [SETTING]
A section containing metadata items relating to a particular setting.
SETTING
should be the full name of a configuration containing the name of the section and the name of the setting separated by an equals=
sign e.g:[env=FOO]
would refer to the environment variableFOO
[namelist:foo=BAR]
would refer toBAR
from the namelistfoo
.
Metadata for Sorting
These configuration metadata are used for grouping and sorting the IDs of the configurations.
- Config ns
A forward slash
/
delimited hierarchical namespace for the container of the setting, which overrides the default. The default namespace for the setting is derived from the first part of the ID - by splitting up the section name by colons:
or forward slashes/
. For example, a configuration with an IDnamelist:var_minimise=niter_set
would have the namespacenamelist/var_minimise
. If a namespace is defined for a section, it will become the default for all the settings in that section.The namespace is used by rose config-edit to group settings, so that they can be placed in different pages. A namespace for a section will become the default for all the settings in that section.
Note
You should not assign namespaces to variables in duplicate sections.
- Config sort-key
A character string that can be used as a sort key for ordering an option within its namespace.
It can also be used to order sections and namespaces.
The
sort-key
is used by rose config-edit to group settings on a page. Items with asort-key
will be sorted to the top of a name-space. Items without asort-key
will be sorted after, in ascending order of their IDs.The sorting procedure in pseudo code is a normal ASCII-like sorting of a list of
setting_sort_key + "~" + setting_id
strings. If there is nosetting_sort_key
, null string will be used.For example, the following metadata:
[env=apple] [env=banana] [env=cherry] sort-key=favourites-01 [env=melon] sort-key=do-not-like-01 [env=prune] sort-key=do-not-like-00
would produce a sorting order of
env=prune
,env=melon
,env=cherry
,env=apple
,env=banana
.
Metadata for Values
These configuration metadata are used to define the valid values of a setting. A Rose utility such as rose config-edit can use these metadata to display the correct widget for a setting and to check its input. However, if the value of a setting contains a string that looks like an environment variable, these metadata will normally be ignored.
- Config type
- Default:
raw
The type/class of the setting. The type names are based on the intrinsic Fortran types, such as
integer
andreal
. Currently supported types are:- boolean
example option:
PRODUCE_THINGS=true
description: either
true
orfalse
usage: environment variables, javascript/JSON inputs
- character
example option:
sea_colour='blue'
description: Fortran character type - a single quoted string, single quotes escaped in pairs
usage: Fortran character types
- integer
example option:
num_lucky=5
description: generic integer type
usage: any integer-type input
- logical
example option:
l_spock=.true.
description: Fortran logical type - either
.true.
or.false.
usage: Fortran logical types
- python_boolean
example option:
ENABLE_THINGS=True
description: Python boolean type - either
True
orFalse
usage: Python boolean types
- python_list
description: used to signify a Python-compatible formatted list such as
["Foo", 50, False]
.Warning
This encapsulates
length
, so do not use a separatelength
declaration for this setting.usage: use for inputs that expect a string that looks like a Python list - e.g. Jinja2 list input variables.
- quoted
example option:
js_measure_cloud_mode="laser"
description: a double quoted string, double quotes escaped with backslash
usage: Inputs that require double quotes and allow backslash escaping e.g. javascript/JSON inputs.
- real
example option:
n_avogadro=6.02e23
description: Fortran real number type, generic floating point numbers
usage: Fortran real types, generic floating point numbers.
Note
Scientific notation must use the “e” or “E” format.
comment: Internally implemented within Rose using Python’s floating point specification.
- raw
description: placeholder used in derived type specifications where none of the above types apply
usage: only in derived types
- str_multi
description: for strings containing newline characters.
usage: plain text strings
- spaced_list
description: used to signify a space separated list such as
"Foo" 50 False
.usage: use for inputs that expect a string that contains a number of space separated items - e.g. in
fcm_make
app configs.Note
Not all inputs need to have
type
defined. In some cases usingvalues
orpattern
is better.
A derived type may be defined by a comma
,
separated list of intrinsic types, e.g.integer, character, real, integer
. The default is a raw string.
- Config length
Define the length of an array. If not present, the setting is assumed to be a scalar. A positive integer defines a fixed length array. A colon
:
defines a dynamic length array.Note
You do not need to use
length
if you already havetype=python_list
for a setting.
- Config element-titles
Define a list of comma separated “titles” to appear above array entries. If not present then no titles are displayed.
Note
Where the number of
element-titles
is greater than the length of the array, it will only display titles up to the length of the array. Additionally, where the associated array is longer than the number ofelement-titles
, blank headings will be placed above them.
- Config values
Define a comma
,
separated list of permitted values of a setting (or an element in the setting if it is an array). This metadata overrides thetype
,range
andpattern
metadata.For example, rose config-edit may use this list to determine the widget to display the setting. It may display the choices using a set of radio buttons if the list of values is small, or a drop down combo box if the list of
values
is large. If the list only contains one value, rose config-edit will expect the setting to always have this value, and may display it as a special setting.
- Config value-titles
Define a comma
,
separated list of titles to associate with each of the elements ofvalues
which will be displayed instead of the value. This list should contain the same number of elements as thevalues
entry.For example, given the following metadata:
[env=HEAT] values=0, 1, 2 value-titles=low, medium, high
rose config-edit will display
low
for option value0
,medium
for1
andhigh
for2
.
- Config value-hints
Define a comma
,
separated list of suggested values for a variable as value “hints”, but still allows the user to provide their own override. This is like an auto-complete widget.For example, given the following metadata:
[env=suggested_fruit] value-hints=pineapple,cherry,banana,apple,pear,mango,kiwi,grapes,peach,fig, =orange,strawberry,blackberry,blackcurrent,raspberry,melon,plum
rose config-edit will display possible option values when the user starts typing if they match a suggested value.
- Config range
Specify a range of values. It can either be a simple comma
,
separated list of allowed values, or a logical expression in the Rose metadata mini-language. This metadata is only valid iftype
is eitherinteger
orreal
.A simple list may contain a mixture of allowed numbers and number ranges such as
1, 2, 4:8, 10:
(which means the value can be 1, 2, between 4 and 8 inclusive, or any values greater than or equal to 10.)A logical expression uses the Rose metadata mini-language, using the variable
this
to denote the value of the current setting, e.g.this <-1 and this >1
.Warning
Inter-variable comparisons are not permitted (but see the
fail-if
property below for a way to implement this).
- Config pattern
Specify a regular expression (Python Regular Expressions) to compare against the whole value of the setting.
For example, if we write the following metadata:
[namelist:cheese=country_of_origin] pattern=^"[A-Z].+"$
then we expect all valid values for
country_of_origin
to start with a double quote (^"
), begin with an uppercase letter ([A-Z]
), contain some other characters or spaces (.+
), and end with a quote ("$
).If you have an array variable (for example,
TARTAN_PAINT_COLOURS='blue','red','blue'
) and you want to specify a pattern that each element of the array must match, you can construct a regular expression that repeats and includes commas. For example, if each element in ourTARTAN_PAINT_COLOURS
array must obey the regular expression'red'|'blue'
, then we can write:[env=TARTAN_PAINT_COLOURS] length=: pattern=^('red'|'blue')(?:,('red'|'blue'))*$
- Config fail-if
Specify a logical expression using the Rose mini-language to validate the value of the current setting with respect to other settings. If the logical expression evaluates to true, the system will consider the setting in error.
See the associated setting
warn-if
for raising warnings.The logical expression uses a Python-like syntax (documented in the appendix). It can reference the value of the current setting with the
this
variable and the value of other settings with their IDs. E.g.:[namelist:test=my_test_var] fail-if=this < namelist:test=control_lt_var;
means that an error will be flagged if the numeric value of
my_test_var
is less than the numeric value ofcontrol_lt_var
.fail-if=this != 1 + namelist:test=ctrl_var_1 * (namelist:test=ctrl_var_2 - this);
shows a more complex operation, again with numeric values.
To check array elements, the ID should be expressed with a bracketed index, as in the configuration:
fail-if=this(2) != "'0A'" and this(4) == "'0A'";
Note
With array elements indexing starts from 1.
Array elements can also be checked using
any
andall
. E.g.:fail-if=any(namelist:test=ctrl_array < this); fail-if=all(this == 0);
Similarly, the number of array elements can be checked using
len
. E.g.:fail-if=len(namelist:test=ctrl_array) < this; fail-if=len(this) == 0;
Expressions can be chained together and brackets used:
fail-if=this(4) == "'0A'" and (namelist:test=ctrl_var_1 != "'N'" or namelist:test=ctrl_var_2 != "'Y'" or all(namelist:test=ctrl_arr_3 == 'N'));
Multiple failure conditions can be added, by using a semicolon as the separator - the semicolon is optional for a single statement or the last in a block, but is recommended. Multiple failure conditions are essentially similar to chaining them together with
or
, but the system can process each expression one by one to target the error message.fail-if=this > 0; this % 2 == 1; this * 3 > 100;
You can add a message to the error or warning message to make it clearer by adding a hash followed by the comment at the end of a configuration metadata line:
# Need common divisor for ctrl_array fail-if=any(namelist:test=ctrl_array % this == 0);
When using multiple failure conditions, different messages can be added if they are placed on individual lines:
fail-if=this > 0; # Needs to be less than or equal to 0 this % 2 == 1; # Needs to be odd this * 3 > 100; # Needs to be more than 100/3.
Note
When dividing a real-numbered setting by something, make sure that the expression does not actually divide an integer by an integer - for example,
this / 2
will evaluate as0
ifthis
has a value of1
, but0.5
if it has a value of1.0
. This is a result of Python’s implicit typing.You can get around this by making sure either the numerator or denominator is a real number - e.g. by rewriting it as
this / 2.0
or1.0 * this / 2
.
- Config warn-if
Specify a logical expression using the Rose mini-language to validate the value of the current setting with respect to other settings. If the logical expression evaluates to true, the system will issue a warning. It is a slightly different usage of the
fail-if
functionality which can do things like warn of deprecated content, e.g.:warn-if=True;
would always evaluate
True
and give a warning if the setting is present.See the associated setting
fail-if
for examples of logical expressions that may be added.
Metadata for Behaviour
These metadata are used to define how the setting should behave in different states.
- Config compulsory
A
true
value indicates that the setting should be compulsory. If this flag is not set, the setting is optional.Compulsory sections should be physically present in the configuration at all times. Compulsory options should be physically present in the configuration if their parent section is physically present.
Optional settings can be removed as the user wishes. Compulsory settings may however be triggered ignored (see
trigger
). For example, the rose config-edit may issue a warning if a compulsory setting is not defined. It may also hide a compulsory variable that only has a single permitted value.
- Config trigger
A setting has the following states:
normal
user ignored (stored in the configuration file with a
!
flag, ignored at runtime)logically ignored (stored in the configuration file with a
!!
flag, ignored at runtime)
If a setting is user ignored, the trigger will do nothing. Otherwise:
If the logic for a setting in the trigger is fulfilled, it will cause the setting to be enabled.
If it is not, it will cause the setting to be logically ignored.
The trigger expression is a list of settings triggered by (different values of) this setting. If the values are not given, the setting will be triggered only if the current setting is enabled.
The syntax contains ID-value pairs, where the values part is optional. Each pair must be separated by a semi-colon. Within each pair, any values must be separated from the ID by a colon (
:
) and a space. Values must be formatted in the same way as the settingvalues
defined above (i.e. comma separated).The trigger syntax looks like:
[namelist:trig_nl=trigger_variable] trigger=namelist:dep_nl=A; namelist:dep_nl=B; namelist:value_nl=X: 10; env=Y: 20, 30, 40; namelist:value_nl=Z: 20;
In this example:
When
namelist:trig_nl=trigger_variable
is ignored, all the variables in the trigger expression will be ignored, irrespective of its value.When
namelist:trig_nl=trigger_variable
is enabled,namelist:dep_nl=A
andnamelist:dep_nl=B
will both be enabled, and the other variables may be enabled according to its value:When the value of the setting is not
10
,20
,30
, or40
,namelist:value_nl=X
,env=Y
andnamelist:value_nl=Z
will be ignored.When the value of the setting is
10
,namelist:value_nl=X
will be enabled, butenv=Y
andnamelist:value_nl=Z
will be ignored.When the value of the setting is
20
,env=Y
andnamelist:value_nl=Z
will be enabled, butnamelist:value_nl=X
will be ignored.When the value of the setting is
30
,env=Y
will be enabled, butnamelist:value_nl=X
andnamelist:value_nl=Z
will be ignored.If the value of the setting contains an environment variable-like string, e.g.
${TEN_MULTIPLE}
, all three will be enabled.
Settings mentioned in trigger expressions will have their default state set to ignored unless explicitly triggered. rose config-edit will issue warnings if variables or sections are in the incorrect state when it loads a configuration. Triggering thereafter will work as normal.
Where multiple triggers act on a setting, the setting is triggered only if all triggers are active (i.e. an AND relationship). For example, for the two triggers here:
[env=IS_WATER] trigger=env=IS_ICE: true; [env=IS_COLD] trigger=env=IS_ICE: true;
the setting
env=IS_ICE
is only enabled if bothenv=IS_WATER
andenv=IS_COLD
aretrue
and enabled. Otherwise, it is ignored.The trigger syntax also supports a logical expression using the Rose metadata mini-language, in the same way as the
range
orfail-if
metadata. As withrange
, inter-variable comparisons are disallowed.[env=SNOWFLAKE_SIDES] trigger=env=CUSTOM_SNOWFLAKE_GEOMETRY: this != 6; env=SILLY_SNOWFLAKE_GEOMETRY: this < 2;
In this example, the setting
env=CUSTOM_SNOWFLAKE_GEOMETRY
is enabled ifenv=SNOWFLAKE_SIDES
is enabled and not6
.env=SILLY_SNOWFLAKE_GEOMETRY
is only enabled whenenv=SNOWFLAKE_SIDES
is enabled and less than2
. The logical expression syntax can be used with non-numeric variables in the same way as the fail-if metadata.It is possible to use metadata triggers to trigger file creation, switching on/off as required.
For example, with the following
rose-app.conf
androse-meta.conf
files, file creation is triggered when settingtrigger=file:foo
to.true.
.rose-app.conf
file:[command] default=true [file:foo] source=namelist:foo [namelist:foo] switch=.false.
rose-meta.conf
file:[file:foo] [namelist:foo=switch] type=logical trigger=file:foo: .true.
- Config duplicate
Allow duplicated copies of the setting. This is used for sections where there may be more than one with the same metadata - for example multiple namelist groups of the same name. If this setting is true for a given name, the application configuration will accept multiple namelist groups of this name. rose config-edit may then provide the option to clone or copy a namelist to generate an additional namelist. Otherwise, rose config-edit may issue warning for configuration sections that are found with multiple copies or an index.
- Config macro
Associate a setting with a comma-delimited set of custom macros (but not upgrade macros).
E.g. for a macro class called
FibonacciChecker
in the metadata underlib/python/macros/fib.py
, we may have:macro=fib.FibonacciChecker
This may be used in rose config-edit to visually associate the setting with these macros. If a macro class has both a
transform
and avalidate
method, you can specify which you need by appending the method to the name e.g.:macro=fib.Fibonacci.validate
- Config widget[gui-application]
Indicate that the gui-application (e.g. rose config-edit) should use a special widget to display this setting.
E.g. If we want to use a slider instead of an entry box for a floating point real number.
The widget may take space-delimited arguments which would be specified after the widget name. E.g. to set up a hypothetical table with named columns X, Y, VCT, and Level, we may do:
widget[rose-config-edit]=table.TableWidget X Y VCT Level
You may override to a Rose built-in widget by specifying a full
rose
class path in Python - for example, to always show radiobuttons for an option withvalues
set:widget[rose-config-edit]=rose.config_editor.valuewidget.radiobuttons.RadioButtonsValueWidget
Another useful Rose built-in widget to use is the array element aligning page widget,
metomi.rose.config_editor.pagewidget.table.PageArrayTable
. You can set this for a section or namespace to make sure each n-th variable value element lines up horizontally. For example:[namelist:meal_choices] customers='Athos','Porthos','Aramis','d''Artagnan' entrees='soup','pate','soup','asparagus' main='beef','spaghetti','coq au vin','lamb' petits_fours=.false.,.true.,.false.,.true.
could use the following metadata:
[namelist:meal_choices] widget[rose-config-edit]=rose.config_editor.pagewidget.table.PageArrayTable
to align the elements on the page like this:
customers Athos Porthos Aramis d'Artagnan entrees soup pate soup asparagus main beef spaghetti coq au vin lamb petits_fours .false. .true. .false. .true.
- Config copy-mode
For use with settings in the
rose-suite.info
file.Setting
copy-mode
in the metadata allows for the field to be eithernever
copied or copied with any value associated to beclear
.For example: in a
rose-suite.info
file:[ensemble members] copy-mode=never
Setting the
ensemble members
field to includecopy-mode=never
means that the ensemble members field would never be copied.[additional info] copy-mode=clear
Setting the
additional info
field to includecopy-mode=never
means that the additional info field would be copied, but any value associated with it would be cleared.
Metadata for Help
These metadata provide help for a configuration.
- Config url
A web URL containing help for the setting. For example:
url=http://www.something.com/FOO/view/dev/doc/FOO.html
For example, the rose config-edit will trigger a web browser to display this when a variable name is clicked. A partial URL can be used for variables if the variable’s section or namespace has a relevant parent
url
property to use as a prefix. For example:[namelist:foo] url=https://www.google.com/search [namelist:foo=bar] url=?q=nearest+bar
- Config help
(Long) help for the setting. For example, rose config-edit will use this in a pop-up dialog for a variable. Embedding variable IDs in the help string will allow links to the variables to be created within the pop-up dialog box, e.g.
help=Used in conjunction with namelist:Var_DiagnosticsNL=n_linear_adj_test to do something linear.
Web URLs beginning with
http://
will also be presented as links in the rose config-edit.
- Config description
(Medium) description for the setting. For example, rose config-edit will use this as part of the hover over text.
rose config-edit will also use descriptions set for sections or namespaces as page header text (appears at the top of a panel or page), with clickable ID and URL links as in help. Descriptions set for variables may be automatically shown underneath the variable name in rose config-edit, depending on view options.
- Config title
(Short) title for the setting. For example, rose config-edit can use this specification as the label of a setting, instead of the variable name.
Appendix: Metadata Location
Centralised Rose metadata is referred to with either the
rose-suite.conf|meta
or rose-suite.info|project
settings in a suite configuration. It needs to live in a
system-global-readable location.
Rose utilities will do a path search for metadata using the following in order of precedence:
The
--meta-path=PATH
option of relevant commands.The content of the
ROSE_META_PATH
environment variable.The
rose.conf|meta-path
setting (see Site And User Configuration).
Each of the above settings can be a colon-separated list of paths.
Underneath each directory in the search path should be a hierarchy like the following:
${APP}/HEAD/
${APP}/${VERSION}/
${APP}/versions.py # i.e. the upgrade macros
Note
A rose-suite.info
is likely to have no versions.
Note
In some cases, a number of different executables may share the
same application configuration metadata in which case APP
is given a
name which covers all the uses.
Tip
The Rose team recommend placing metadata in a rose-meta
directory at
the top of a project’s source tree. Central metadata, if any, at the
meta-path
location in the site configuration, should be a collection
of regularly-updated subdirectories from all of the relevant projects’
rose-meta
directories.
For example, a system CHOCOLATE
may have a flat metadata structure
within the repository:
CHOCOLATE/doc/
...
CHOCOLATE/rose-meta/
CHOCOLATE/rose-meta/choc-dark/
CHOCOLATE/rose-meta/choc-milk/
and the system CAFFEINE
may have a hybrid structure, with both flat
and hierarchical components:
CAFFEINE/doc/
...
CAFFEINE/rose-meta/caffeine-guarana/
CAFFEINE/rose-meta/caffeine-coffee/cappuccino/
CAFFEINE/rose-meta/caffeine-coffee/latte/
CAFFEINE/rose-meta/caffeine-tea/yorkshire/
CAFFEINE/rose-meta/caffeine-tea/lapsang/
and a site configuration with:
meta-path=/path/to/rose-meta
We would expect the following directories in /path/to/rose-meta
:
/path/to/rose-meta/caffeine-guarana/
/path/to/rose-meta/caffeine-coffee/
/path/to/rose-meta/caffeine-tea/
/path/to/rose-meta/choc-dark/
/path/to/rose-meta/choc-milk/
with caffeine-coffee
containing subdirectories cappuccino
and
latte
, and caffeine-tea
containing yorkshire
and lapsang
.
Upgrade and Versions
Terminology:
- The HEAD (i.e. development) version
The configuration metadata most relevant to the latest revision of the source tree.
- A named version
The configuration metadata most relevant to a release, or a particular revision, of the software. This will normally be a copy of the HEAD version at a given revision, although it may be updated with some backward compatible fixes.
Each change in the HEAD version that requires an upgrade procedure should introduce an upgrade macro. Each upgrade macro will provide the following information:
A tag of the configuration which can be applied by this macro (i.e. the previous tag).
A tag of the configuration after the transformation.
This allows our system to build up a chain if multiple upgrades need to be applied. The tag can be any name, but will normally refer to the ticket number that introduces the change.
Every new upgrade macro creates a new tagged version. A named version is simply a tagged version for which a copy of the relevant configuration metadata is made available.
Named versions for system releases are typically created at the end of the release process. The associated upgrade macro is typically only required in order to create the new name tag and, therefore, does not normally alter the application configuration.
Application configurations can reference the configuration metadata as follows:
#!cfg
# Refer to the HEAD version
# (typically you wouldn't do this since no upgrade process is possible)
# For flat metadata
meta=my-command
# For hierarchical metadata
meta=/path/to/metadata/my-command/HEAD
# Refer to a named or tagged version in the flat metadata
meta=my-command/8.3
meta=my-command/t123
# Refer to a named or tagged version in the hierarchical metadata
meta=/path/to/metadata/my-command/8.3
If a version is defined then the Rose utilities will first look for the corresponding named version. If this cannot be found then the HEAD version is used and, if an upgrade is available, a warning will be given to indicate that the configuration metadata being used requires upgrade macros to be run. If the version defined does not correspond to a tagged version then a warning will be given.
Note
If a hierarchical structure for the metadata is being used,
the HEAD
tag must be specified explicitly.
When to create named versions
One option is to create a new named version for each release of your system. This makes it easy for users to understand. However, if there is a new release which does not require a change to the metadata then you will still have to create a new copy and force the user to go through a null upgrade which may not be desirable. An alternative is to only create a new named version at releases which require changes. The name then indicates the metadata is relevant for a particular release and all subsequent releases (unless an upgrade macro is available to a later release).
Tip
It is also possible to make any tagged version between releases a named version, but it will usually be better not to. In which case, the user will be using HEAD and will be prompted to upgrade (which is probably what you want if you’re not using a release).
Using development versions of upgrade macros
Users will be able to test out development versions of the upgrade macros by
adding a working copy of the relevant branch into their metadata search path.
However, care must be taken when doing this. Running the upgrade macro will
change the rose-app.conf|meta
setting to refer to the new tag.
If the upgrade macro is
subsequently changed or other upgrade macros are added to the chain prior to
this tag (because they get committed to the trunk first) then this will
result in application configurations which have not gone through the correct
upgrade process. Therefore, when using development versions of the upgrade
macros it is safest to not commit any resulting changes (or to use a branch
of the suite which you are happy to discard).
Metadata Mini-Language
The Rose metadata mini-language supports writing a logical expression in Python-like syntax, using variable IDs to reference their associated values.
Expressions are set as the value of metadata properties such as
rose-meta.conf[SETTING]fail-if
and
rose-meta.conf[SETTING]range
.
The language is a small sub-set of Python - a limited set of operators is supported.
Warning
No built-in object methods, functions, or modules are
supported - neither are control blocks such as if
/for
, statements
such as del
or with
, or defining your own functions or classes.
Anything that requires that kind of power should be in proper Python code
as a macro.
Nevertheless, the language allows considerable power in terms of defining simple rules for variable values.
Operators
The following logical operators are supported:
and # Logical AND
or # Logical OR
not # Logical NOT
The following numeric operators are supported:
+ # add
- # subtract
* # multiply
** # power or exponent - e.g. 2 ** 3 implies 8
/ # divide
// # integer divide (floor) - e.g. 3 // 2 implies 1
% # remainder e.g. 5 % 3 implies 2
The following string operators are supported:
+ # concatenate - e.g. "foo" + "bar" implies "foobar"
* # self-concatenate some number of times - e.g. "foo" * 2 implies "foofoo"
% # formatting - e.g. "foo %s baz" % "bar" implies "foo bar baz"
# Where m, n are integers or expressions that evaluate to integers
# (negative numbers count from the end of the string):
[n] # get nth character from string - e.g. "foo"[1] implies "o"
[m:n] # get slice of string from m to n - e.g. "foobar"[1:5] implies "ooba"
[m:] # get slice of string from m onwards - e.g. "foobar"[1:] implies "oobar"
[:n] # get slice of string up to n - e.g. "foobar"[:5] implies "fooba"
The following comparison operators are supported:
is # Is the same object as (usually used for 'is none')
< # Less than
> # Greater than
== # Equal to
>= # Greater than or equal to
<= # Less than or equal to
!= # Not equal to
The following membership operator is supported:
in # contained in (True/False)
# e.g. "oo" in "foobar" implies True; "foo" in ["bar", "baz"] implies False
# To test for lack of membership, combine with the "not" logical operator:
not in # not contained in, i.e. the opposite to that described above
Tip
The in
operator functions as it does in Python Python in operator.
Note the difference between testing if a setting’s value is equal to some
possibility contained within a collection, for example as in:
place in ['here', 'there'] # i.e: place == 'here' or place == 'there'
and testing if it is a substring, as in:
place in 'there' # place could be 'there', 'here', 'er', 'the', etc.
Note
Operator precedence is intended to be the same as Python. However, with the
current choice of language engine, the %
and //
operators may not
obey this - make sure you force the correct behaviour using brackets.
Constants
The following are special constants:
None # Python None
False # Python False
True # Python True
Using Variable IDs
Putting a variable ID in the expression means that when the expression is evaluated, the string value of the variable is cast and substituted into the expression.
For example, if we have a configuration that looks like this:
[namelist:zoo]
num_elephants=2
elephant_mood='peaceful'
and an expression in the configuration metadata:
namelist:zoo=elephant_mood != 'annoyed' and num_elephants >= 2
then the expression would become:
'peaceful' != 'annoyed' and 2 >= 2
If the variable is not currently available (ignored or missing) then the
expression cannot be evaluated. If inter-variable comparisons are not allowed
for the expression’s parent option (such as with
rose-meta.conf[SETTING]trigger
and
rose-meta.conf[SETTING]range
)
then referencing other variable IDs is not allowed.
In this case the expression would be false.
You may use this
as a placeholder for the current variable ID - for
example, the fail-if expression:
[namelist:foo=bar]
fail-if=namelist:foo=bar > 100 and namelist:foo=bar % 2 == 1
is the same as:
[namelist:foo=bar]
fail-if=this > 100 and this % 2 == 1
Arrays
The syntax has some special ways of dealing with variable values that are arrays - i.e. comma-separated lists.
You can refer to a single element of the value for a given variable ID
(or this
) by suffixing a number in round brackets - e.g.:
namelist:foo=bar(2)
references the second element in the value for bar
in the section
namelist:foo
. This follows Fortran index numbering and syntax, which
starts at 1 rather than 0, i.e. foo(1)
references the first element in
the array foo
.
If we had a configuration:
[namelist:foo]
bar='a', 'b', 'c', 'd'
namelist:foo=bar(2)
would get substituted in an expression with 'b'
when the expression was evaluated. For example, an expression that contained:
namelist:foo=bar(2) == 'c'
would be evaluated as:
'b' == 'c'
Should you wish to make use of the array length in an expression you can
make use of the len
function, which behaves in the same manner as the
Python len
and Fortran size
equivalents to return the array length.
For example:
len(namelist:foo=bar) > 3
would be expanded to:
4 > 3
and evaluate as true.
There are two other special array functions, any
and all
, which
behave in a similar fashion to their Python and Fortran equivalents, but
have a different syntax.
They allow you to write a shorthand expression within an any()
or
all()
bracket which implies a loop over each array element. For example:
any(namelist:foo=bar == 'e')
evaluates true if any elements in the value of bar
in the section
namelist:foo
are 'e'
. For the above configuration snippet, this
would be expanded before evaluation to be:
'a' == 'e' or 'b' == 'e' or 'c' == 'e' or 'd' == 'e'
Similarly,
all(namelist:foo=bar == 'e')
evaluates true if all elements are 'e'
. Again, with the above
configuration, this would be expanded before proper evaluation:
'a' == 'e' and 'b' == 'e' and 'c' == 'e' and 'd' == 'e'
Internals
Rose uses an external engine to evaluate the raw language string after
variable IDs and any any()
and all()
functions have been substituted
and expanded.
The current choice of engine is Jinja2, which is responsible for the details of the supported Pythonic syntax. This may change.
Warning
Do not use any Jinja2-specific syntax.
Config Editor Ignored Mechanics
This describes the intended behaviour of rose config-edit when there is an ignored state mismatch for a setting - e.g. a setting might be enabled when it should be trigger-ignored.
rose config-edit differs from the strict command line macro equivalent (rose macro) because the Switch Off Metadata mode and accidentally metadata-less configurations need to be presented in a nice way without lots of unnecessary errors. rose config-edit should only report the errors where the state is definitely wrong or makes a material difference to the user.
The table contains error and fixing information for some varieties of ignored state mismatches. The actual situations are considerably more varied, given section-ignoring and latent variables - the table holds the most important varieties.
The State
contains the actual states. The Trigger State
column
contains the trigger-mechanism’s expected states. The states can be:
IT
-!!
trigger ignored
IU
-!
user ignored
E
- (normal)enabled
A subset of possible ignored/enabled states, errors and fixes:
State |
Trigger State |
Compulsory |
Display Error? |
User Options |
Notes |
---|---|---|---|---|---|
|
|
compulsory |
no |
None |
|
|
|
optional |
no |
None |
|
|
|
compulsory |
error |
|
|
|
|
optional |
error |
|
|
|
|
compulsory |
error |
|
|
|
|
optional |
overlook |
|
See [1] |
|
|
compulsory |
overlook |
None |
See [2] |
|
|
optional |
no |
None |
|
|
|
compulsory |
error |
|
|
|
|
optional |
no |
|
|
|
|
compulsory |
error |
|
|
|
|
optional |
no |
|
|
|
|
compulsory |
error |
|
|
|
|
optional |
error |
|
|
|
|
compulsory |
no |
None |
|
|
|
optional |
no |
|
|
|
|
compulsory |
no |
None |
|
|
|
optional |
no |
|