Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-sphinx-jsonschema for 
openSUSE:Factory checked in at 2024-01-15 22:16:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sphinx-jsonschema (Old)
 and      /work/SRC/openSUSE:Factory/.python-sphinx-jsonschema.new.21961 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-sphinx-jsonschema"

Mon Jan 15 22:16:07 2024 rev:4 rq:1138556 version:1.19.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-sphinx-jsonschema/python-sphinx-jsonschema.changes
        2021-04-19 21:06:53.472109595 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-sphinx-jsonschema.new.21961/python-sphinx-jsonschema.changes
     2024-01-15 22:17:11.506358204 +0100
@@ -1,0 +2,13 @@
+Sun Jan 14 10:36:35 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 1.19.1:
+  * load a schema from a Python dict or object (or actually any
+    Python entity with a ``__str__`` method.).
+  * with JSON Pointer the ``:pass_unmodified:`` option is included.
+  * fixed a bug escaping backspaces.
+  * ``:hide_key:`` directive option.
+    This option allows you to hide certain keys, specified by a JSON
+    Path specification, to be excluded from rendering.
+  * added the ``:encoding:`` directive option.
+
+-------------------------------------------------------------------

Old:
----
  sphinx-jsonschema-1.16.8.tar.gz

New:
----
  sphinx-jsonschema-1.19.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-sphinx-jsonschema.spec ++++++
--- /var/tmp/diff_new_pack.QcjUIe/_old  2024-01-15 22:17:11.922373402 +0100
+++ /var/tmp/diff_new_pack.QcjUIe/_new  2024-01-15 22:17:11.926373549 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-sphinx-jsonschema
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,13 +18,13 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-sphinx-jsonschema
-Version:        1.16.8
+Version:        1.19.1
 Release:        0
 Summary:        Sphinx extension to display JSON Schema
 License:        GPL-3.0-only
 URL:            https://github.com/lnoor/sphinx-jsonschema
 # Tarballs from pypi.org are missing license files
-Source:         
https://github.com/lnoor/sphinx-jsonschema/archive/refs/tags/v%{version}.tar.gz#/sphinx-jsonschema-%{version}.tar.gz
+Source:         
https://github.com/lnoor/sphinx-jsonschema/archive/refs/tags/v.%{version}.tar.gz#/sphinx-jsonschema-%{version}.tar.gz
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
@@ -46,7 +46,7 @@
 Sphinx extension to display JSON Schema.
 
 %prep
-%setup -q -n sphinx-jsonschema-%{version}
+%setup -q -n sphinx-jsonschema-v.%{version}
 
 %build
 %python_build

++++++ sphinx-jsonschema-1.16.8.tar.gz -> sphinx-jsonschema-1.19.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sphinx-jsonschema-1.16.8/.gitignore 
new/sphinx-jsonschema-v.1.19.1/.gitignore
--- old/sphinx-jsonschema-1.16.8/.gitignore     2021-03-23 17:35:18.000000000 
+0100
+++ new/sphinx-jsonschema-v.1.19.1/.gitignore   2022-05-01 14:24:48.000000000 
+0200
@@ -91,3 +91,5 @@
 # PyCharm
 .idea/
 
+# vscode
+.code-workspace
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sphinx-jsonschema-1.16.8/README.rst 
new/sphinx-jsonschema-v.1.19.1/README.rst
--- old/sphinx-jsonschema-1.16.8/README.rst     2021-03-23 17:35:18.000000000 
+0100
+++ new/sphinx-jsonschema-v.1.19.1/README.rst   2022-05-01 14:24:48.000000000 
+0200
@@ -60,15 +60,20 @@
 
     .. jsonschema:: /home/leo/src/jsonschema/sample.json
 
-Or a path relative to the referencing document::
+A path relative to the referencing document::
 
     .. jsonschema:: jsonschema/sample.json
 
+Or a schema defined in a Python object::
+
+    .. jsonschema:: mod.pkg.SCHEMA
+
 With all three of the above you may add JSON Pointer notation to display a 
