[gtkmm-documentation] tools/meson_aux: Replace shell scripts with Python scripts



commit 0658ded8b5f18c053526dd1c6d6abdaf9311bbd0
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Tue Oct 1 15:10:08 2019 +0200

    tools/meson_aux: Replace shell scripts with Python scripts
    
    Python scripts can be used on all operating systems where Meson
    can be used. Shell scripts are restricted to Unix-like systems.

 docs/tutorial/meson.build              |  17 ++-
 examples/book/buildapp/meson.build     |  13 +--
 examples/book/giomm/meson.build        |   6 +-
 examples/book/meson.build              |   4 +-
 examples/book/treeview/meson.build     |   6 +-
 examples/meson.build                   |   6 +-
 examples/others/meson.build            |   6 +-
 meson.build                            |  29 +++--
 tools/meson_aux/compile-schemas.py     |  30 +++++
 tools/meson_aux/compile-schemas.sh     |  17 ---
 tools/meson_aux/copy-to-subdir.py      |  35 ++++++
 tools/meson_aux/copy-to-subdir.sh      |  21 ----
 tools/meson_aux/extra-dist-cmd.py      |  89 +++++++++++++++
 tools/meson_aux/extra-dist-cmd.sh      |  51 ---------
 tools/meson_aux/tutorial-custom-cmd.py | 196 +++++++++++++++++++++++++++++++++
 tools/meson_aux/tutorial-custom-cmd.sh |  77 -------------
 16 files changed, 397 insertions(+), 206 deletions(-)
---
diff --git a/docs/tutorial/meson.build b/docs/tutorial/meson.build
index f9c70f9..a915116 100644
--- a/docs/tutorial/meson.build
+++ b/docs/tutorial/meson.build
@@ -1,12 +1,13 @@
 # docs/tutorial
 
-# input: gnome, install_datadir, gtkmm_pcname, tutorial_custom_cmd_sh, project_source_root
+# input: gnome, install_datadir, gtkmm_pcname, tutorial_custom_cmd,
+#        project_source_root, python3
 # output: can_parse_and_validate, build_translations_by_default, can_build_translations,
 #         build_pdf_by_default, can_build_pdf, tutorialdir
 
-# xsltproc is required by tutorial_custom_cmd_sh html.
+# xsltproc is required by tutorial_custom_cmd html.
 xsltproc = find_program('xsltproc', required: true)
-# perl is required by tutorial_custom_cmd_sh insert_example_code.
+# perl is required by tutorial_custom_cmd insert_example_code.
 perl = find_program('perl', required: true)
 xmllint = find_program('xmllint', required: false)
 
