Config¶
The Config class allows user and API settings to be saved and updated using a configuration file. A config class is not required by DAPT but using one provides several advantages. First, it makes initializing a class much easier as each class can pull required attributes from a config. Second, API credentials can be stored in a config, allowing credentials to be kept in one place. Third, by allowing API tokens to be stored, there is no need to reauthenticate a service (assuming the tokens are still valid). Finally, it provides a way for users to have their own settings file.
Configuration files use JSON (JavaScript Object Notation) format. A detailed understanding of JSON is not required, but the basics should be understood. There are two main components of JSON files: key/value pairs (objects) and arrays/lists. When using key/value pairs, the pairs must be surrounded by curly braces and seporated with commas. Objects are seporated by colons (:) and keys must be sourounded by quotes. Values can be objects, arrays, strings, numbers, booleans, or null. Bellow is a sample JSON file that could be used by DAPT.
{
"performed-by":"Ben",
"num-of-runs":-1,
"testing-variables":
{
"executable-path":"./main",
"output-path":"output/"
}
}
The performed-by
and num-of-runs
keys are reserved DAPT fields.
These cause DAPT to add additional information during tests, initiate classes automatically,
and change the testing behavior. The list of reserved fields and their behaviors are shown
bellow. The testing-variables
key has and object in it that might be used for a specific
testing parameters. They name of this key does not matter as long as it is not a reserved field.
To see how the Config class is used checkout the usage section or class
documentation.
Fields¶
There are many key-value pairs which can be used in the configuration to make DAPT behave in a particular way. These keys are called fields. These fields are reserved and should not be used in your config file unless you expect DAPT to use them. A list of top level fields is provided below.
Fields | Description |
---|---|
num-of-runs (int) |
The number of paramater sets to run. |
performed-by (str) |
The username of the person that ran the parameter set. |
last-test (str) |
The last test id that was run. If a test exits before completeing, it will be re-ran. |
computer-strength
(int) |
Only run tests on computers with sufficient power. The
parameter set will only be run if this value is greater than
or equal that of the parameter sets computer-strength . |
google-sheets (str) |
Values used by the Google Sheets storage API. |
delimited-file (str) |
Values used by the Delimited file database class. |
box (str) |
Values used by the Box storage API. |
pretty-save (bool) |
Output the config in a ~pretty~ way. True by default. |
Some of these fields are used by other DAPT classes to store values. For example, the
google-sheets
field has many sub-fields that set parameters in the class automatically.
The spreedsheet-id
sub-field sets the spreedsheet ID that should be used as the database.
These sub-fields are not listed above. They are notable, however, because you may accidentally
find one of these sub-fields if you recursively search a config file. If you are worried about
accidentally using one of these fields, the FULL_CONFIG
variable in the
config module contains all
of the config fields.
Usage¶
For these examples, the example JSON shown above is used, stored in a
file named example.json
. To create a Config object the path to the JSON file must be
provided.
>>> config = dapt.Config(path="example.json")
The configuration should be accessed using the get_value()
method. This method will returned
the value of the associated key. Keys can be provided as a string or a list where elements are
the path to the value. The num-or-runs
attribute can be accessed as shown bellow.
>>> config.get_value("num-of-runs")
-1
If you wanted to find the value of output-path
then you specify the path to it.
>>> config.get_value(["testing-variables", "output-path"])
'output/'
Alternatively, the output-path
key can be accessed by using the recursive
flag. This
flag makes the get_value()
method recursively search the JSON tree for the first occupance
of the specified key. This flag will increase the look-up time and may not return the value you
expect if multiple keys with that name are present.
The advantage of using the get_value()
method is that None
will be returned if the value
is not found.
The configuration dictionary can be accessed indirectly by treating the Config object as a dictionary.
>>> config["num-of-runs"]
-1
>>> config["testing-variables"]["output-path"]
'output/'
Using this approach, the length of the dictionary can be accessed using Pythons internal len()
function or any other dict method. The keys of the dictionary can be accessed using the
keys()
method.
Before accessing a value in the config, it is good to check that it exists. This can be done
using the has_value()
method. This method returns True
if there is a non-none value in
the config for the given key. The key and recursive attributes behave the same as with the
get_value()
method. For example, to check that the output-path
key exists you could
run the following and expect a return value of True
.:
>>> config.has_value(["testing-variables", "output-path"])
True
If you checked for the key foo
, then has_value()
would return False
.
To add key-value pairs to the configuration or update values, the update()
method should
be used. This method will allow the configuration to change and save it to the JSON file.
The configuration can be changed in four different ways. First, by providing the key as a string.
Second, by providing the key as an array representing a path to the value. The third method
uses a str
for the string and recursively finds the first occurrence of the key in the config.
Lastly, the configuration can be updated by accessing the dictionary directly. Then update()
can be ran without parameters to save the config. The second and last methods are required to
access nested key-value pairs. All of these methods work to add new data or change values in
the configuration.
>>> config.update(key="performed-by", value="John", recursive=False)
{'performed-by': 'John', 'num-of-runs': -1,
'testing-variables': {'executable-path': './main', 'output-path': 'output/'}}
>>> config.update(key=["testing-variables", "executable-path"], value="main.exe",
recursive=False)
{'performed-by': 'John', 'num-of-runs': -1,
'testing-variables': {'executable-path': 'main.exe', 'output-path': 'output/'}}
>>> config.update(key="output-path", value="save/", recursive=True)
{'performed-by': 'John', 'num-of-runs': -1,
'testing-variables':{'executable-path': 'main.exe', 'output-path': 'save/'}}
>>> config["num-of-runs"] = 3
>>> config.update()
{'performed-by': 'John', 'num-of-runs': 3,
'testing-variables':{'executable-path': 'main.exe', 'output-path': 'save/'}}
When creating a new configuration file, the create()
method can be used. This static method
will create a default configuration file at the path provided. This file contains all of the
possible fields used by DAPT.
>>> dapt.config.Config.create(path="new-config.json")
Configuration files can contain sensitive API credentials or passwords. Storing these in plane
text or publishing configuration files online is unsecure as people can then gain access to your
online services. To combate this you can “safe” the configuration file. The safe()
method
will remove all API credentials from the configuration so the file cannot be used to access your
APIs. Currently, this this process is one-way and the credentials cannot be recovered.
However, in the future this will encrypt the file can be distributed online and unlocked by people
with the correct password.
-
class
dapt.config.
Config
(path='config.json')¶ Bases:
object
Class which loads and allows for editing of a config file.
Parameters: path (string) – path to config file -
static
create
(path='config.json')¶ Creates a config file with the reserved keys inserted. The
DEFAULT_CONFIG
will be used.Parameters: path (string) – path where config file will be written Returns: A Config
object with the newly created default configuration
-
get_value
(key, recursive=False, default=None)¶ Get the first value of the given key or return
None
if one doesn’t exist.Parameters: - key (str or list) – the key (given as a string) or List containing the path to the value
- recursive (bool) – recursively look through the config for the given key. False by default. If recursive is set to True then key must be a string.
- default (obj) – A default value to use if no value can be found. This is
None
by default.
Returns: The value associated to the given key or None if the key is not in the dictionary.
-
has_value
(key, recursive=False)¶ Checks to see if the config contains the key and a value other than None.
Parameters: - key (str or list) – the key (given as a string) or List containing the path to the value
- recursive (bool) – recursively look through the config for the given key. False by default. If recursive is set to True then key must be a string.
Returns: True if the key has a value and it’s not None, False otherwise.
-
keys
()¶ Get the keys from the configuration. This method only returns the keys at the top of the dictionary. It will not return any nested keys.
Returns: A list containing the keys in the dictionary.
-
read
()¶ Reads the file with path set to self.path
Returns: Dictionary of config file
-
static
safe
(path='config.json')¶ Safe config file by removing accessToken and refreshToken.
Parameters: path (string) – path where config file will be writen
-
update
(key=None, value=None, recursive=False)¶ Given a key and associated value, updated the config file. Alternatively, you can give no arguments and the config dict will be saved. You can also do both.
Parameters: - key (str or list) – the key (given as a string) or List containing the path to the value. If None is given then nothing will be updated in the dictionary.
- value (str) – the value associated ot the key.
- recursive (bool) – recursively look through the config for the given key. False by default. If recursive is set to True then key must be a string.
Returns: Dictionary of config file
-
static