1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import List
from box.box import Box
class ConfigBox(Box):
"""
Modified box object to add object transforms.
Allows for build in transforms like:
cns = ConfigBox(my_bool='yes', my_int='5', my_list='5,4,3,3,2')
cns.bool('my_bool') # True
cns.int('my_int') # 5
cns.list('my_list', mod=lambda x: int(x)) # [5, 4, 3, 3, 2]
"""
_protected_keys = dir(Box) + ["bool", "int", "float", "list", "getboolean", "getfloat", "getint"]
def __getattr__(self, item):
"""
Config file keys are stored in lower case, be a little more
loosey goosey
"""
try:
return super().__getattr__(item)
except AttributeError:
return super().__getattr__(item.lower())
def __dir__(self) -> List[str]:
return super().__dir__() + ["bool", "int", "float", "list", "getboolean", "getfloat", "getint"]
def bool(self, item, default=None):
"""
Return value of key as a boolean
:param item: key of value to transform
:param default: value to return if item does not exist
:return: approximated bool of value
"""
try:
item = self.__getattr__(item)
except AttributeError as err:
if default is not None:
return default
raise err
if isinstance(item, (bool, int)):
return bool(item)
if isinstance(item, str) and item.lower() in ("n", "no", "false", "f", "0"):
return False
return True if item else False
def int(self, item, default=None):
"""
Return value of key as an int
:param item: key of value to transform
:param default: value to return if item does not exist
:return: int of value
"""
try:
item = self.__getattr__(item)
except AttributeError as err:
if default is not None:
return default
raise err
return int(item)
def float(self, item, default=None):
"""
Return value of key as a float
:param item: key of value to transform
:param default: value to return if item does not exist
:return: float of value
"""
try:
item = self.__getattr__(item)
except AttributeError as err:
if default is not None:
return default
raise err
return float(item)
def list(self, item, default=None, spliter: str = ",", strip=True, mod=None):
"""
Return value of key as a list
:param item: key of value to transform
:param mod: function to map against list
:param default: value to return if item does not exist
:param spliter: character to split str on
:param strip: clean the list with the `strip`
:return: list of items
"""
try:
item = self.__getattr__(item)
except AttributeError as err:
if default is not None:
return default
raise err
if strip:
item = item.lstrip("[").rstrip("]")
out = [x.strip() if strip else x for x in item.split(spliter)]
if mod:
return list(map(mod, out))
return out
# loose configparser compatibility
def getboolean(self, item, default=None):
return self.bool(item, default)
def getint(self, item, default=None):
return self.int(item, default)
def getfloat(self, item, default=None):
return self.float(item, default)
def __repr__(self):
return f"{self.__class__.__name__}({str(self.to_dict())})"
def copy(self):
return ConfigBox(super().copy())
def __copy__(self):
return ConfigBox(super().copy())
|