Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-sphinxcontrib-plantuml for 
openSUSE:Factory checked in at 2021-06-29 22:43:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-sphinxcontrib-plantuml (Old)
 and      /work/SRC/openSUSE:Factory/.python-sphinxcontrib-plantuml.new.2625 
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-sphinxcontrib-plantuml"

Tue Jun 29 22:43:34 2021 rev:4 rq:903060 version:0.21

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-sphinxcontrib-plantuml/python-sphinxcontrib-plantuml.changes
      2020-04-23 18:38:41.365034923 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-sphinxcontrib-plantuml.new.2625/python-sphinxcontrib-plantuml.changes
    2021-06-29 22:44:16.890954554 +0200
@@ -1,0 +2,6 @@
+Tue Jun 29 08:58:05 UTC 2021 - Linnaea Lavia <[email protected]>
+
+- Version update to 0.21, drops python2
+  * py3-for-tests.patch: refreshed
+
+-------------------------------------------------------------------

Old:
----
  sphinxcontrib-plantuml-0.18.tar.gz

New:
----
  sphinxcontrib-plantuml-0.21.tar.gz

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

Other differences:
------------------
++++++ python-sphinxcontrib-plantuml.spec ++++++
--- /var/tmp/diff_new_pack.ol2J3m/_old  2021-06-29 22:44:17.302955098 +0200
+++ /var/tmp/diff_new_pack.ol2J3m/_new  2021-06-29 22:44:17.302955098 +0200
@@ -16,9 +16,11 @@
 #
 
 
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%define skip_python2 1
+%{?!python_module:%define python_module() python3-%{**}}
+
 Name:           python-sphinxcontrib-plantuml
-Version:        0.18
+Version:        0.21
 Release:        0
 Summary:        Sphinx API for Web Apps
 License:        BSD-2-Clause
@@ -26,9 +28,8 @@
 URL:            https://github.com/sphinx-contrib/plantuml/
 Source:         
https://github.com/sphinx-contrib/plantuml/archive/%{version}.tar.gz#/sphinxcontrib-plantuml-%{version}.tar.gz
 Patch0:         py3-for-tests.patch
-BuildRequires:  %{python_module Sphinx >= 1.1}
+BuildRequires:  %{python_module Sphinx >= 2}
 BuildRequires:  %{python_module Sphinx-latex}
-BuildRequires:  %{python_module nose}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
@@ -37,7 +38,7 @@
 BuildRequires:  texlive-epstopdf
 BuildRequires:  tox
 Requires:       plantuml
-Requires:       python-Sphinx >= 1.1
+Requires:       python-Sphinx >= 2
 BuildArch:      noarch
 %python_subpackages
 

++++++ py3-for-tests.patch ++++++
--- /var/tmp/diff_new_pack.ol2J3m/_old  2021-06-29 22:44:17.326955129 +0200
+++ /var/tmp/diff_new_pack.ol2J3m/_new  2021-06-29 22:44:17.326955129 +0200
@@ -2,13 +2,8 @@
 ===================================================================
 --- plantuml-0.18.orig/tests/fakecmd.py
 +++ plantuml-0.18/tests/fakecmd.py
-@@ -1,7 +1,7 @@
+@@ -1,3 +1,3 @@
 -#!/usr/bin/env python
 +#!/usr/bin/env python3
  import sys
  
- # embed as PostScript comment
--print '%', ' '.join(sys.argv)
-+print('%', ' '.join(sys.argv))
- for line in sys.stdin:
-     sys.stdout.write('% ' + line)

++++++ sphinxcontrib-plantuml-0.18.tar.gz -> sphinxcontrib-plantuml-0.21.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/Makefile new/plantuml-0.21/Makefile
--- old/plantuml-0.18/Makefile  2020-01-01 02:34:22.000000000 +0100
+++ new/plantuml-0.21/Makefile  2021-05-11 12:04:36.000000000 +0200
@@ -1,9 +1,10 @@
-PYTHON = python
+FAKEROOT = fakeroot
+PYTHON = python3
 TWINE = twine
 
 .PHONY: dist
 dist:
-       $(PYTHON) setup.py sdist
+       $(FAKEROOT) $(PYTHON) setup.py sdist
 
 .PHONY: upload
 upload: dist
@@ -11,7 +12,7 @@
 
 .PHONY: check
 check:
-       $(PYTHON) `which nosetests`
+       $(PYTHON) -m pytest
 
 .PHONY: clean
 clean:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/README.rst new/plantuml-0.21/README.rst
