Convert NestedText to Data

nestedtext.loads(content, top='dict', *, source=None, on_dup=None, keymap=None, normalize_key=None, dialect=None)[source]

Loads NestedText from string.

Parameters:
  • content (str) – String that contains encoded data.

  • top (str) – Top-level data type. The NestedText format allows for a dictionary, a list, or a string as the top-level data container. By specifying top as “dict”, “list”, or “str” you constrain both the type of top-level container and the return value of this function. By specifying “any” you enable support for all three data types, with the type of the returned value matching that of top-level container in content. As a short-hand, you may specify the dict, list, str, and any built-ins rather than specifying top with a string.

  • source (str or Path) – If given, this string is attached to any error messages as the culprit. It is otherwise unused. Is often the name of the file that originally contained the NestedText content.

  • on_dup (str or func) –

    Indicates how duplicate keys in dictionaries should be handled. Specifying “error” causes them to raise exceptions (the default behavior). Specifying “ignore” causes them to be ignored (first wins). Specifying “replace” results in them replacing earlier items (last wins). By specifying a function, the keys can be de-duplicated. This call-back function returns a new key and takes two arguments:

    key:

    The new key (duplicates an existing key).

    state:

    A dictionary containing other possibly helpful information:

    dictionary:

    The entire dictionary as it is at the moment the duplicate key is found. You should not change it.

    keys:

    The keys that identify the dictionary.

    This dictionary is created as loads is called and deleted as it returns. Any values placed in it are retained and available on subsequent calls to this function during the load operation.

    This function should return a new key. If the key duplicates an existing key, the value associated with that key is replaced. If None is returned, this key is ignored. If a KeyError is raised, the duplicate key is reported as an error.

    Be aware that key de-duplication occurs after key normalization. As such you should generate keys during de-duplication that are consistent with your normalization scheme.

  • keymap (dict) – Specify an empty dictionary or nothing at all for the value of this argument. If you give an empty dictionary it will be filled with location information for the values that are returned. Upon return the dictionary maps a tuple containing the keys for the value of interest to the location of that value in the NestedText source document. The location is contained in a Location object. You can access the line and column number using the Location.as_tuple() method, and the line that contains the value annotated with its location using the Location.as_line() method.

  • normalize_key (func) – A function that takes two arguments; the original key for a value and the tuple of normalized keys for its parent values. It then transforms the given key into the desired normalized form. Only called on dictionary keys, so the key will always be a string.

  • dialect (str) –

    Specifies support for particular variations in NestedText.

    In general you are discouraged from using a dialect as it can result in NestedText documents that are not compliant with the standard.

    The following deviant dialects are supported.

    support inlines:

    If “i” is included in dialect, support for inline lists and dictionaries is dropped. The default is “I”, which enables support for inlines. The main effect of disabling inlines in the load functions is that keys may begin with [ or {.

Returns:

The extracted data. The type of the return value is specified by the top argument. If top is “any”, then the return value will match that of top-level data container in the input content. If content is empty, an empty data value of the type specified by top is returned. If top is “any” None is returned.

Raises:

NestedTextError – if there is a problem in the NextedText document.

Examples

A NestedText document is specified to loads in the form of a string:

>>> import nestedtext as nt

>>> contents = """
... name: Kristel Templeton
... gender: female
... age: 74
... """

>>> try:
...     data = nt.loads(contents, "dict")
... except nt.NestedTextError as e:
...     e.terminate()

>>> print(data)
{'name': 'Kristel Templeton', 'gender': 'female', 'age': '74'}

loads() takes an optional argument, source. If specified, it is added to any error messages. It is often used to designate the source of NestedText document. For example, if contents were read from a file, source would be the file name. Here is a typical example of reading NestedText from a file:

>>> filename = "examples/duplicate-keys.nt"
>>> try:
...     with open(filename, encoding="utf-8") as f:
...         addresses = nt.loads(f.read(), source=filename)
... except nt.NestedTextError as e:
...     print(e.render())
examples/duplicate-keys.nt, 5: duplicate key: name.
       4 ❬name:❭
       5 ❬name:❭

Notice in the above example the encoding is explicitly specified as “utf-8”. NestedText files should always be read and written using utf-8 encoding.

The following examples demonstrate the various ways of handling duplicate keys:

>>> content = """
... key: value 1
... key: value 2
... key: value 3
... name: value 4
... name: value 5
... """

>>> print(nt.loads(content))
Traceback (most recent call last):
...
nestedtext.nestedtext.NestedTextError: 3: duplicate key: key.
       2 ❬key: value 1❭
       3 ❬key: value 2❭


>>> print(nt.loads(content, on_dup="ignore"))
{'key': 'value 1', 'name': 'value 4'}

>>> print(nt.loads(content, on_dup="replace"))
{'key': 'value 3', 'name': 'value 5'}

>>> def de_dup(key, state):
...     if key not in state:
...         state[key] = 1
...     state[key] += 1
...     return f"{key} — #{state[key]}"

>>> print(nt.loads(content, on_dup=de_dup))
{'key': 'value 1', 'key — #2': 'value 2', 'key — #3': 'value 3', 'name': 'value 4', 'name — #2': 'value 5'}
nestedtext.load(f, top='dict', *, source=None, on_dup=None, keymap=None, normalize_key=None, dialect=None)[source]

Loads NestedText from file or stream.

Is the same as loads() except the NextedText is accessed by reading a file rather than directly from a string. It does not keep the full contents of the file in memory and so is more memory efficient with large files.

Parameters:
  • f (str, os.PathLike, io.TextIOBase, collections.abc.Iterator) – The file to read the NestedText content from. This can be specified either as a path (e.g. a string or a pathlib.Path), as a text IO object (e.g. an open file, or 0 for stdin), or as an iterator. If a path is given, the file will be opened, read, and closed. If an IO object is given, it will be read and not closed; utf-8 encoding should be used.. If an iterator is given, it should generate full lines in the same manner that iterating on a file descriptor would.

  • kwargs – See loads() for optional arguments.

Returns:

The extracted data. See loads() description of the return value.

Raises:
  • NestedTextError – if there is a problem in the NextedText document.

  • OSError – if there is a problem opening the file.

Examples

Load from a path specified as a string:

>>> import nestedtext as nt
>>> print(open("examples/groceries.nt").read())
groceries:
  - Bread
  - Peanut butter
  - Jam


>>> nt.load("examples/groceries.nt")
{'groceries': ['Bread', 'Peanut butter', 'Jam']}

Load from a pathlib.Path:

>>> from pathlib import Path
>>> nt.load(Path("examples/groceries.nt"))
{'groceries': ['Bread', 'Peanut butter', 'Jam']}

Load from an open file object:

>>> with open("examples/groceries.nt") as f:
...     nt.load(f)
...
{'groceries': ['Bread', 'Peanut butter', 'Jam']}