subschema::
 
     .. jsonschema:: http://some.domain/with/a/path/spec.json#/path/to/schema
     .. jsonschema:: /home/leo/src/jsonschema/sample.json#/path/to/schema
     .. jsonschema:: jsonschema/sample.json#/path/to/schema
+    .. jsonschema:: mod.pkg.SCHEMA#/path/to/schema
 
 Alternatively you can embed the schema::
 
@@ -169,6 +174,50 @@
 Changelog
 =========
 
+Version 1.19.0
+--------------
+
+Glenn Nicholls <https://github.com/GlenNicholls> contributed code to load a 
schema from a
+Python dict or object (or actually any Python entity with a ``__str__`` 
method.).
+
+Version 1.18.0
+--------------
+
+Expanding on the work of `Pavel Odvody <https://github.com/shaded-enmity>`_ 
with JSON Pointer
+the ``:pass_unmodified:`` option is included.
+This option prevents escaping the string pointed at.
+This extension arose from discussions with `Ryan Lane 
<https://github.com/ryan-lane>`
+
+Version 1.17.2
+--------------
+
+`Ezequiel Orbe <https://github.com/eorbe>`_ found, reported and fixed a bug 
escaping backspaces.
+
+Version 1.17.0
+--------------
+
+`Pavel Odvody <https://github.com/shaded-enmity>`_ contributed the 
``:hide_key:`` directive option.
+This option allows you to hide certain keys, specified by a JSON Path 
specification, to be excluded
+from rendering.
+
+
+Version 1.16.11
+---------------
+
+Removed debugging code left in, pointed out by `Kevin Landreth 
<https://github.com/CrackerJackMack>`.
+
+Version 1.16.10
+---------------
+
+`iamdbychkov <https://github.com/iamdbychkov>`_ added the ``:encoding:`` 
directive option.
+This option allows explicit control of the encoding used to read a file
+instead of relying on the operating system default.
+
+Version 1.16.9
+--------------
+
+Bugfix.
+
 Version 1.16.8
 --------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sphinx-jsonschema-1.16.8/docs/conf.py 
new/sphinx-jsonschema-v.1.19.1/docs/conf.py
--- old/sphinx-jsonschema-1.16.8/docs/conf.py   2021-03-23 17:35:18.000000000 
+0100
+++ new/sphinx-jsonschema-v.1.19.1/docs/conf.py 2022-05-01 14:24:48.000000000 
+0200
@@ -60,9 +60,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = u'1.16'
+version = u'1.17'
 # The full version, including alpha/beta/rc tags.
-release = u'1.16.8'
+release = u'1.17.2'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sphinx-jsonschema-1.16.8/docs/directive.rst 
new/sphinx-jsonschema-v.1.19.1/docs/directive.rst
--- old/sphinx-jsonschema-1.16.8/docs/directive.rst     2021-03-23 
17:35:18.000000000 +0100
+++ new/sphinx-jsonschema-v.1.19.1/docs/directive.rst   2022-05-01 
14:24:48.000000000 +0200
@@ -124,6 +124,38 @@
         }
     }
 
+Lastly, you can use the ``jsonschema`` directive to render a schema from a 
Python
+object:
+
+.. code-block:: python
+    :caption: ``example.py``
+
+        SCHEMA = {
+            "$schema": "http://json-schema.org/draft-04/schema#";,
+            "title": "An example",
+            "id": "http://example.com/schemas/example.json";,
+            "description": "This is just a tiny example of a schema rendered 
by `sphinx-jsonschema <http://github.com/lnoor/sphinx-jsonschema>`_.\n\nYes 
that's right you can use *reStructuredText* in a description.",
+            "type": "string",
+            "minLength": 10,
+            "maxLength": 100,
+            "pattern": "^[A-Z]+$"
+        }
+
+with the following usage of the directive:
+
+.. code-block:: rst
+
+    .. jsonschema:: sphinx-jsonschema.example.SCHEMA
+
+which should render as:
+
+.. jsonschema:: sphinx-jsonschema.example.SCHEMA
+
+.. important::
+    For rendering Python objects with the ``jsonschema`` directive, the object 
does not
+    *need* to be a dict or a string. However, the object must have a 
``__str__`` method
+    defined that will return a valid schema.
+
 Options
 -------
 