--- old/plantuml-0.18/README.rst        2020-01-01 02:34:22.000000000 +0100
+++ new/plantuml-0.21/README.rst        2021-05-11 12:04:36.000000000 +0200
@@ -1,36 +1,49 @@
 PlantUML for Sphinx
 ===================
 
+Installation
+------------
+
+.. code-block::
+
+   pip install sphinxcontrib-plantuml
+
 Usage
 -----
 
-Once you enable this extension,
-::
+Add ``sphinxcontrib.plantuml`` to your extensions list in your ``conf.py``:
+
+
+.. code-block:: python
 
-    # Add any Sphinx extension module names here, as strings. They can be 
extensions
-    # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-    extensions = ['sphinxcontrib.plantuml']
+   extensions = [
+       'sphinxcontrib.plantuml',
+   ]
 
-you may need to specify plantuml command in your conf.py::
+You may also need to specify the plantuml command in your **conf.py**:
 
-    plantuml = 'java -jar /path/to/plantuml.jar'
+.. code-block:: python
 
-Instead, you can install a wrapper script in your PATH::
+   plantuml = 'java -jar /path/to/plantuml.jar'
 
-    % cat <<EOT > /usr/local/bin/plantuml
-    #!/bin/sh -e
-    java -jar /path/to/plantuml.jar "$@"
-    EOT
-    % chmod +x /usr/local/bin/plantuml
+Instead, you can install a wrapper script in your PATH:
 
-Then, write PlantUML text under ``.. uml::`` directive::
+.. code-block:: console
+
+   % cat <<EOT > /usr/local/bin/plantuml
+   #!/bin/sh -e
+   java -jar /path/to/plantuml.jar "$@"
+   EOT
+   % chmod +x /usr/local/bin/plantuml
+
+Then, write PlantUML text under the ``.. uml::`` directive::
 
     .. uml::
 
        Alice -> Bob: Hi!
        Alice <- Bob: How are you?
 
-or specify path to external PlantUML file::
+or specify path to an external PlantUML file::
 
     .. uml:: external.uml
 
@@ -42,7 +55,7 @@
 
        Foo <|-- Bar
 
-You can specify a caption::
+You can also specify a caption::
 
     .. uml::
        :caption: Caption with **bold** and *italic*
@@ -92,3 +105,16 @@
 
 plantuml_syntax_error_image
   Should plantuml generate images with render errors. (default: False)
+
+plantuml_cache_path
+  Directory where image cache is stored. (default: '_plantuml')
+
+plantuml_batch_size
+  **(EXPERIMENTAL)**
+  Run plantuml command per the specified number of images. (default: 1)
+
+  If enabled, plantuml documents will be first written to the cache directory,
+  and rendered in batches. This eliminates bootstrapping overhead of Java
+  runtime and allows plantuml to leverage multiple CPU cores.
+
+  To enable batch rendering, set the size to 100-1000.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/setup.py new/plantuml-0.21/setup.py
--- old/plantuml-0.18/setup.py  2020-01-01 02:34:22.000000000 +0100
+++ new/plantuml-0.21/setup.py  2021-05-11 12:04:36.000000000 +0200
@@ -4,11 +4,11 @@
 
 long_desc = open('README.rst').read()
 
