-
-
Notifications
You must be signed in to change notification settings - Fork 111
Description
Custom encoders provide a way to have custom objects in the "tree" of stuff that gets rendered to a toml file by allowing the user to provide the item-generation code (aka encoder). The actual recursive tree-traversal encoder used by tomlkit carries through the arguments: _parent (item within which the created item would get inserted) and _sort_keys (just a user option). When encoding only simple values (aka a tree leaf), those parameters don't matter, but in order to write a custom encoder for a dict-like, list-like or tuple-like custom object, those are relevant.
Context: I was writing a sort of "decorated tree" of config values, specifically to keep track of file/line-number of where a particular config value was set, to later render those source locations as comments in the toml config file, next to each config value. I ended up writing this horrible custom encoder:
def traced_item_encoder(traced_item):
if not isinstance(traced_item, TracedItem):
raise tomlkit.ConvertError("Expecting a TracedItem")
# We use a pretty crazy hack here because tomlkit doesn't forward the _parent and _sort_keys
# arguments to the custom encoders, but they are needed to correctly handle dict and list values.
# So, we walk up the stack and pick them out ourselves.
it = tomlkit.item(
traced_item.raw_value,
_parent=inspect.currentframe().f_back.f_locals["_parent"],
_sort_keys=inspect.currentframe().f_back.f_locals["_sort_keys"],
)
if traced_item.origin:
it.comment("ORIGIN: " + traced_item.origin)
return itI'm guessing the solution would be to pass a **kwargs down, since I would assume most custom encoders end up making a call to tomlkit.item eventually.