Suppose you have a file called config.ini
like so…
[META]
version = 0.0.1
name = mnist
root = /home/me/projects/${META.name}
description = This is a sample
config file with a multiline
description. These are useful for
project descriptions/changelog/devnotes etc...
[Data]
source = https://files.fast.ai/data/examples/mnist_tiny.tgz
root = ${META.root}/data/
[misc]
x = 1
y = 20
z = float(${x}*${y}**2)
a = ['hello','hi','how','are','you', ${x}*${z}*${y}]
b = {"hi": 1, "hello": 2}
[load]
[load.test]
@load = print_root_location
root = ${Data.root}
[load.csv]
@load = load_csv_function
root = ${Data.root}
[load.json]
@load = load_json_class
root = ${Data.root}
You can load it up as an AttrDict
config = parse("/tmp/config.ini" )
assert config.META.version == "0.0.1"
assert config.META.root == "/home/me/projects/mnist"
assert isinstance (config.misc.b, AttrDict), type (config.project.data.b)
assert isinstance (config.misc.a, L)
Notice, how the ${}
variables got resolved.
Not just that, the varaible z
got computed on the fly.
Not just that, some of the variables like list
and dict
got resolved into their respective python data structures.
{
"Data" : {
"root" : "/home/me/projects/mnist/data/" ,
"source" : "https://files.fast.ai/data/examples/mnist_tiny.tgz"
} ,
"META" : {
"description" : "This is a sample\nconfig file with a multiline\ndescription. These are useful for\nproject
descriptions/changelog/devnotes etc..." ,
"name" : "mnist" ,
"root" : "/home/me/projects/mnist" ,
"version" : "0.0.1"
} ,
"load" : {
"csv" : {
"@load" : null,
"root" : "/home/me/projects/mnist/data/"
} ,
"json" : {
"@load" : "load_json_class" ,
"root" : "/home/me/projects/mnist/data/"
} ,
"test" : {
"@load" : "print_root_location" ,
"root" : "/home/me/projects/mnist/data/"
}
} ,
"misc" : {
"a" : [
"hello" ,
"hi" ,
"how" ,
"are" ,
"you" ,
8000.0
] ,
"b" : {
"hello" : 2 ,
"hi" : 1
} ,
"x" : 1 ,
"y" : 20 ,
"z" : 400.0
}
}
print (config.META.description)
This is a sample
config file with a multiline
description. These are useful for
project descriptions/changelog/devnotes etc...
You can also register/call python functions/callables/classes/objects to strings by running
registry.create("load" )
@registry.load.register ("print_root_location" )
def printer(root):
return root
@registry.load.register ("load_csv_function" )
def _load_csv_function(root):
def load_csv_function(file ):
return f"Loading file from { root} / { file } "
return load_csv_function
@registry.load.register ("load_json_class" )
class JsonLoader:
def __init__ (self , root):
self .root = root
def __call__ (self , file ):
assert file .endswith("json" )
return f"Loading file from { self . root} / { file } "
… and resolve them on parse
config = parse_and_resolve("/tmp/config.ini" )
'/home/me/projects/mnist/data/'
config.load.csv(file = "file.csv" )
'Loading file from /home/me/projects/mnist/data//file.csv'
config.load.json(file = "file.json" )
'Loading file from /home/me/projects/mnist/data//file.json'