-requires = ['Sphinx>=1.1']
+requires = ['Sphinx>=1.6']
 
 setup(
     name='sphinxcontrib-plantuml',
-    version='0.18',
+    version='0.21',
     url='https://github.com/sphinx-contrib/plantuml/',
     download_url='https://pypi.python.org/pypi/sphinxcontrib-plantuml',
     license='BSD',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/sphinxcontrib/plantuml.py 
new/plantuml-0.21/sphinxcontrib/plantuml.py
--- old/plantuml-0.18/sphinxcontrib/plantuml.py 2020-01-01 02:34:22.000000000 
+0100
+++ new/plantuml-0.21/sphinxcontrib/plantuml.py 2021-05-11 12:04:36.000000000 
+0200
@@ -15,17 +15,23 @@
 import os
 import re
 import shlex
+import shutil
 import subprocess
 from contextlib import contextmanager
 
 from docutils import nodes
 from docutils.parsers.rst import directives
 from docutils.parsers.rst import Directive
+
+from sphinx import util
 from sphinx.errors import SphinxError
+from sphinx.util import (
+    i18n,
+    logging,
+)
 from sphinx.util.nodes import set_source_info
 from sphinx.util.osutil import (
     ensuredir,
-    ENOENT,
 )
 
 try:
@@ -33,20 +39,21 @@
 except ImportError:
     Image = None
 
-try:
-    from sphinx.util.i18n import search_image_for_language
-except ImportError:  # Sphinx < 1.4
-    def search_image_for_language(filename, env):
-        return filename
 
-try:
-    from sphinx.util import logging
-    logger = logging.getLogger(__name__)
-    def _warn(self, msg):
-        logger.warning(msg)
-except (AttributeError, ImportError):  # Sphinx < 1.6
-    def _warn(self, msg):
-        self.builder.warn(msg)
+logger = logging.getLogger(__name__)
+
+
+if os.name == 'nt':
+    def rename(src, dst):
+        try:
+            os.rename(src, dst)
+        except OSError as err:
+            if err.errno != errno.EEXIST:
+                raise
+            os.unlink(dst)
+            os.rename(src, dst)
+else:
+    rename = os.rename
 
 
 class PlantUmlError(SphinxError):
@@ -105,7 +112,7 @@
             return [warning('uml directive cannot have both content and '
                             'a filename argument', line=self.lineno)]
         if self.arguments:
-            fn = search_image_for_language(self.arguments[0], env)
+            fn = i18n.search_image_for_language(self.arguments[0], env)
             relfn, absfn = env.relfn2path(fn)
             env.note_dependency(relfn)
             try:
@@ -152,13 +159,17 @@
         fp.close()
 
 
-def generate_name(self, node, fileformat):
+def hash_plantuml_node(node):
     h = hashlib.sha1()
     # may include different file relative to doc
     h.update(node['incdir'].encode('utf-8'))
     h.update(b'\0')
     h.update(node['uml'].encode('utf-8'))
-    key = h.hexdigest()
+    return h.hexdigest()
+
+
+def generate_name(self, node, fileformat):
+    key = hash_plantuml_node(node)
     fname = 'plantuml-%s.%s' % (key, fileformat)
     imgpath = getattr(self.builder, 'imgpath', None)
     if imgpath:
@@ -203,30 +214,12 @@
     refname, outfname = generate_name(self, node, fileformat)
     if os.path.exists(outfname):
         return refname, outfname  # don't regenerate
-    absincdir = os.path.join(self.builder.srcdir, node['incdir'])
+
+    cachefname = self.builder.plantuml_builder.render(node, fileformat)
     ensuredir(os.path.dirname(outfname))
-    f = open(outfname, 'wb')
-    try:
-        try:
-            p = subprocess.Popen(generate_plantuml_args(self, node,
-                                                        fileformat),
-                                 stdout=f, stdin=subprocess.PIPE,
-                                 stderr=subprocess.PIPE,
-                                 cwd=absincdir)
-        except OSError as err:
-            if err.errno != ENOENT:
-                raise
-            raise PlantUmlError('plantuml command %r cannot be run'
-                                % self.builder.config.plantuml)
-        serr = p.communicate(node['uml'].encode('utf-8'))[1]
-        if p.returncode != 0:
-            if self.builder.config.plantuml_syntax_error_image:
-                _warn(self, 'error while running plantuml\n\n%s' % serr)
-            else:
-                raise PlantUmlError('error while running plantuml\n\n%s' % 
serr)
-        return refname, outfname
-    finally:
-        f.close()
+    # TODO: optionally do symlink/link
+    shutil.copyfile(cachefname, outfname)
+    return refname, outfname
 
 
 def render_plantuml_inline(self, node, fileformat):
@@ -238,7 +231,7 @@
                              stderr=subprocess.PIPE,
                              cwd=absincdir)
     except OSError as err:
-        if err.errno != ENOENT:
+        if err.errno != errno.ENOENT:
             raise
         raise PlantUmlError('plantuml command %r cannot be run'
                             % self.builder.config.plantuml)
@@ -248,6 +241,135 @@
     return sout.decode('utf-8')
 
 