@@ -140,7 +141,7 @@ index_docbook = custom_target('index.docbook',
   input: 'C' / 'index-in.docbook',
   output: 'index.docbook',
   command: [
-    tutorial_custom_cmd_sh, 'insert_example_code',
+    python3, tutorial_custom_cmd, 'insert_example_code',
     meson.current_source_dir() / 'insert_example_code.pl',
     project_source_root / 'examples' / 'book',
     '@INPUT@',
@@ -154,9 +155,7 @@ custom_target('html_index.html',
   input: index_docbook,
   output: 'html',
   command: [
-    tutorial_custom_cmd_sh, 'html',
-    'html',
-    meson.current_build_dir(),
+    python3, tutorial_custom_cmd, 'html',
     '@INPUT@',
     '@OUTPUT@',    
   ],
@@ -171,7 +170,7 @@ if can_parse_and_validate
     input: index_docbook,
     output: 'C_xmllint.stamp',
     command: [
-      tutorial_custom_cmd_sh, 'xmllint',
+      python3, tutorial_custom_cmd, 'xmllint',
       validate,
       '@INPUT@',
       '@OUTPUT@'
@@ -187,7 +186,7 @@ if can_build_pdf
     input: index_docbook,
     output: 'programming-with-gtkmm.pdf',
     command: [
-      tutorial_custom_cmd_sh,
+      python3, tutorial_custom_cmd,
       dblatex.found() ? 'dblatex' : 'docbook2pdf',
       '@INPUT@',
       meson.current_source_dir() / 'C' / 'figures',
diff --git a/examples/book/buildapp/meson.build b/examples/book/buildapp/meson.build
index 724cfb8..2987452 100644
--- a/examples/book/buildapp/meson.build
+++ b/examples/book/buildapp/meson.build
@@ -1,7 +1,7 @@
 # examples/book/buildapp
 
-# input: gnome, gtkmm_dep, build_examples_by_default, compile_schemas_sh,
-#        copy_to_subdir_sh, meson_backend, test_timeout, project_build_root
+# input: gnome, gtkmm_dep, build_examples_by_default, compile_schemas, python3,
+#        copy_to_subdir, meson_backend, test_timeout, project_build_root
 # input and output: examples_targets
 
 exapp_main = ['exampleapplication.cc', 'exampleappwindow.cc', 'main.cc']
@@ -44,10 +44,9 @@ foreach ex : examples_book_buildapp
           input: dir / src,
           output: dir.underscorify() + '_gschemas.compiled',
           command: [
-            compile_schemas_sh,
-            dir,
-            meson.current_source_dir(),
-            meson.current_build_dir(),            
+            python3, compile_schemas,
+            meson.current_source_dir() / dir,
+            meson.current_build_dir() / dir,
             '@OUTPUT@'
           ]
         )
@@ -68,7 +67,7 @@ foreach ex : examples_book_buildapp
     input: exe_file,
     output: stamp_file_name,
     command: [
-      copy_to_subdir_sh,
+      python3, copy_to_subdir,
       '@INPUT@',
       dir,
       ex[1],
diff --git a/examples/book/giomm/meson.build b/examples/book/giomm/meson.build
index 62675f1..c6b51eb 100644
--- a/examples/book/giomm/meson.build
+++ b/examples/book/giomm/meson.build
@@ -1,7 +1,7 @@
 # examples/book/giomm
 
-# input: gnome, giomm_dep, build_examples_by_default, copy_to_subdir_sh,
-#        meson_backend, project_build_root
+# input: gnome, giomm_dep, build_examples_by_default, copy_to_subdir,
+#        meson_backend, project_build_root, python3
 # input and output: examples_targets
 
 examples_book_giomm = [
@@ -45,7 +45,7 @@ foreach ex : examples_book_giomm
     input: exe_file,
     output: stamp_file_name,
     command: [
-      copy_to_subdir_sh,
+      python3, copy_to_subdir,
       '@INPUT@',
       dir,
       ex[1],
diff --git a/examples/book/meson.build b/examples/book/meson.build
index b1ce70e..33c98c2 100644
--- a/examples/book/meson.build
+++ b/examples/book/meson.build
@@ -1,7 +1,7 @@
 # examples/book
 
 # input: gnome, gtkmm_dep, giomm_dep, build_examples_by_default,
-#        compile_schemas_sh, copy_to_subdir_sh, config_include_dir,
+#        compile_schemas, copy_to_subdir, config_include_dir, python3,
 #        meson_backend, test_timeout, project_build_root
 # input and output: examples_targets
 
@@ -142,7 +142,7 @@ foreach ex : examples_book
     input: exe_file,
     output: stamp_file_name,
     command: [
-      copy_to_subdir_sh,
+      python3, copy_to_subdir,
       '@INPUT@',
       dir,
       ex[1],
diff --git a/examples/book/treeview/meson.build b/examples/book/treeview/meson.build
index 80eed31..c154a96 100644
--- a/examples/book/treeview/meson.build
+++ b/examples/book/treeview/meson.build
@@ -1,7 +1,7 @@
 # examples/book/treeview
 
-# input: gnome, gtkmm_dep, build_examples_by_default, compile_schemas_sh,
-#        copy_to_subdir_sh, meson_backend, test_timeout, project_build_root
+# input: gnome, gtkmm_dep, build_examples_by_default, compile_schemas, python3,
+#        copy_to_subdir, meson_backend, test_timeout, project_build_root
 # input and output: examples_targets
 
 exwindow_main = ['examplewindow.cc', 'main.cc']
@@ -50,7 +50,7 @@ foreach ex : examples_book_treeview
     input: exe_file,
     output: stamp_file_name,
     command: [
-      copy_to_subdir_sh,
+      python3, copy_to_subdir,
       '@INPUT@',
       dir,
       ex[1],
diff --git a/examples/meson.build b/examples/meson.build
index 28d759a..78d808a 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -1,7 +1,7 @@
 # examples
 
-# input: gnome, gtkmm_dep, giomm_dep, compile_schemas_sh, copy_to_subdir_sh,
-#        project_build_root
+# input: gnome, gtkmm_dep, giomm_dep, compile_schemas, copy_to_subdir,
+#        project_build_root, python3
 # output: build_examples_by_default
 
 # examples/book/input/main.cc includes build/config.h.
@@ -16,7 +16,7 @@ custom_target('build_config',
   input: conf_file,
   output: 'config.stamp',
   command: [
-    copy_to_subdir_sh,
+    python3, copy_to_subdir,
     '@INPUT@',
     'build',
     'config.h',
diff --git a/examples/others/meson.build b/examples/others/meson.build
index 0599cf7..1472d05 100644
--- a/examples/others/meson.build
+++ b/examples/others/meson.build
@@ -1,7 +1,7 @@
 # examples/others
 
-# input: gnome, gtkmm_dep, build_examples_by_default, copy_to_subdir_sh,
-#        meson_backend, test_timeout, project_build_root
+# input: gnome, gtkmm_dep, build_examples_by_default, copy_to_subdir,
+#        meson_backend, test_timeout, project_build_root, python3
 # input and output: examples_targets
 
 examples_others = [
@@ -51,7 +51,7 @@ foreach ex : examples_others
     input: exe_file,
     output: stamp_file_name,
     command: [
-      copy_to_subdir_sh,
+      python3, copy_to_subdir,
       '@INPUT@',
       dir,
       ex[1],
diff --git a/meson.build b/meson.build
index 5da90ff..9cf1de2 100644
--- a/meson.build
+++ b/meson.build
@@ -5,10 +5,17 @@ project('gtkmm-documentation', 'c', 'cpp',
   default_options: [
     'cpp_std=c++17'
   ],
-  meson_version: '>= 0.49.0',
+  meson_version: '>= 0.50.0', # required for python3.path()
   license: 'GPLv2'
 )
 
+python3 = import('python').find_installation('python3')
+python_version = python3.language_version()
+python_version_req = '>= 3.5'
+if not python_version.version_compare(python_version_req)
+  error('Requires Python @0@, found @1@.'.format(python_version_req, python_version))
+endif
+
 gtkmm_pcname = 'gtkmm-4.0'
 gtkmm_dep = dependency(gtkmm_pcname, version: '>=3.95.1')
 giomm_dep = dependency('giomm-2.64', version: '>=2.63.1')
@@ -18,25 +25,27 @@ gnome = import('gnome')
 install_prefix = get_option('prefix')
 install_datadir = get_option('datadir')
 
-compile_schemas_sh = files('tools' / 'meson_aux' / 'compile-schemas.sh')
-copy_to_subdir_sh = files('tools' / 'meson_aux' / 'copy-to-subdir.sh')
-tutorial_custom_cmd_sh = files('tools' / 'meson_aux' / 'tutorial-custom-cmd.sh')
-
 # Use these instead of meson.source_root() and meson.build_root() in subdirectories.
 # source_root() and build_root() are not useful, if this is a subproject.
 project_source_root = meson.current_source_dir()
 project_build_root = meson.current_build_dir()
 
+script_dir = project_source_root / 'tools' / 'meson_aux'
+compile_schemas = script_dir / 'compile-schemas.py'
+copy_to_subdir = script_dir / 'copy-to-subdir.py'
+tutorial_custom_cmd = script_dir / 'tutorial-custom-cmd.py'
+extra_dist_cmd = script_dir / 'extra-dist-cmd.py'
+
 cpp_compiler = meson.get_compiler('cpp')
 
 warning_level = get_option('warnings')
 warning_flags = []
 if warning_level == 'min'
-  warning_flags = [ '-Wall' ]
+  warning_flags = ['-Wall']
 elif warning_level == 'max' or warning_level == 'fatal'
   warning_flags = '-pedantic -Wall -Wextra -Wformat-security -Wsuggest-override -Wshadow 
-Wno-long-long'.split()
   if warning_level == 'fatal'
-    warning_flags += [ '-Werror' ]
+    warning_flags += ['-Werror']
     deprecations = 'G PANGO ATK GDK GDK_PIXBUF GTK GLIBMM GIOMM GDKMM ATKMM PANGOMM GTKMM SIGCXX'.split()
     foreach d : deprecations
       warning_flags += '-D@0@_DISABLE_DEPRECATED'.format(d)
@@ -53,9 +62,9 @@ subdir('examples')
 if not meson.is_subproject()
   # Modify the contents of the distribution directory. (not allowed in a subproject)
   meson.add_dist_script(
-    'tools' / 'meson_aux' / 'extra-dist-cmd.sh',
-    meson.current_source_dir(),
-    meson.current_build_dir(),
+    python3.path(), extra_dist_cmd,
+    project_source_root,
+    project_build_root,
   )
 endif
 
diff --git a/tools/meson_aux/compile-schemas.py b/tools/meson_aux/compile-schemas.py
new file mode 100755
index 0000000..e0136e3
--- /dev/null
+++ b/tools/meson_aux/compile-schemas.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build
+
+#                      argv[1]      argv[2]       argv[3]
+# compile-schemas.py <schema_dir> <target_dir> <output_file>
+
+import os
+import sys
+import subprocess
+import shutil
+
+schema_dir = sys.argv[1]
+target_dir = sys.argv[2]
+output_file = sys.argv[3]
+
+# Create the target directory, if it does not exist.
+os.makedirs(target_dir, exist_ok=True)
+
+cmd = [
+  'glib-compile-schemas',
+  '--strict',
+  '--targetdir=' + target_dir,
+  schema_dir,
+]
+
+result = subprocess.run(cmd)
+if result.returncode == 0:
+  shutil.copy(os.path.join(target_dir, 'gschemas.compiled'), output_file)
+sys.exit(result.returncode)
diff --git a/tools/meson_aux/copy-to-subdir.py b/tools/meson_aux/copy-to-subdir.py
new file mode 100755
index 0000000..b11e3c8
--- /dev/null
+++ b/tools/meson_aux/copy-to-subdir.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build
+
+#                        argv[1]           argv[2]           argv[3]          argv[4]
+# copy-to-subdir.py <input_file_path> <relative_subdir> <output_file_name> <stamp_file_path>
+
+# <input_file_path> Input file, possibly including path.
+# <relative_subdir> To where the file shall be copied, relative to the input file's directory.
+# <output_file_name> Output file, without path.
+# <stamp_file_path> Stamp file, possibly including path.
+
+# Paths can be either absolute paths, or paths relative to the directory which
+# is current when this script is called.
+
+import os
+import sys
+import shutil
+from pathlib import Path
+
+input_file_path = sys.argv[1]
+relative_subdir = sys.argv[2]
+output_file_name = sys.argv[3]
+stamp_file_path = sys.argv[4]
+
+input_dir = os.path.dirname(input_file_path)
+target_dir = os.path.join(input_dir, relative_subdir)
+
+# Create the target directory, if it does not exist.
+os.makedirs(target_dir, exist_ok=True)
+
+# shutil.copy2() copies timestamps and some other file metadata.
+shutil.copy2(input_file_path, os.path.join(target_dir, output_file_name))
+
+Path(stamp_file_path).touch(exist_ok=True)
diff --git a/tools/meson_aux/extra-dist-cmd.py b/tools/meson_aux/extra-dist-cmd.py
new file mode 100755
index 0000000..3c9d72b
--- /dev/null
+++ b/tools/meson_aux/extra-dist-cmd.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with add_dist_script() in meson.build
+
+#                        argv[1]         argv[2]
+# extra-dist-cmd.py <root_source_dir> <root_build_dir>
+
+# Meson does not preserve timestamps on distributed files. Neither does this script.
+
+import os
+import sys
+import shutil
+import subprocess
+import re
+
+root_source_dir = sys.argv[1]
+root_build_dir = sys.argv[2]
+
+# Make a ChangeLog file for distribution.
+cmd = [
+  'git',
+  '--git-dir=' + os.path.join(root_source_dir, '.git'),
+  '--work-tree=' + root_source_dir,
+  'log',
+  '--no-merges',
+  '--date=short',
+  '--max-count=200',
+  '--pretty=tformat:%cd  %an  <%ae>%n%n  %s%n%w(0,0,2)%+b',
+]
+logfile = open(os.path.join(os.getenv('MESON_DIST_ROOT'), 'ChangeLog'), mode='w')
+result = subprocess.run(cmd, stdout=logfile)
+logfile.close()
+if result.returncode != 0:
+  sys.exit(result.returncode)
+
+# Distribute some built files in addition to the files in the local git clone.
+os.chdir(root_build_dir)
+dist_docs_tutorial = os.path.join(os.getenv('MESON_DIST_ROOT'), 'docs', 'tutorial')
+dist_docs_tutorial_C = os.path.join(dist_docs_tutorial, 'C')
+docs_tutorial_index_docbook = os.path.join('docs', 'tutorial', 'index.docbook')
+
+# English index.docbook and html files.
+# shutil.copy() does not copy timestamps.
+shutil.copy(docs_tutorial_index_docbook, dist_docs_tutorial_C)
+shutil.copytree(os.path.join('docs', 'tutorial', 'html'),
+                os.path.join(dist_docs_tutorial, 'html'),
+                copy_function=shutil.copy)
+
+# Read the distributed LINGUAS file, containing a list of available translations.
+linguas = os.path.join(dist_docs_tutorial, 'LINGUAS')
+langs = []
+if os.path.isfile(linguas):
+  linguas_file_obj = open(linguas)
+  buffer = linguas_file_obj.read().splitlines()
+  linguas_file_obj.close()
+  comment_pattern = re.compile(r'\s*(?:#|$)') # comment or blank line
+  for line in buffer:
+    if not comment_pattern.match(line):
+      langs += line.split()
+else:
+  print('=== Warning: File', linguas, 'not found.')
+
+# .gmo files with translations and translated index.docbook files.
+for lang in langs:
+  for file in [lang + '.gmo', 'index.docbook']:
+    shutil.copy(os.path.join('docs', 'tutorial', lang, file),
+                os.path.join(dist_docs_tutorial, lang))
+
+# If there is an updated PDF file, include it in the tarball.
+pdf_file = os.path.join('docs', 'tutorial', 'programming-with-gtkmm.pdf')
+if os.path.isfile(pdf_file) and \
+   os.stat(pdf_file).st_mtime > os.stat(docs_tutorial_index_docbook).st_mtime:
+  shutil.copy(pdf_file, dist_docs_tutorial_C)
+else:
+  print('--- Info: No updated PDF file found.')
+
+# Don't distribute .gitignore files.
+for dirpath, dirnames, filenames in os.walk(os.getenv('MESON_DIST_ROOT')):
+  if '.gitignore' in filenames:
+    os.remove(os.path.join(dirpath, '.gitignore'))
+
+# Remove an empty MESON_DIST_ROOT/build directory.
+dist_build_dir = os.path.join(os.getenv('MESON_DIST_ROOT'), 'build')
+if os.path.isdir(dist_build_dir):
+  try:
+    os.rmdir(dist_build_dir)
+  except OSError:
+    # Ignore the error, if not empty.
+    pass
diff --git a/tools/meson_aux/tutorial-custom-cmd.py b/tools/meson_aux/tutorial-custom-cmd.py
new file mode 100755
index 0000000..e39bd3d
--- /dev/null
+++ b/tools/meson_aux/tutorial-custom-cmd.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build
+
+#                           argv[1]   argv[2:]
+# tutorial-custom-cmd.py <subcommand> <xxx>...
+
+import os
+import sys
+import subprocess
+from pathlib import Path
+import shutil
+
+subcommand = sys.argv[1]
+
+def insert_example_code():
+  #      argv[2]            argv[3]             argv[4]         argv[5]
+  # <perl_script_file> <examples_book_dir> <input_xml_file> <output_xml_file>
+
+  perl_script_file = sys.argv[2]
+  examples_book_dir = sys.argv[3]
+  input_xml_file = sys.argv[4]
+  output_xml_file = sys.argv[5]
+
+  cmd = [
+    'perl',
+    '--',
+    perl_script_file,
+    examples_book_dir,
+    input_xml_file,
+  ]
+  xml_file = open(output_xml_file, mode='w')
+  result = subprocess.run(cmd, stdout=xml_file)
+  xml_file.close()
+  if result.returncode != 0:
+    return result.returncode
+
+  # Copy output_xml_file to the source directory.
+  shutil.copy(output_xml_file, os.path.dirname(input_xml_file))
+  return 0
+
+def html():
+  #      argv[2]          argv[3]
+  # <input_xml_file> <output_html_dir>
+
+  input_xml_file = sys.argv[2]
+  output_html_dir = sys.argv[3]
+
+  # Set the use.id.as.filename param so that we don't use the chapter / section
+  # number as the filename, otherwise the url will change every time anything is
+  # re-ordered or inserted in the documentation.
+  # For a list of available parameters, see http://docbook.sourceforge.net/release/xsl/current/doc/html/
+  xslt_params = [
+    '--param', 'toc.section.depth', '1',
+    '--stringparam', 'html.stylesheet', 'style.css',
+    '--stringparam', 'admon.graphics', '1',
+    '--stringparam', 'admon.graphics.path', 'icons/',
+    '--stringparam', 'admon.graphics.extension', '.png',
+    '--stringparam', 'chunker.output.indent', 'yes',
+    '--stringparam', 'chunker.output.encoding', 'UTF-8',
+    '--stringparam', 'navig.graphics', 'yes',
+    '--stringparam', 'navig.graphics.extension', '.png',
+    '--stringparam', 'navig.graphics.path', 'icons/',
+    '--stringparam', 'toc.list.type', 'ul',
+    '--stringparam', 'use.id.as.filename', '1',
+  ]
+  xslt_stylesheet = 'http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl'
+
+  # Remove old files and create the destination directory.
+  shutil.rmtree(output_html_dir, ignore_errors=True)
+  os.makedirs(output_html_dir, exist_ok=True)
+
+  cmd = [
+    'xsltproc',
+  ] + xslt_params + [
+    '-o', output_html_dir + '/',
+    '--xinclude',
+    xslt_stylesheet,
+    input_xml_file,
+  ]
+  result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+                          universal_newlines=True)
+  # xsltproc prints the names of all written files. Don't print those lines.
+  for line in result.stdout.splitlines():
+    if not line.startswith('Writing '):
+      print(line)
+
+  return result.returncode
+
+def xmllint():
+  #  argv[2]       argv[3]          argv[4]
+  # <validate> <input_xml_file> <stamp_file_path>
+
+  validate = sys.argv[2]
+  input_xml_file = sys.argv[3]
+  stamp_file_path = sys.argv[4]
+
+  cmd = [
+    'xmllint',
+    '--noout',
+    '--noent',
+    '--xinclude',
+  ]
+  if validate == 'true':
+    cmd += ['--postvalid']
+  cmd += [input_xml_file]
+  result = subprocess.run(cmd)
+  if result.returncode:
+    return result.returncode
+
+  Path(stamp_file_path).touch(exist_ok=True)
+  return 0
+
+def dblatex():
+  #      argv[2]        argv[3]        argv[4]
+  # <input_xml_file> <figures_dir> <output_pdf_file>
+  # Create a PDF file, using dblatex.
+
+  input_xml_file = sys.argv[2]
+  figures_dir = sys.argv[3]
+  output_pdf_file = sys.argv[4]
+
+  # For a list of available parameters, see http://dblatex.sourceforge.net/doc/manual/
+  dblatex_params = [
+    '-P', 'toc.section.depth=2',
+    '-P', 'paper.type=a4paper',
+  ]
+  figures_dir_parent = os.path.dirname(figures_dir)
+
+  cmd = [
+    'dblatex',
+  ] + dblatex_params + [
+    '-I', figures_dir_parent,
+    '-o', output_pdf_file,
+    '--pdf', input_xml_file,
+  ]
+  return subprocess.run(cmd).returncode
+
+def docbook2pdf():
+  #      argv[2]        argv[3]        argv[4]
+  # <input_xml_file> <figures_dir> <output_pdf_file>
+  # Create a PDF file, using docbook2pdf.
+
+  input_xml_file = sys.argv[2]
+  figures_dir = sys.argv[3]
+  output_pdf_file = sys.argv[4]
+
+  output_dir = os.path.dirname(output_pdf_file)
+  if not output_dir:
+    output_dir = '.'
+  output_basename = os.path.basename(output_pdf_file)
+  if output_basename.endswith('.pdf'):
+    output_basename = output_basename[:-4]
+  xml_file = os.path.join(output_dir, output_basename + '.xml')
+
+  # We need to produce a full examples XML with all of the XIncludes done.
+  cmd = [
+    'xmllint',
+    '--xinclude',
+    '--postvalid',
+    '--output', xml_file,
+    input_xml_file,
+  ]
+  result = subprocess.run(cmd)
+  if result.returncode:
+    return result.returncode
+
+  # We also need to copy the figures from the source directory, so they
+  # can be found from the XML file.
+  # By default, shutil.copytree() copies files with shutil.copy2(),
+  # which copies timestamps and some other file metadata.
+  # The destination directory must not exist when shutil.copytree() is called.
+  output_figures_dir = os.path.join(output_dir, os.path.basename(figures_dir))
+  shutil.rmtree(output_figures_dir, ignore_errors=True)
+  shutil.copytree(figures_dir, output_figures_dir)
+
+  cmd = [
+    'docbook2pdf',
+    '--output', output_dir,
+    xml_file,
+  ]
+  return subprocess.run(cmd).returncode
+
+# ----- Main -----
+if subcommand == 'insert_example_code':
+  sys.exit(insert_example_code())
+if subcommand == 'html':
+  sys.exit(html())
+if subcommand == 'xmllint':
+  sys.exit(xmllint())
+if subcommand == 'dblatex':
+  sys.exit(dblatex())
+if subcommand == 'docbook2pdf':
+  sys.exit(docbook2pdf())
+print(sys.argv[0], ': illegal subcommand,', subcommand)
+sys.exit(1)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]