@@ -147,6 +147,7 @@ class Box(dict):
147147 :param default_box: Similar to defaultdict, return a default value
148148 :param default_box_attr: Specify the default replacement.
149149 WARNING: If this is not the default 'Box', it will not be recursive
150+ :param default_box_none_transform: When using default_box, treat keys with none values as absent. True by default
150151 :param frozen_box: After creation, the box cannot be modified
151152 :param camel_killer_box: Convert CamelCase to snake_case
152153 :param conversion_box: Check for near matching keys as attributes
@@ -159,8 +160,8 @@ class Box(dict):
159160
160161 _protected_keys = dir ({}) + ['to_dict' , 'to_json' , 'to_yaml' , 'from_yaml' , 'from_json' , 'from_toml' , 'to_toml' ]
161162
162- def __new__ (cls , * args : Any , box_it_up : bool = False , default_box : bool = False ,
163- default_box_attr : Any = None , frozen_box : bool = False , camel_killer_box : bool = False ,
163+ def __new__ (cls , * args : Any , box_it_up : bool = False , default_box : bool = False , default_box_attr : Any = None ,
164+ default_box_none_transform : bool = True , frozen_box : bool = False , camel_killer_box : bool = False ,
164165 conversion_box : bool = True , modify_tuples_box : bool = False , box_safe_prefix : str = 'x' ,
165166 box_duplicates : str = 'ignore' , box_intact_types : Union [Tuple , List ] = (), ** kwargs : Any ):
166167 """
@@ -172,6 +173,7 @@ def __new__(cls, *args: Any, box_it_up: bool = False, default_box: bool = False,
172173 obj ._box_config .update ({
173174 'default_box' : default_box ,
174175 'default_box_attr' : default_box_attr or cls .__class__ ,
176+ 'default_box_none_transform' : default_box_none_transform ,
175177 'conversion_box' : conversion_box ,
176178 'box_safe_prefix' : box_safe_prefix ,
177179 'frozen_box' : frozen_box ,
@@ -182,15 +184,16 @@ def __new__(cls, *args: Any, box_it_up: bool = False, default_box: bool = False,
182184 })
183185 return obj
184186
185- def __init__ (self , * args : Any , box_it_up : bool = False , default_box : bool = False ,
186- default_box_attr : Any = None , frozen_box : bool = False , camel_killer_box : bool = False ,
187+ def __init__ (self , * args : Any , box_it_up : bool = False , default_box : bool = False , default_box_attr : Any = None ,
188+ default_box_none_transform : bool = True , frozen_box : bool = False , camel_killer_box : bool = False ,
187189 conversion_box : bool = True , modify_tuples_box : bool = False , box_safe_prefix : str = 'x' ,
188190 box_duplicates : str = 'ignore' , box_intact_types : Union [Tuple , List ] = (), ** kwargs : Any ):
189191 super (Box , self ).__init__ ()
190192 self ._box_config = _get_box_config (kwargs .pop ('__box_heritage' , None ))
191193 self ._box_config .update ({
192194 'default_box' : default_box ,
193195 'default_box_attr' : default_box_attr or self .__class__ ,
196+ 'default_box_none_transform' : default_box_none_transform ,
194197 'conversion_box' : conversion_box ,
195198 'box_safe_prefix' : box_safe_prefix ,
196199 'frozen_box' : frozen_box ,
@@ -208,6 +211,8 @@ def __init__(self, *args: Any, box_it_up: bool = False, default_box: bool = Fals
208211 for k , v in args [0 ].items ():
209212 if v is args [0 ]:
210213 v = self
214+ if v is None and self ._box_config ['default_box' ] and self ._box_config ['default_box_none_transform' ]:
215+ continue
211216 self [k ] = v
212217 elif isinstance (args [0 ], Iterable ):
213218 for k , v in args [0 ]:
0 commit comments