+class PlantumlBuilder(object):
+    def __init__(self, builder):
+        # for compatibility with existing functions which expect self.builder
+        # TODO: remove self.builder
+        self.builder = builder
+
+        self.batch_size = builder.config.plantuml_batch_size
+        self.cache_dir = os.path.join(builder.outdir,
+                                      builder.config.plantuml_cache_path)
+
+        self._base_cmdargs = _split_cmdargs(builder.config.plantuml)
+        self._base_cmdargs.extend(['-charset', 'utf-8'])
+
+        self.image_formats = []
+        if builder.format == 'html':
+            fmt = builder.config.plantuml_output_format
+            if fmt != 'none':
+                fileformats, _gettag = _lookup_html_format(fmt)
+                self.image_formats = list(fileformats)
+        elif builder.format == 'latex':
+            fmt = builder.config.plantuml_latex_output_format
+            if fmt != 'none':
+                fileformat, _postproc = _lookup_latex_format(fmt)
+                self.image_formats = [fileformat]
+
+        self._known_keys = set()
+        self._pending_keys = []
+
+    def collect_nodes(self, doctree):
+        for node in doctree.traverse(plantuml):
+            key = hash_plantuml_node(node)
+            if key in self._known_keys:
+                continue
+            self._known_keys.add(key)
+
+            doc = node['uml'].encode('utf-8')
+            if b'!include' in doc or b'%filename' in doc:
+                # Heuristic to work around the path/filename issue. There's no
+                # easy way to specify the cwd of the doc without using -pipe.
+                continue
+
+            outdir = os.path.join(self.cache_dir, key[:2])
+            outfbase = os.path.join(outdir, key)
+            if all(os.path.exists('%s.%s' % (outfbase, sfx))
+                   for sfx in ['puml'] + self.image_formats):
+                continue
+
+            ensuredir(outdir)
+            with open(outfbase + '.puml', 'wb') as f:
+                # @startuml/enduml is mandatory in non-pipe mode. For backward
+                # compatibility, we do wrap the document only if @startXYZ is
+                # not specified.
+                started = doc.lstrip().startswith(b'@start')
+                if not started:
+                    f.write(b'@startuml\n')
+                f.write(doc)
+                if not started:
+                    f.write(b'\n@enduml\n')
+
+            self._pending_keys.append(key)
+
+    def render_batches(self):
+        pending_keys = sorted(self._pending_keys)
+        for fileformat in self.image_formats:
+            for i in range(0, len(pending_keys), self.batch_size):
+                keys = pending_keys[i:i + self.batch_size]
+                with util.progress_message(
+                        'rendering plantuml diagrams [%d..%d/%d]'
+                        % (i, i + len(keys), len(pending_keys))):
+                    self._render_files(keys, fileformat)
+
+        del self._pending_keys[:]
+
+    def _render_files(self, keys, fileformat):
+        cmdargs = self._base_cmdargs[:]
+        cmdargs.extend(_ARGS_BY_FILEFORMAT[fileformat])
+        cmdargs.extend(os.path.join(k[:2], '%s.puml' % k) for k in keys)
+        try:
+            p = subprocess.Popen(cmdargs, stderr=subprocess.PIPE,
+                                 cwd=self.cache_dir)
+        except OSError as err:
+            if err.errno != errno.ENOENT:
+                raise
+            raise PlantUmlError('plantuml command %r cannot be run'
+                                % self.builder.config.plantuml)
+        serr = p.communicate()[1]
+        if p.returncode != 0:
+            if self.builder.config.plantuml_syntax_error_image:
+                logger.warning('error while running plantuml\n\n%s' % serr)
+            else:
+                raise PlantUmlError('error while running plantuml\n\n%s' % 
serr)
+
+    def render(self, node, fileformat):
+        key = hash_plantuml_node(node)
+        outdir = os.path.join(self.cache_dir, key[:2])
+        outfname = os.path.join(outdir, '%s.%s' % (key, fileformat))
+        if os.path.exists(outfname):
+            return outfname
+
+        ensuredir(outdir)
+        absincdir = os.path.join(self.builder.srcdir, node['incdir'])
+        with open(outfname + '.new', 'wb') as f:
+            try:
+                p = subprocess.Popen(generate_plantuml_args(self, node,
+                                                            fileformat),
+                                     stdout=f, stdin=subprocess.PIPE,
+                                     stderr=subprocess.PIPE,
+                                     cwd=absincdir)
+            except OSError as err:
+                if err.errno != errno.ENOENT:
+                    raise
+                raise PlantUmlError('plantuml command %r cannot be run'
+                                    % self.builder.config.plantuml)
+            serr = p.communicate(node['uml'].encode('utf-8'))[1]
+            if p.returncode != 0:
+                if self.builder.config.plantuml_syntax_error_image:
+                    logger.warning('error while running plantuml\n\n%s' % serr)
+                else:
+                    raise PlantUmlError('error while running plantuml\n\n%s'
+                                        % serr)
+
+        rename(outfname + '.new', outfname)
+        return outfname
+
+
+def _render_batches_on_vist(self):
+    self.builder.plantuml_builder.render_batches()
+
+
 def _get_png_tag(self, fnames, node):
     refname, outfname = fnames['png']
     alt = node.get('alt', node['uml'])
