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
+
+- 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'', 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 @@
'