diff --git a/doc/common_mistakes.rst b/doc/common_mistakes.rst index db04ba8..5241c48 100644 --- a/doc/common_mistakes.rst +++ b/doc/common_mistakes.rst @@ -1,9 +1,18 @@ +.. hide: + + >>> from inform import Inform + >>> ignore = Inform(prog_name=False) + + *************** Common mistakes *************** .. currentmodule:: nestedtext +Two Values for One Key +---------------------- + When :func:`load()` or :func:`loads()` complains of errors it is important to look both at the line fingered by the error message and the one above it. The line that is the target of the error message might by an otherwise valid @@ -80,3 +89,55 @@ trailing whitespace. To do so in Vim, add:: set listchars=trail:␣ to your ~/.vimrc file. + + +Lists or Strings at the Top Level +--------------------------------- + +Most *NestedText* files start with key-value pairs at the top-level and we +noticed that many developers would simply assume this in their code, which would +result in unexpected crashes when their programs read legal *NestedText* files +that had either a list or a string at the top level. To avoid this, the +:func:`load` and :func:`loads` functions are configured to expect a dictionary +at the top level by default, which results in an error being reported if +a dictionary key is not the first token found: + +.. code-block:: python + + >>> import nestedtext as nt + + >>> content = """ + ... - a + ... - b + ... """ + + >>> try: + ... print(nt.loads(content)) + ... except nt.NestedTextError as e: + ... e.report() + error: 2: content must start with key or brace ({). + 2 ❬- a❭ + +This restriction is easily removed using *top*: + +.. code-block:: python + + >>> try: + ... print(nt.loads(content, top=list)) + ... except nt.NestedTextError as e: + ... e.report() + ['a', 'b'] + +The *top* argument can take any of the following values: *"dict"*, *dict*, +*"list"*, *list*, *"str"*, *str*, *"any"*, or *any*. The default value is +*dict*. The value given for *top* also determines the value returned by +:func:`load` and :func:`loads` if the *NestedText* document is empty. + +================ ================================= +*top* value returned for empty document +---------------- --------------------------------- +*"dict"*, *dict* ``{}`` +*"list"*, *list* ``[]`` +*"str"*, *str* ``""`` +*"any"*, *any* *None* +================ ================================= diff --git a/examples/accumulation/settings.py b/examples/accumulation/settings.py index e7e2b8d..9a00428 100644 --- a/examples/accumulation/settings.py +++ b/examples/accumulation/settings.py @@ -84,10 +84,10 @@ def report_error(msg): value = base elif key in schema: if accumulate: - report_error(f"setting is unsuitable for accumulation") + report_error("setting is unsuitable for accumulation") value = schema[key](value) # cast to desired type else: - report_error(f"unknown setting") + report_error("unknown setting") processed[key] = value return processed diff --git a/tests/official_tests b/tests/official_tests index da32a12..0fa5552 160000 --- a/tests/official_tests +++ b/tests/official_tests @@ -1 +1 @@ -Subproject commit da32a124f5f94512add77d3e998c2ad6dbe036f8 +Subproject commit 0fa5552b2038a5972e0141d726f332c2d9c117b1 diff --git a/tests/test_nestedtext.py b/tests/test_nestedtext.py index adea9e0..cb298fb 100644 --- a/tests/test_nestedtext.py +++ b/tests/test_nestedtext.py @@ -992,6 +992,9 @@ def check_result(keys, expected, addresses): ◊ 7 ❬ > Topeka, Kansas 20697❭ ▲ """, bolm='◊', strip_nl="b") + with pytest.raises(IndexError) as exception: + loc.as_line('value', offset=(2,8)) + assert exception.value.args == (2,) # test_keymaps_with_duplicates {{{2