@@ -256,9 +378,9 @@
     # process images prior to html_vist.
     scale_attrs = [k for k in ('scale', 'width', 'height') if k in node]
     if scale_attrs and Image is None:
-        _warn(self, ('plantuml: unsupported scaling attributes: %s '
-                     '(install PIL or Pillow)'
-                     % ', '.join(scale_attrs)))
+        logger.warning(('plantuml: unsupported scaling attributes: %s '
+                        '(install PIL or Pillow)'
+                        % ', '.join(scale_attrs)))
     if not scale_attrs or Image is None:
         return ('<img src="%s" alt="%s"/>\n'
                 % (self.encode(refname), self.encode(alt)))
@@ -289,7 +411,7 @@
             styles.extend('%s: %s%s' % (a, w * scale / 100, 'px')
                           for a, w in zip(['width', 'height'], im.size))
         except (IOError, OSError) as err:
-            _warn(self, 'plantuml: failed to get image size: %s' % err)
+            logger.warning('plantuml: failed to get image size: %s' % err)
 
     return ('<a href="%s"><img src="%s" alt="%s" style="%s"/>'
             '</a>\n'
@@ -352,27 +474,29 @@
 }
 
 
+def _lookup_html_format(fmt):
+    try:
+        return _KNOWN_HTML_FORMATS[fmt]
+    except KeyError:
+        raise PlantUmlError(
+            'plantuml_output_format must be one of %s, but is %r'
+            % (', '.join(map(repr, _KNOWN_HTML_FORMATS)), fmt))
+
+
 @contextmanager
 def _prepare_html_render(self, fmt):
     if fmt == 'none':
         raise nodes.SkipNode
 
     try:
-        try:
-            fileformats, gettag = _KNOWN_HTML_FORMATS[fmt]
-        except KeyError:
-            raise PlantUmlError(
-                'plantuml_output_format must be one of %s, but is %r'
-                % (', '.join(map(repr, _KNOWN_HTML_FORMATS)), fmt))
-
-        yield fileformats, gettag
-
+        yield _lookup_html_format(fmt)
     except PlantUmlError as err:
-        _warn(self, str(err))
+        logger.warning(str(err))
         raise nodes.SkipNode
 
 
 def html_visit_plantuml(self, node):
+    _render_batches_on_vist(self)
     if 'html_format' in node:
         fmt = node['html_format']
     else:
@@ -403,13 +527,13 @@
             p = subprocess.Popen(['bash'] + args, stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
     except OSError as err:
-        if err.errno != ENOENT:
+        if err.errno != errno.ENOENT:
             raise
         raise PlantUmlError('epstopdf command %r cannot be run'
                             % self.builder.config.plantuml_epstopdf)
     serr = p.communicate()[1]
     if p.returncode != 0:
-        raise PlantUmlError('error while running epstopdf\n\n' + serr)
+        raise PlantUmlError('error while running epstopdf\n\n%s' % serr)
     return refname[:-4] + '.pdf', fname[:-4] + '.pdf'
 
 
@@ -420,7 +544,17 @@
 }
 
 
+def _lookup_latex_format(fmt):
+    try:
+        return _KNOWN_LATEX_FORMATS[fmt]
+    except KeyError:
+        raise PlantUmlError(
+            'plantuml_latex_output_format must be one of %s, but is %r'
+            % (', '.join(map(repr, _KNOWN_LATEX_FORMATS)), fmt))
+
+
 def latex_visit_plantuml(self, node):
+    _render_batches_on_vist(self)
     if 'latex_format' in node:
         fmt = node['latex_format']
     else:
@@ -428,16 +562,11 @@
     if fmt == 'none':
         raise nodes.SkipNode
     try:
-        try:
-            fileformat, postproc = _KNOWN_LATEX_FORMATS[fmt]
-        except KeyError:
-            raise PlantUmlError(
-                'plantuml_latex_output_format must be one of %s, but is %r'
-                % (', '.join(map(repr, _KNOWN_LATEX_FORMATS)), fmt))
+        fileformat, postproc = _lookup_latex_format(fmt)
         refname, outfname = render_plantuml(self, node, fileformat)
         refname, outfname = postproc(self, refname, outfname)
     except PlantUmlError as err:
