Parsers
What’s a parser?
All parsers are functions that take a string value and return a parsed instance.
For example:
int
takes a string value and returns an int.parse_class
takes a string value that’s a dotted Python path and returns the class objectListOf(str)
takes a string value that uses a comma delimiter and returns a list of strings
Note
When specifying configuration options, the default value must always be a string. When Everett can’t find a value for a requested key, it will take the default value and pass it through the parser. Because parsers always take a string as input, the default value must always be a string.
Good:
debug = config("debug", parser=bool, default="false")
^^^^^^^
Bad:
debug = config("debug", parser=bool, default=False)
^^^^^ Not a string
Available parsers
Python types like str, int, float, pathlib.Path
Python types can convert strings to Python values. You can use these as parsers:
str
int
float
decimal
pathlib.Path
bools
Everett provides a special bool parser that handles more descriptive values for “true” and “false”:
true: t, true, yes, y, on, 1 (and uppercase versions)
false: f, false, no, n, off, 0 (and uppercase versions)
- everett.manager.parse_bool(val)
Parse a bool value.
Handles a series of values, but you should probably standardize on “true” and “false”.
>>> from everett.manager import parse_bool >>> parse_bool("y") True >>> parse_bool("FALSE") False
- Parameters:
val (str) –
- Return type:
bool
classes
Everett provides a everett.manager.parse_class
that takes a string
specifying a module and class and returns the class.
- everett.manager.parse_class(val)
Parse a string, imports the module and returns the class.
>>> from everett.manager import parse_class >>> parse_class("everett.manager.Option") <class 'everett.manager.Option'>
- Parameters:
val (str) –
- Return type:
Any
data size
Everett provides a everett.manager.parse_data_size
that takes a string
specifying an amount and a data size metric (e.g. kb, kib, tb, etc) and returns
the amount of bytes that represents.
- everett.manager.parse_data_size(val)
Parse a string denoting a data size into an int of bytes.
This allows you to parse data sizes with a number and then the metric. Examples:
10b - 10 bytes
100kb - 100 kilobytes = 100 * 1000
40gb - 40 gigabytes = 40 * 1000^3
23gib - 40 gibibytes = 23 * 1024^3
Supported metrics:
b - bytes
decimal:
kb - kilobytes
mb - megabytes
gb - gigabytes
tb - terabytes
pb - petabytes
binary:
kib - kibibytes
mib - mebibytes
gib - gibibytes
tib - tebibytes
pib - pebibytes
The metrics are not case sensitive–it supports upper, lower, and mixed case.
>>> from everett.manager import parse_data_size >>> parse_data_size("40_000_000") 40000000 >>> parse_data_size("40gb") 40000000000 >>> parse_data_size("20KiB") 20480
- Parameters:
val (str) –
- Return type:
Any
time period
Everett provides a everett.manager.parse_time_period
that takes a string
specifying a period of time and returns the total number of seconds represented
by that period.
- everett.manager.parse_data_size(val)
Parse a string denoting a data size into an int of bytes.
This allows you to parse data sizes with a number and then the metric. Examples:
10b - 10 bytes
100kb - 100 kilobytes = 100 * 1000
40gb - 40 gigabytes = 40 * 1000^3
23gib - 40 gibibytes = 23 * 1024^3
Supported metrics:
b - bytes
decimal:
kb - kilobytes
mb - megabytes
gb - gigabytes
tb - terabytes
pb - petabytes
binary:
kib - kibibytes
mib - mebibytes
gib - gibibytes
tib - tebibytes
pib - pebibytes
The metrics are not case sensitive–it supports upper, lower, and mixed case.
>>> from everett.manager import parse_data_size >>> parse_data_size("40_000_000") 40000000 >>> parse_data_size("40gb") 40000000000 >>> parse_data_size("20KiB") 20480
- Parameters:
val (str) –
- Return type:
Any
ListOf(parser)
Everett provides a special everett.manager.ListOf
parser which
parses a list of some other type. For example:
ListOf(str) # comma-delimited list of strings
ListOf(int) # comma-delimited list of ints
- everett.manager.ListOf(parser, delimiter=',')
Parse a comma-separated list of things.
After delimiting items, this strips the whitespace at the beginning and end of each string. Then it passes each string into the parser to get the final value.
>>> from everett.manager import ListOf >>> ListOf(str)('') [] >>> ListOf(str)('a,b,c,d') ['a', 'b', 'c', 'd'] >>> ListOf(int)('1,2,3,4') [1, 2, 3, 4] >>> ListOf(str)('1, 2 ,3,4') ['1', '2', '3', '4']
Note: This doesn’t handle quotes or backslashes or any complicated string parsing.
For example:
>>> ListOf(str)('"a,b",c,d') ['"a', 'b"', 'c', 'd']
- Parameters:
parser (Callable) –
delimiter (str) –
dj_database_url
Everett works with dj-database-url. The dj_database_url.parse
function takes a string and returns a Django database connection value.
For example:
import dj_database_url
from everett.manager import ConfigManager
config = ConfigManager.basic_config()
DATABASE = {
"default": config("DATABASE_URL", parser=dj_database_url.parse)
}
That’ll pull the DATABASE_URL
value from the environment (it throws an
error if it’s not there) and runs it through dj_database_url
which parses
it and returns what Django needs.
With a default:
import dj_database_url
from everett.manager import ConfigManager
config = ConfigManager.basic_config()
DATABASE = {
"default": config(
"DATABASE_URL", default="sqlite:///my.db", parser=dj_database_url.parse
)
}
Note
To use dj-database-url, you’ll need to install it separately. Everett doesn’t depend on it or require it to be installed.
django-cache-url
Everett works with django-cache-url.
For example:
import django_cache_url
from everett.manager import ConfigManager
config = ConfigManager.basic_config()
CACHES = {
"default": config("CACHE_URL", parser=django_cache_url.parse)
}
That’ll pull the CACHE_URL
value from the environment (it throws an error if
it’s not there) and runs it through django_cache_url
which parses it and
returns what Django needs.
With a default:
import django_cache_url
from everett.manager import ConfigManager
config = ConfigManager.basic_config()
CACHES = {
"default": config(
"CACHE_URL", default="locmem://myapp", parser=django_cache_url.parse
)
}
Note
To use django-cache-url, you’ll need to install it separately. Everett doesn’t require it to be installed.
Implementing your own parsers
Implementing your own parser should be straight-forward. Parsing functions always take a string and return the Python value you need.
If the value is not parseable, the parsing function should raise a ValueError
.
For example, say we wanted to implement a parser that returned yes/no/no-answer or a parser class that’s line delimited:
# parser_examples.py
from everett.manager import ConfigManager, get_parser
def parse_ynm(val):
"""Returns True, False or None (empty string)"""
val = val.strip().lower()
if not val:
return None
return val[0] == "y"
config = ConfigManager.from_dict(
{"NO_ANSWER": "", "YES": "yes", "ALSO_YES": "y", "NO": "no"}
)
assert config("no_answer", parser=parse_ynm) is None
assert config("yes", parser=parse_ynm) is True
assert config("also_yes", parser=parse_ynm) is True
assert config("no", parser=parse_ynm) is False
class Pairs(object):
def __init__(self, val_parser):
self.val_parser = val_parser
def __call__(self, val):
val_parser = get_parser(self.val_parser)
out = []
for part in val.split(","):
k, v = part.split(":")
out.append((k, val_parser(v)))
return out
config = ConfigManager.from_dict({"FOO": "a:1,b:2,c:3"})
assert config("FOO", parser=Pairs(int)) == [("a", 1), ("b", 2), ("c", 3)]