Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ include AUTHORS
include LICENSE.txt
include README.md
include tests.py
include doc/*.rst
recursive-include jsonpointer-stubs *.pyi
8 changes: 4 additions & 4 deletions doc/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ JSON pointer notation:
>>> obj = {"foo": {"anArray": [ {"prop": 44}], "another prop": {"baz": "A string" }}}

>>> set_pointer(obj, '/foo/anArray/0/prop', 55)
{'foo': {'another prop': {'baz': 'A string'}, 'anArray': [{'prop': 55}]}}
{'foo': {'anArray': [{'prop': 55}], 'another prop': {'baz': 'A string'}}}

>>> obj
{'foo': {'another prop': {'baz': 'A string'}, 'anArray': [{'prop': 55}]}}
{'foo': {'anArray': [{'prop': 55}], 'another prop': {'baz': 'A string'}}}

By default ``set_pointer`` modifies the original object. Pass ``inplace=False``
to create a copy and modify the copy instead:
Expand All @@ -50,10 +50,10 @@ to create a copy and modify the copy instead:
>>> obj = {"foo": {"anArray": [ {"prop": 44}], "another prop": {"baz": "A string" }}}

>>> set_pointer(obj, '/foo/anArray/0/prop', 55, inplace=False)
{'foo': {'another prop': {'baz': 'A string'}, 'anArray': [{'prop': 55}]}}
{'foo': {'anArray': [{'prop': 55}], 'another prop': {'baz': 'A string'}}}

>>> obj
{'foo': {'another prop': {'baz': 'A string'}, 'anArray': [{'prop': 44}]}}
{'foo': {'anArray': [{'prop': 44}], 'another prop': {'baz': 'A string'}}}

By default, setting a value below a member that does not exist raises a
``JsonPointerException``. Pass ``create=True`` to create missing members as
Expand Down
63 changes: 63 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import json
import os
import runpy
import shlex
import subprocess
import sys
import tempfile
import textwrap
import unittest
from contextlib import redirect_stderr, redirect_stdout
from unittest import mock
Expand Down Expand Up @@ -923,6 +925,67 @@ def test_non_verbose_exception_excludes_doc(self):
self.assertIn('bar', str(e))


class DocExampleTests(unittest.TestCase):
""" Runs the shell examples from the documentation """

ROOT = os.path.dirname(os.path.abspath(__file__))
SCRIPT = os.path.join(ROOT, 'bin', 'jsonpointer')

def _examples(self, name):
""" Yields (command, expected output) pairs of the shell sessions in
the ``code-block:: bash`` directives of the given doc file """
with open(os.path.join(self.ROOT, 'doc', name), encoding='utf-8') as f:
blocks = f.read().split('.. code-block:: bash\n')[1:]
self.assertTrue(blocks, 'no bash examples found in ' + name)

for block in blocks:
# The block ends at the first non-indented line
lines = []
for line in block.splitlines()[1:]:
if line and not line[0].isspace():
break
lines.append(line)
lines = textwrap.dedent('\n'.join(lines)).splitlines()

cmd, output = None, []
for line in lines + ['']:
is_output = line.strip() and not line.startswith(('$ ', '#'))
if cmd is not None and is_output:
output.append(line)
continue
if cmd is not None:
yield cmd, ''.join(out + '\n' for out in output)
cmd, output = None, []
if line.startswith('$ '):
cmd = line[2:]

def test_commandline_examples(self):
tmpdir = tempfile.TemporaryDirectory()
self.addCleanup(tmpdir.cleanup)
env = dict(os.environ, PYTHONPATH=self.ROOT, PYTHONUTF8='1')

examples = list(self._examples('commandline.rst'))
self.assertTrue(any(cmd.startswith('jsonpointer ')
for cmd, _ in examples))
for cmd, expected in examples:
with self.subTest(cmd=cmd):
args = shlex.split(cmd)
if args[0] == 'cat':
# "cat" shows the input files used by later examples
path = os.path.join(tmpdir.name, args[1])
with open(path, 'w', encoding='utf-8') as f:
f.write(expected)
continue

self.assertEqual(args[0], 'jsonpointer')
result = subprocess.run([sys.executable, self.SCRIPT] + args[1:],
cwd=tmpdir.name, env=env,
capture_output=True, encoding='utf-8')
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout, expected)


def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(jsonpointer))
tests.addTests(doctest.DocFileSuite('doc/tutorial.rst'))
return tests
Loading