-        _warn(self, str(err))
+        logger.warning(str(err))
         raise nodes.SkipNode
 
     # put node representing rendered image
@@ -453,34 +582,27 @@
 
 
 def confluence_visit_plantuml(self, node):
+    _render_batches_on_vist(self)
     fmt = self.builder.config.plantuml_output_format
     with _prepare_html_render(self, fmt) as (fileformats, _):
         _, outfname = render_plantuml(self, node, fileformats[0])
 
-    # Create a new image node in the document
-    img_node = nodes.image(uri=outfname, **node.attributes)
-    img_node.delattr('uml')
-    img_node.document = node.document
-    img_node.parent = node.parent
-    node.parent.children.insert(node.parent.children.index(node), img_node)
-    if not img_node.hasattr('alt'):
-        img_node['alt'] = node['uml']
+    # put node representing rendered image
+    img_node = nodes.image(uri=outfname, alt=node.get('alt', node['uml']))
+    node.replace_self(img_node)
+    self.visit_image(img_node)
 
-    # Confluence builder needs to be aware of the new asset
-    from sphinxcontrib.confluencebuilder import ConfluenceLogger
-    ConfluenceLogger.info('re-scanning for assets... ', nonl=0)
-    self.assets.process(list(self.assets.env.all_docs.keys()))
-    ConfluenceLogger.info('done\n')
 
-    # Handle the new node as a regular image
-    return self.visit_image(img_node)
+def confluence_depart_plantuml(self, node):
+    pass
 
 
 def text_visit_plantuml(self, node):
+    _render_batches_on_vist(self)
     try:
         text = render_plantuml_inline(self, node, 'txt')
     except PlantUmlError as err:
-        _warn(self, str(err))
+        logger.warning(str(err))
         text = node['uml']  # fall back to uml text, which is still readable
 
     self.new_state()
@@ -490,18 +612,19 @@
 
 
 def pdf_visit_plantuml(self, node):
+    _render_batches_on_vist(self)
     try:
         refname, outfname = render_plantuml(self, node, 'eps')
         refname, outfname = _convert_eps_to_pdf(self, refname, outfname)
     except PlantUmlError as err:
-        _warn(self, str(err))
+        logger.warning(str(err))
         raise nodes.SkipNode
     rep = nodes.image(uri=outfname, alt=node.get('alt', node['uml']))
     node.parent.replace(node, rep)
 
 
 def unsupported_visit_plantuml(self, node):
-    _warn(self, 'plantuml: unsupported output format (node skipped)')
+    logger.warning('plantuml: unsupported output format (node skipped)')
     raise nodes.SkipNode
 
 
@@ -511,10 +634,30 @@
     'man': (unsupported_visit_plantuml, None),  # TODO
     'texinfo': (unsupported_visit_plantuml, None),  # TODO
     'text': (text_visit_plantuml, None),
-    'confluence': (confluence_visit_plantuml, None),
+    'confluence': (confluence_visit_plantuml, confluence_depart_plantuml),
+    'singleconfluence': (confluence_visit_plantuml, 
confluence_depart_plantuml),
 }
 
 
+def _on_builder_inited(app):
+    app.builder.plantuml_builder = PlantumlBuilder(app.builder)
+
+
+def _on_doctree_read(app, doctree):
+    # Collect as many static nodes as possible prior to start building.
+    if app.builder.plantuml_builder.batch_size > 1:
+        app.builder.plantuml_builder.collect_nodes(doctree)
+
+
+def _on_doctree_resolved(app, doctree, docname):
+    # Dynamically generated nodes will be collected here, which will be
+    # batched at node visitor. Since 'doctree-resolved' and node visits
+    # can be intermixed, there's no way to batch rendering of dynamic nodes
+    # at once.
+    if app.builder.plantuml_builder.batch_size > 1:
+        app.builder.plantuml_builder.collect_nodes(doctree)
+
+
 def setup(app):
     app.add_node(plantuml, **_NODE_VISITORS)
     app.add_directive('uml', UmlDirective)
@@ -528,6 +671,11 @@
     app.add_config_value('plantuml_epstopdf', 'epstopdf', '')
     app.add_config_value('plantuml_latex_output_format', 'png', '')
     app.add_config_value('plantuml_syntax_error_image', False, '')