@@ -152,6 +184,17 @@
     Automatically resolves references when possible.
     Works well with ``:auto_target:`` and ``:lift_definitions:``.
 
+hide_key: (default: None)
+    Hide parts of the schema matching comma separated list of JSON pointers
+
+hide_key_if_empty: (default: None)
+    Hide parts of the schema matching comma separated list of JSON pointers if 
the value is empty
+
+encoding (default: None)
+    Allows you to define the encoding used by the file containing the json 
schema.
+
+pass_unmodified (default: None)
+    Allows you to prevent escaping of _, / and * characters in strings.
 
 Lift Title
 ++++++++++
@@ -359,7 +402,9 @@
 It takes a dict as value the boolean valued keys of which have the same name 
as the options.
 
 So, in ``conf.py`` you can state:
-.. code-block:: py
+
+.. code-block:: python
+    :caption: ``conf.py``
 
     jsonschema_options = {
         'lift_description': True,
@@ -374,3 +419,65 @@
 They accept an optional argument which can be one of the words ``On``, 
``Off``, ``True``
 or ``False``. The default value for the argument is ``True``.
 
+Declare file encoding
++++++++++++++++++++++
+The ``:encoding:`` option allows you to define the encoding used by the file 
containing
+the json schema. When the operating system default encoding does not produce 
correct
+results then this option allows you to specify the encoding to use.
+When omitted the operating system default is used as it always has been. But 
it is now
+possible to explicitly declare the expected encoding using ``:encoding: utf8``.
+You can use any encoding defined by Python's codecs for your platform.
+
+Hiding parts of the schema
+++++++++++++++++++++++++++
+Sometimes we want to omit certain keys from rendering to make the table more 
succicnt.
+This can be achieved using the ``:hide_key:`` and ``:hide_key_if_empty:`` 
options to hide
+all matching keys or all matching keys with empty associated value, 
respectively.
+The options accept comma separated list of JSON pointers. Matching multiple 
keys
+is possible using the wildcard syntax ``*`` for single level matching and 
``**`` for
+deep matching.
+
+.. code-block:: rst
+
+    .. jsonschema::
+        :hide_key: /**/examples
+
+This example will hide all ``examples`` fields regardless of where they are 
located
+in the schema.
+If your JSON pointer contains comma you need to place it inside quotes:
+
+.. code-block:: rst
+
+    .. jsonschema::
+        :hide_key: /**/examples,"/**/with, comma"
+
+It is also possible to hide a key if their value is empty using 
``:hide_key_if_empty:``.
+
+.. code-block:: rst
+
+    .. jsonschema::
+        :hide_key_if_empty: /**/defaults
+
+Prevent escaping of strings
++++++++++++++++++++++++++++
+Strings are sometimes subject to multiple evaluation passes when rendering.
+This happens because `sphinx-jsonschema` renders a schema by transforming in 
into a table
+and then recursively call on Sphinx to render the table.
+To prevent unintended modifications due to this second pass some characters 
(such as '_'
+and '*' are escaped before the second pass.
+
+Sometimes that doesn't work out well and you don't want to escape those 
characters.
+The option ``:pass_unmodified:`` accepts one or more JSON pointers and 
prevents the strings
+pointed at to be escaped.
+
+.. code-block:: rst
+
+    .. jsonschema::
+        :pass_unmodified: /examples/0
+
+        {
+            "examples": [
+                "unescaped under_score",
+                "escaped under_score"
+            ]
+        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sphinx-jsonschema-1.16.8/docs/index.rst 
new/sphinx-jsonschema-v.1.19.1/docs/index.rst
--- old/sphinx-jsonschema-1.16.8/docs/index.rst 2021-03-23 17:35:18.000000000 
+0100
+++ new/sphinx-jsonschema-v.1.19.1/docs/index.rst       2022-05-01 
14:24:48.000000000 +0200
@@ -34,6 +34,49 @@
 Changelog
 =========
 
+Version 1.19.0
+--------------
+
+Glenn Nicholls <https://github.com/GlenNicholls> contributed code to load a 
schema from a
+Python dict or object (or actually any Python entity with a ``__str__`` 
method.).
+
+Version 1.18.0
+--------------
+
+Expanding on the work of `Pavel Odvody <https://github.com/shaded-enmity>`_ 
with JSON Pointer
+the ``:pass_unmodified:`` option is included.
+This option prevents escaping the string pointed at.
+This extension arose from discussions with `Ryan Lane 
<https://github.com/ryan-lane>`
+
+Version 1.17.2
+--------------
+
+`Ezequiel Orbe <https://github.com/eorbe>`_ found, reported and fixed a bug 
escaping backspaces.
+
+Version 1.17.0
+--------------
+
+`Pavel Odvody <https://github.com/shaded-enmity>`_ contributed the 
``:hide_key:`` directive option.
+This option allows you to hide certain keys, specified by a JSON Pointer 
specification, to be excluded
+from rendering.
+
+Version 1.16.11
+---------------
+
+Removed debugging code left in, pointed out by `Kevin Landreth 
<https://github.com/CrackerJackMack>`.
+
+Version 1.16.10
+---------------
+
+`iamdbychkov <https://github.com/iamdbychkov>`_ added the ``:encoding:`` 
directive option.
+This option allows explicit control of the encoding used to read a file 
instead of
+relying on the operating system default.
+
+Version 1.16.9
+--------------
+
+Bugfix.
+
 Version 1.16.8
 --------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sphinx-jsonschema-1.16.8/setup.py 
new/sphinx-jsonschema-v.1.19.1/setup.py
--- old/sphinx-jsonschema-1.16.8/setup.py       2021-03-23 17:35:18.000000000 
+0100
+++ new/sphinx-jsonschema-v.1.19.1/setup.py     2022-05-01 14:24:48.000000000 
+0200
@@ -10,7 +10,7 @@
 
 setup(
     name='sphinx-jsonschema',
-    version='1.16.8',     # don't forget: must match __init__.py::setup() 
return value
+    version='1.19.0',     # don't forget: must match __init__.py::setup() 
return value
 
     description='Sphinx extension to display JSON Schema',
     long_description=long_description,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sphinx-jsonschema-1.16.8/sphinx-jsonschema/__init__.py 
new/sphinx-jsonschema-v.1.19.1/sphinx-jsonschema/__init__.py
--- old/sphinx-jsonschema-1.16.8/sphinx-jsonschema/__init__.py  2021-03-23 
17:35:18.000000000 +0100
+++ new/sphinx-jsonschema-v.1.19.1/sphinx-jsonschema/__init__.py        
2022-05-01 14:24:48.000000000 +0200
@@ -13,11 +13,14 @@
     :licence: GPL v3, see LICENCE for details.
 """
 
-import os.path
+import csv
+import importlib
 import json
+import os
+import yaml
+
 from jsonpointer import resolve_pointer
 from traceback import format_exception, format_exception_only
-import yaml
 from collections import OrderedDict
 
 from docutils import nodes, utils
@@ -25,7 +28,131 @@
 from docutils.parsers.rst import directives
 from docutils.utils import SystemMessagePropagation
 from docutils.utils.error_reporting import SafeString
-from .wide_format import WideFormat
+from .wide_format import WideFormat, NOESC
+
+
+def pairwise(seq):
+    """ Iterate over pairs in a sequence """
+    return zip(seq, seq[1:])
+
+
+def maybe_int(val):
+    """ Convert value to an int and return it or just return the value """
+    try:
+        return int(val)
+    except:
+        return val
+
+
+def json_path_validate(path):
+    """ Check that json path doesn't contain consecutive or trailing wildcards 
"""
+    forbidden = {
+        ('**', '**'),
+        ('**', '*'),
+        ('*', '**'),
+        ('*', '*')
+    }
+
+    return set(pairwise(path)) & forbidden == set()
+
+
+def _json_fan_out(doc, path, transform, deep=False):
+    """ Process */** wildcards in the path by fanning out the processing to 
multiple keys """
+    if not path:
+        if isinstance(doc, list):
+            for r in range(len(doc)):
+                transform(doc, r)
+        return
+
+    targets = []
+
+    def deeper(v):
+        if deep:
+            _json_fan_out(v, path, transform, deep)
+        else:
+            if len(path) > 1 :
+                _json_bind(v, path[1:], transform)
+
+    def iterate(iterator):
+        for k, v in iterator:
+            if k == path[0]:
+                targets.append(path)
+            else:
+                deeper(v)
+
+    if isinstance(doc, dict):
+        iterate(doc.items())
+    if isinstance(doc, list):
+        iterate(enumerate(doc))
+
+    # Since transformers can mutate the original document
+    # we need to process them once we're done iterating
+    for r in targets:
+        _json_bind(doc, r, transform)
+
+
+def _json_bind(doc, path, transform):
+    """ Bind (sub)document to a particular path """
+    obj = doc
+    last = obj
+
+    for idx, p in enumerate(path):
+        if p in ('**', '*'):
+            return _json_fan_out(
+                obj,
+                path[idx+1:],
+                transform,
+                deep=(p == '**')
+            )
+
+        last = obj
+        try:
+            obj = obj[p]
+        except (KeyError, IndexError):
+            return
+
+    if path:
+        transform(last, path[-1])
+
+
+def json_path_transform(document, path, transformer):
+    """ Transform items in `document` conforming to `path` with a 
`transformer` in-place """
+
+    # Try to cast parts of the path as int if possible so that we can support
+    # paths like `/some/array/0/something` and we don't end up with TypeError
+    # trying to index into a list with a string '0'
+    parts = [maybe_int(p) for p in path.split('/')[1:]]
+
+    if not parts or not json_path_validate(parts):
+        raise ValueError('Supplied JSON path is invalid')
+
+    _json_bind(document, parts, transformer)
+
+
+def remove(doc, key):
+    if key in ('*', '**'):
+        raise ValueError('Supplied JSON path is invalid')
+    del doc[key]
+
+
+def remove_empty(doc, key):
+    if key in ('*', '**'):
+        raise ValueError('Supplied JSON path is invalid')
+    if not doc[key]:
+        del doc[key]
+
+
+def tag_noescape(doc, key):
+    if isinstance(doc[key], str):
+        doc[key] = NOESC + doc[key]
+    else:
+        raise ValueError('"%s" does not refer to a string' % key)
+
+
+def jsonpath_list(item):
+    if item:
+        return list(csv.reader([item])).pop()
+    raise ValueError('Invalid JSON path: "%s"' % item)
 
 
 def flag(argument):
@@ -37,7 +164,9 @@
         return True
     if value in ['off', 'false']:
         return False
-    raise ValueError('"%s" unknown, choose from "On", "True", "Off" or 
"False"' % argument)
+    raise ValueError(
+        '"%s" unknown, choose from "On", "True", "Off" or "False"' % argument)
+
 
 class JsonSchema(Directive):
     optional_arguments = 1
@@ -47,12 +176,28 @@
                    'lift_definitions': flag,
                    'auto_reference': flag,
                    'auto_target': flag,
-                   'timeout': float}
+                   'timeout': float,
+                   'encoding': directives.encoding,
+                   'hide_key': jsonpath_list,
+                   'hide_key_if_empty': jsonpath_list,
+                   'pass_unmodified': jsonpath_list}
 
     def run(self):
         try:
             schema, source, pointer = self.get_json_data()
-            format = WideFormat(self.state, self.lineno, source, self.options, 
self.state.document.settings.env.app)
+
+            if self.options.get('hide_key'):
+                for hide_path in self.options['hide_key']:
+                    json_path_transform(schema, hide_path, remove)
+            if self.options.get('hide_key_if_empty'):
+                for hide_path in self.options['hide_key_if_empty']:
+                    json_path_transform(schema, hide_path, remove_empty)
+            if self.options.get('pass_unmodified'):
+                for path in self.options['pass_unmodified']:
+                    json_path_transform(schema, path, tag_noescape)
+
+            format = WideFormat(self.state, self.lineno, source,
+                                self.options, 
self.state.document.settings.env.app)
             return format.run(schema, pointer)
         except SystemMessagePropagation as detail:
             return [detail.args[0]]
@@ -61,15 +206,16 @@
         except Exception as error:
             tb = error.__traceback__
             # loop through all traceback points to only return the last 
traceback
-            while tb.tb_next:
+            while tb and tb.tb_next:
                 tb = tb.tb_next
 
-            raise self.error(''.join(format_exception(type(error), error, tb, 
chain=False)))
+            raise self.error(''.join(format_exception(
+                type(error), error, tb, chain=False)))
 
     def get_json_data(self):
         """
         Get JSON data from the directive content, from an external
-        file, or from a URL reference.
+        file, from a URL reference, or from importing a schema defined in 
Python.
         """
         if self.arguments:
             filename, pointer = self._splitpointer(self.arguments[0])
@@ -80,9 +226,14 @@
         if self.content:
             schema, source = self.from_content(filename)
         elif filename and filename.startswith('http'):
+            # Appears to be URL so process it as such
             schema, source = self.from_url(filename)
-        elif filename:
+        elif os.path.exists(self._convert_filename(filename)):
+            # File exists so it must be a JSON schema
             schema, source = self.from_file(filename)
+        elif filename:
+            # Must be a Python reference to a schema
+            schema, source = self.from_data(filename)
         else:
             raise self.error('"%s" directive has no content or a reference to 
an external file.'
                              % self.name)
@@ -91,9 +242,9 @@
             schema = self.ordered_load(schema)
         except Exception as error:
             error = self.state_machine.reporter.error(
-                    '"%s" directive encountered a the following error while 
parsing the data.\n %s'
-                     % (self.name, 
SafeString("".join(format_exception_only(type(error), error)))),
-                    nodes.literal_block(schema, schema), line=self.lineno)
+                '"%s" directive encountered a the following error while 
parsing the data.\n %s'
+                % (self.name, 
SafeString("".join(format_exception_only(type(error), error)))),
+                nodes.literal_block(schema, schema), line=self.lineno)
             raise SystemMessagePropagation(error)
 
         if pointer:
@@ -137,35 +288,70 @@
             response = requests.get(url, timeout=timeout)
         except requests.exceptions.RequestException as e:
             raise self.error(u'"%s" directive recieved an "%s" when loading 
from url: %s.'
-                                % (self.name, type(e), url))
+                             % (self.name, type(e), url))
 
         if response.status_code != 200:
             # When making a connection to the url a status code will be 
returned
             # Normally a OK (200) response would we be returned all other 
responses
             # an error will be raised could be separated futher
             raise self.error(u'"%s" directive received an "%s" when loading 
from url: %s.'
-                                % (self.name, response.reason, url))
+                             % (self.name, response.reason, url))
 
         # response content always binary converting with decode() no specific 
format defined
         data = response.content.decode()
         return data, url
 
-    def from_file(self, filename):
+    def _convert_filename(self, filename):
+        """
+        Join the filename with the docs' source if it is not absolute.
+        """
+        if os.path.isabs(filename):
+            return filename
+        # file relative to the path of the current rst file
         document_source = os.path.dirname(self.state.document.current_source)
-        if not os.path.isabs(filename):
-            # file relative to the path of the current rst file
-            source = os.path.join(document_source, filename)
-        else:
-            source = filename
+        return os.path.join(document_source, filename)
 
+    def from_file(self, filename):
+        source = self._convert_filename(filename)
         try:
-            with open(source) as file:
+            with open(source, encoding=self.options.get('encoding')) as file:
                 data = file.read()
         except IOError as error:
             raise self.error(u'"%s" directive encountered an IOError while 
loading file: %s\n%s'
-                                % (self.name, source, error))
+                             % (self.name, source, error))
+
+        # Simplifing source path and to the document a new dependency
+        document_source = os.path.dirname(self.state.document.current_source)
+        source = utils.relative_path(document_source, source)
+        self.state.document.settings.record_dependencies.add(source)
+
+        return data, source
+
+    def from_data(self, filename):
+        """Get schema from Python data/object."""
+        document_source = os.path.dirname(self.state.document.current_source)
+
+        parts = filename.split('.')
+        if len(parts) > 1:
+            module_name = '.'.join(parts[:-1])
+            obj_name = parts[-1]
+        else:
+            raise self.error(
+                f"{self.name} directive requires a Python reference to a 
schema object"
+                f" like 'mod.pkg.data'. '{filename}' is not valid."
+            )
+
+        try:
+            mod = importlib.import_module(module_name)
+            data = str(getattr(mod, obj_name))
+        except (ImportError, ModuleNotFoundError) as error:
+            raise self.error(
+                f"{self.name} directive encountered an error while importing 
python"
+                f" module '{module_name}': \n{error}"
+            )
 
         # Simplifing source path and to the document a new dependency
+        source = mod.__file__
         source = utils.relative_path(document_source, source)
         self.state.document.settings.record_dependencies.add(source)
 
@@ -193,8 +379,8 @@
             yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
             construct_mapping)
 
-        text = text.replace('\\(', '\\\\(')
-        text = text.replace('\\)', '\\\\)')
+        text = text.replace(r'\\(', r'\\\\(')
+        text = text.replace(r'\\)', r'\\\\)')
         try:
             result = yaml.load(text, OrderedLoader)
         except yaml.scanner.ScannerError:
@@ -206,4 +392,7 @@
 def setup(app):
     app.add_directive('jsonschema', JsonSchema)
     app.add_config_value('jsonschema_options', {}, 'env')
-    return {'version': '1.16.8'}
+    return {
+        'parallel_read_safe': True,
+        'version': '1.19.0'
+    }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sphinx-jsonschema-1.16.8/sphinx-jsonschema/example.py 
new/sphinx-jsonschema-v.1.19.1/sphinx-jsonschema/example.py
--- old/sphinx-jsonschema-1.16.8/sphinx-jsonschema/example.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/sphinx-jsonschema-v.1.19.1/sphinx-jsonschema/example.py 2022-05-01 
14:24:48.000000000 +0200
@@ -0,0 +1,10 @@
+SCHEMA = {
+    "$schema": "http://json-schema.org/draft-04/schema#";,
+    "title": "An example",
+    "id": "http://example.com/schemas/example.json";,
+    "description": "This is just a tiny example of a schema rendered by 
`sphinx-jsonschema <http://github.com/lnoor/sphinx-jsonschema>`_.\n\nYes that's 
right you can use *reStructuredText* in a description.",
+    "type": "string",
+    "minLength": 10,
+    "maxLength": 100,
+    "pattern": "^[A-Z]+$"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sphinx-jsonschema-1.16.8/sphinx-jsonschema/wide_format.py 
new/sphinx-jsonschema-v.1.19.1/sphinx-jsonschema/wide_format.py
--- old/sphinx-jsonschema-1.16.8/sphinx-jsonschema/wide_format.py       
2021-03-23 17:35:18.000000000 +0100
+++ new/sphinx-jsonschema-v.1.19.1/sphinx-jsonschema/wide_format.py     
2022-05-01 14:24:48.000000000 +0200
@@ -22,6 +22,7 @@
 else:
     str_unicode = str
 
+NOESC = ':noesc:'  # prefix marker to indicate string must not be escaped.
 
 class WideFormat(object):
     KV_SIMPLE = [
@@ -211,10 +212,12 @@
         rows = []
         self.nesting += 1
 
-        if 'definitions' in schema and self.options['lift_definitions']:
-            definitions = self._definitions(schema)
-        else:
-            definitions = None
+        definitions = []
+        if self.options['lift_definitions']:
+            if '$defs' in schema:
+                definitions = self._definitions(schema, '$defs')
+            elif 'definitions' in schema:
+                definitions = self._definitions(schema, 'definitions')
 
         if 'type' in schema:
             # select processor for type
@@ -234,6 +237,7 @@
 
         # definitions aren't really type equiv's but still best place for them
         rows.extend(self._objectproperties(schema, 'definitions'))
+        rows.extend(self._objectproperties(schema, '$defs'))
 
         if label is not None:
             # prepend label column if required
@@ -334,9 +338,9 @@
             del schema[key]
         return rows
 
-    def _definitions(self, schema):
+    def _definitions(self, schema, defs_key):
         target = {}
-        for name, item in schema['definitions'].items():
+        for name, item in schema[defs_key].items():
             # add title by the name of the object if title not defined
             if 'title' not in item:
                 item['title'] = name
@@ -353,10 +357,13 @@
 
 
         result = []
-        for name, item in schema['definitions'].items():
-            result.extend(self.run(item, '/definitions/' + name))
+        for name, item in schema[defs_key].items():
+            new_target = '/{defs_key}/{name}'.format(
+                defs_key=defs_key, name=name
+            )
+            result.extend(self.run(item, new_target))
 
-        del schema['definitions']
+        del schema[defs_key]
         return result
 
     def _complexstructures(self, schema):
@@ -410,27 +417,32 @@
                             label,
                             self._cell(str_unicode(', '.join(obj)))))
                 else:
-                    import pdb; pdb.set_trace()
                     rows.extend(self._dispatch(obj, label)[0])
             del schema[key]
         return rows
 
+    def _get_defined_reference(self, schema, key):
+        target = '#/{defs}/'.format(defs=key)
+        if schema['$ref'].startswith(target):
+            reference = [r for r in schema['$ref'][2:].split('/') if r != key]
+            return len(reference), reference[-1]
+
     def _reference(self, schema):
         if self.options['auto_reference'] and self.options['lift_title']:
             # first check if references is to own schema
             # when definitions is separated automated they will be linked to 
the title
             # otherwise it will only be a string
+            reference = (
+                self._get_defined_reference(schema, 'definitions') or
+                self._get_defined_reference(schema, '$defs')
+            )
             if schema['$ref'] == '#' or schema['$ref'] == '#/':
                 if self.ref_titles.get(0, False):
                     row = (self._line(self._cell('`' + self.ref_titles[0] + 
'`_')))
                 else:
                     row = (self._line(self._cell(schema['$ref'])))
-            elif schema['$ref'].startswith("#/definitions/"):
-                reference = schema['$ref'][2:].split('/')
-                # removing definitions from list otherwise nesting level will 
be to deep
-                reference = [v for v in reference if v != "definitions"]
-                target_name = reference[-1]
-                ref_length = len(reference)
+            elif reference:
+                ref_length, target_name = reference
                 # Check if there are definitions available to make a reference
                 if (self.ref_titles.get(ref_length, False) and
                         target_name in self.ref_titles[ref_length]):
@@ -620,6 +632,8 @@
         return Path(path).name
 
     def _escape(self, text):
+        if text.startswith(NOESC):
+            return text[len(NOESC):]
         text = text.replace('\\', '\\\\')
         text = text.replace('_', '\\_')
         text = text.replace('*', '\\*')

Reply via email to