Confectioner API

Core API

confectioner.core.shop(_recipe: str, _where: str | None = None, _strict: bool = True, **kwargs) List[str]

Using a recipe, find the appropriate ingredient files

From the recipe file, find ingredient file that match the passed kwargs. All other arguments are prefixed with underscores to avoid clashes with the keys of the recipe file.

Parameters:
  • _recipe (str) – A recipe file, either YAML or JSON

  • _where (str | None, optional) – The parent directory of the recipe file. If omitted, the current working directory is used

  • _strict (bool, optional) – If True (default) entries in the recipe only match when all keys are present and matching in kwargs. If False, keys not provided are assumed to match. For example: - day: friday - mood: angry would when passed (day=’friday’, _strict=False), but not (day=’friday’, _strict=False)

  • **kwargs – Query arguments to match against entries in the recipe

Returns:

A list of ingredient files from the recipe that match the query

Return type:

List[str]

confectioner.core.prep(ingredients: List[str]) List[Dict[str, Any]]

Given a list of ingredient files, load them as dictionaries

Parameters:

ingredients (List[str]) – A list of ingredient files

Returns:

A list of dictionaries, each one corresponding to an ingredient file

Return type:

List[Dict[str, Any]]

confectioner.core.mix(dish: dict, ingredient: dict, dicts: Literal['overwrite', 'merge'] = 'merge', lists: Literal['overwrite', 'append'] = 'overwrite') dict

Given two ingredients (dicts), mix (recursively merge) them.

Parameters:
  • dish (dict) – The “so-far”; what ingredient will be mixed into

  • ingredient (dict) – The new ingredient being added. If any entries exist in both this and dish, then the entry here is used.

  • dicts (Literal['overwrite', 'merge'], optional) – How to handle subdicts. When ‘overwrite’, a subdict from ingredient will completely clobber the corresponding entry in dish. When merge, the two dicts will be recursed into and merged.

  • lists (Literal['overwrite', 'append'], optional) – How to handle lists. When overwrite, a list from ingredient will completely clobber the corresponding entry in dish. When append, if both entries are lists then the list from ingredient will be appended to the list from dish

Returns:

A new dish (dict) with the added ingredient

Return type:

dict

confectioner.core.bake(_recipe: str | List[Dict[str, Any]], *, _reverse: bool = False, _dicts: Literal['overwrite', 'merge'] = 'merge', _lists: Literal['overwrite', 'append'] = 'overwrite', _resolve: bool = True, _eager: bool = False, _report: bool | Callable = False, _where: str | None = None, _strict: bool = True, **kwargs) Dict[str, Any]
confectioner.core.bake(_recipe: List[Dict[str, Any]], *, _reverse: bool = False, _dicts: Literal['overwrite', 'merge'] = 'merge', _lists: Literal['overwrite', 'append'] = 'overwrite', _resolve: bool = True, _eager: bool = False, _report: bool | Callable = False, **kwargs) Dict[str, Any]
confectioner.core.bake(_recipe: str, *, _reverse: bool = False, _dicts: Literal['overwrite', 'merge'] = 'merge', _lists: Literal['overwrite', 'append'] = 'overwrite', _where: str | None = None, _strict: bool = True, _resolve: bool = True, _eager: bool = False, **kwargs) Dict[str, Any]

Bake (merge) a set of ingredients into a finished product (dictionary).

Bake can either do the entire confecting process from end to end (shop, prep, bake), or can take the list of prepped ingredient dictionaries and just do the final step (recursively merge). All arguments other than the first one (_recipe) are keyword-only. All arguments are prefixed with underscores to avoid clashes with the keys of the recipe file.

Parameters:
  • _recipe (str | List[Dict[str, Any]]) – Either a path to a recipe file or the list of dicts output by prep

  • _reverse (bool, optional) – If False (default) ingredients at end of list take precedence. If True, ingredients at top take precedence.

  • _dicts (Literal['overwrite', 'merge'], optional) – See (confectioner.core.mix())

  • _lists (Literal['overwrite', 'append'], optional) – See (confectioner.core.mix())

  • _resolve (bool, optional) – If True (default) resolve ony entries with templating syntax.

  • _eager (bool, optional) – If True (default False) eagerly resolve templating syntax. (i.e. if config B is being mixed into config A, resolve A on itself before mixing B into A)

  • _report (bool | Callable, optional) – Should any informational messages be logged. Boolean or a callable that performs the logging (such as print)

  • _where (str | None, optional) – See (confectioner.core.shop()). Ignored if _recipe is not a filepath.

  • _strict (bool, optional) – See (confectioner.core.shop()) Ignored if _recipe is not a filepath.

  • **kwargs – See (confectioner.core.shop()) Ignored if _recipe is not a filepath.

Return type:

Dict[str, Any]

class confectioner.baker.Baker(home: str | None = None)

A Baker allows you to call the functions in the core module with a default home directory.

Parameters:

home (str) – The home directory of the baker.

See Also: confectioner.core

File Utilities

confectioner.files.register_reader(protocol: str, reader: Callable[[str], IO], force: bool = False) None

Register a reader for a protocol.

Parameters:
  • protocol (str) – The protocol to register the reader for.

  • reader (Callable[[str], IO]) – The reader function.

  • force (bool, optional) – If True, override an existing reader for that protocol (if it exists). If False (default), raise a ValueError.

Return type:

None

confectioner.files.register_loader(extension: str, loader: Callable[[IO], Any], force: bool = False) None

Register a loader for a file extension.

Parameters:
  • extension (str) – The file extension to register the loader for.

  • loader (Callable[[IO], Any]) – The loader function.

  • force (bool, optional) – If True, override an existing loader for that file extension (if it exists). If False (default), raise a ValueError.

Return type:

None

Templating Utilities

confectioner.templating.resolve(o: Any, options: Mapping[str, Any] | None = None, *, report: _ResolveReporter | bool | Callable = False, remove_escapes: bool = True) Any

Resolve templated values (possibly recursively).

Parameters:
  • o (Any) – The object to resolve.

  • options (Mapping[str, Any] | None, optional) – The options to lookup resolved values in. If None, use o as the options.

  • report (_ResolveReporter | bool | Callable, optional) – If True, print a message for each resolved value. If False, do not print messages. If a callable, call the callable for each resolved value.

  • remove_escapes (bool, optional) – If True (default), remove escape characters from resolved strings.

Returns:

The resolved object.

Return type:

Any

confectioner.templating.get_dotted_key(dotted: str, options: Mapping[str, Any] | list) Any

Get a nested value from a dictionary or list using a dotted key.

Parameters:
  • dotted (str) – The dotted key to lookup.

  • options (Mapping[str, Any] | list) – The dictionary or list to lookup the dotted key in.

Returns:

The value at the dotted key.

Return type:

Any

confectioner.templating.set_dotted_key(dotted: str, val: Any, options: Dict[str, Any]) None

Set a nested value in a dictionary or list using a dotted key.

Parameters:
  • dotted (str) – The dotted key to set.

  • options (Dict[str, Any]) – The dictionary or list to set the dotted key in.

Return type:

None

confectioner.templating.dotted_key_exists(dotted: str, options: Mapping[str, Any] | list) bool

Check if a dotted key exists in a dictionary or list.

Parameters:
  • dotted (str) – The dotted key to check.

  • options (Mapping[str, Any] | list) – The dictionary or list to check the dotted key in.

Returns:

True if the dotted key exists, False otherwise.

Return type:

bool

confectioner.templating.find_template_keys(o: str) Set[str]

Find all template keys in a string.

Parameters:

o (str) – The string to search.

Returns:

The set of template keys.

Return type:

Set[str]