+    app.add_config_value('plantuml_cache_path', '_plantuml', '')
+    app.add_config_value('plantuml_batch_size', 1, '')
+    app.connect('builder-inited', _on_builder_inited)
+    app.connect('doctree-read', _on_doctree_read)
+    app.connect('doctree-resolved', _on_doctree_resolved)
 
     # imitate what app.add_node() does
     if 'rst2pdf.pdfbuilder' in app.config.extensions:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/tests/fakecmd.py 
new/plantuml-0.21/tests/fakecmd.py
--- old/plantuml-0.18/tests/fakecmd.py  2020-01-01 02:34:22.000000000 +0100
+++ new/plantuml-0.21/tests/fakecmd.py  2021-05-11 12:04:36.000000000 +0200
@@ -1,7 +1,18 @@
 #!/usr/bin/env python
 import sys
 
-# embed as PostScript comment
-print '%', ' '.join(sys.argv)
-for line in sys.stdin:
-    sys.stdout.write('% ' + line)
+def dump(fout, fin):
+    # embed as PostScript comment
+    fout.write('% ' + ' '.join(sys.argv) + '\n')
+    for line in fin:
+        fout.write('% ' + line)
+
+if '-pipe' in sys.argv:
+    dump(sys.stdout, sys.stdin)
+else:
+    for fname in sys.argv[1:]:
+        if not fname.endswith('.puml'):
+            continue
+        with open(fname[:-5] + '.png', 'w') as fout:
+            with open(fname, 'r') as fin:
+                dump(fout, fin)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/tests/fixture/hello.puml 
new/plantuml-0.21/tests/fixture/hello.puml
--- old/plantuml-0.18/tests/fixture/hello.puml  1970-01-01 01:00:00.000000000 
+0100
+++ new/plantuml-0.21/tests/fixture/hello.puml  2021-05-11 12:04:36.000000000 
+0200
@@ -0,0 +1,3 @@
+@startuml
+Hello
+@enduml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/tests/test_functional.py 
new/plantuml-0.21/tests/test_functional.py
--- old/plantuml-0.18/tests/test_functional.py  2020-01-01 02:34:22.000000000 
+0100
+++ new/plantuml-0.21/tests/test_functional.py  2021-05-11 12:04:36.000000000 
+0200
@@ -1,18 +1,15 @@
 import glob
-import nose
 import os
 import re
 import tempfile
 import shutil
 import sys
+import unittest
 
 from sphinx.application import Sphinx
 
-from nose.tools import *
-
 _fixturedir = os.path.join(os.path.dirname(__file__), 'fixture')
 _fakecmd = os.path.join(os.path.dirname(__file__), 'fakecmd.py')
-_fakeepstopdf = os.path.join(os.path.dirname(__file__), 'fakeepstopdf.py')
 
 def setup():
     global _tempdir, _srcdir, _outdir
@@ -42,7 +39,7 @@
     app.build()
 
 def with_runsphinx(builder, **kwargs):
-    confoverrides = {'plantuml': _fakecmd}
+    confoverrides = {'plantuml': [sys.executable, _fakecmd]}
     confoverrides.update(kwargs)
     def wrapfunc(func):
         def test():
@@ -51,7 +48,7 @@
                     import rst2pdf
                     rst2pdf.__file__
                 except ImportError:
-                    raise nose.SkipTest
+                    raise unittest.SkipTest
             src = '\n'.join(l[4:] for l in func.__doc__.splitlines()[2:])
             os.mkdir(_outdir)
             try:
@@ -82,10 +79,10 @@
 
     pngcontent = readfile(pngfiles[0]).splitlines()
     assert b'-pipe' in pngcontent[0]
-    assert_equals(b'Hello', pngcontent[1][2:])
+    assert pngcontent[1][2:] == b'Hello'
     svgcontent = readfile(svgfiles[0]).splitlines()
     assert b'-tsvg' in svgcontent[0]
-    assert_equals(b'Hello', svgcontent[1][2:])
+    assert svgcontent[1][2:] == b'Hello'
 
 @with_runsphinx('html', plantuml_output_format='none')
 def test_buildhtml_no_output():
@@ -148,7 +145,7 @@
 
        Hello
     """
-    assert b'<div class="figure" id="label">' in readfile('index.html')
+    re.search(br'<div class="figure[^"]*" id="label">', readfile('index.html'))
 
 @with_runsphinx('html')
 def test_buildhtml_nonascii():
@@ -161,7 +158,47 @@
     files = glob.glob(os.path.join(_outdir, '_images', 'plantuml-*.png'))
     content = readfile(files[0]).splitlines()
     assert b'-charset utf-8' in content[0]
-    assert_equals(u'\u3042', content[1][2:].decode('utf-8'))
+    assert content[1][2:].decode('utf-8') == u'\u3042'
+
+@with_runsphinx('html', plantuml_batch_size=2)
+def test_buildhtml_in_batches():
+    """Render in batches
+
+    .. uml::
+
+       Hello
+
+    .. uml::
+
+       Hello!
+
+    .. uml::
+
+       @startuml
+       Hello!!
+       @enduml
+
+    .. uml::
+
+       !include seq.ja.uml
+    """
+    puml_files = glob.glob(os.path.join(_outdir, '_plantuml', '*', '*.puml'))
+    assert len(puml_files) == 3
+    puml_contents = [readfile(f).splitlines() for f in puml_files]
+    assert all(len(lines) == 3 for lines in puml_contents)
+    assert all(lines[0] == b'@startuml' for lines in puml_contents)
+    assert all(lines[-1] == b'@enduml' for lines in puml_contents)
+    assert (sorted(lines[1] for lines in puml_contents)
+            == [b'Hello', b'Hello!', b'Hello!!'])
+
+    # batches: [2, 1], excluded: 1
+    png_files = glob.glob(os.path.join(_outdir, '_plantuml', '*', '*.png'))
+    assert len(png_files) == 4
+    png_commands = [readfile(f).splitlines()[0] for f in png_files]
+    assert len(set(png_commands)) == 3
+    assert sum(b'-pipe' in cmd for cmd in set(png_commands)) == 1
+    assert sorted(sum(c.endswith(b'.puml') for c in cmd.split())
+                  for cmd in set(png_commands)) == [0, 1, 2]
 
 @with_runsphinx('latex')
 def test_buildlatex_simple():
@@ -178,7 +215,7 @@
 
     content = readfile(files[0]).splitlines()
     assert b'-pipe' in content[0]
-    assert_equals(b'Hello', content[1][2:])
+    assert content[1][2:] == b'Hello'
 
 @with_runsphinx('latex', plantuml_latex_output_format='eps')
 def test_buildlatex_simple_with_eps():
@@ -195,7 +232,7 @@
 
     content = readfile(files[0]).splitlines()
     assert b'-teps' in content[0]
-    assert_equals(b'Hello', content[1][2:])
+    assert content[1][2:] == b'Hello'
 
 @with_runsphinx('latex', plantuml_latex_output_format='pdf')
 def test_buildlatex_simple_with_pdf():
@@ -214,7 +251,7 @@
 
     epscontent = readfile(epsfiles[0]).splitlines()
     assert b'-teps' in epscontent[0]
-    assert_equals(b'Hello', epscontent[1][2:])
+    assert epscontent[1][2:] == b'Hello'
 
 @with_runsphinx('latex', plantuml_latex_output_format='none')
 def test_buildlatex_no_output():
@@ -269,4 +306,4 @@
 
     epscontent = readfile(epsfiles[0]).splitlines()
     assert b'-teps' in epscontent[0]
-    assert_equals(b'Hello', epscontent[1][2:])
+    assert epscontent[1][2:] == b'Hello'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/tests/test_svgstyle.py 
new/plantuml-0.21/tests/test_svgstyle.py
--- old/plantuml-0.18/tests/test_svgstyle.py    2020-01-01 02:34:22.000000000 
+0100
+++ new/plantuml-0.21/tests/test_svgstyle.py    2021-05-11 12:04:36.000000000 
+0200
@@ -2,8 +2,6 @@
 import shutil
 import tempfile
 
-from nose.tools import *
-
 from sphinxcontrib import plantuml
 
 def setup():
@@ -28,4 +26,4 @@
         '<svg xmlns="http://www.w3.org/2000/svg"; height="147pt" '
         'style="width:115px;height:147px;" version="1.1" viewBox="0 0 115 147" 
'
         'width="115pt"><defs/>')
-    assert_equals('width:115px;height:147px;', plantuml._get_svg_style(fname))
+    assert plantuml._get_svg_style(fname) == 'width:115px;height:147px;'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/plantuml-0.18/tox.ini new/plantuml-0.21/tox.ini
--- old/plantuml-0.18/tox.ini   2020-01-01 02:34:22.000000000 +0100
+++ new/plantuml-0.21/tox.ini   2021-05-11 12:04:36.000000000 +0200
@@ -3,6 +3,6 @@
 
 [testenv]
 deps =
-    nose
+    pytest
     rst2pdf
-commands = nosetests
+commands = pytest

Reply via email to