diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py
index e87d47fda..43969a7eb 100644
--- a/sphinx/builders/applehelp.py
+++ b/sphinx/builders/applehelp.py
@@ -8,21 +8,21 @@
:license: BSD, see LICENSE for details.
"""
-import html
-import pipes
import plistlib
import shlex
import subprocess
from os import path, environ
+from subprocess import CalledProcessError, PIPE, STDOUT
+from sphinx import package_dir
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.errors import SphinxError
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.console import bold # type: ignore
-from sphinx.util.fileutil import copy_asset
+from sphinx.util.fileutil import copy_asset, copy_asset_file
from sphinx.util.matching import Matcher
-from sphinx.util.osutil import copyfile, ensuredir, make_filename
+from sphinx.util.osutil import ensuredir, make_filename
if False:
# For type annotation
@@ -31,22 +31,7 @@ if False:
logger = logging.getLogger(__name__)
-
-# False access page (used because helpd expects strict XHTML)
-access_page_template = '''\
-
-
-
- %(title)s
-
-
-
-
-
-
-
-'''
+template_dir = path.join(package_dir, 'templates', 'applehelp')
class AppleHelpIndexerFailed(SphinxError):
@@ -128,13 +113,17 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
resources_dir = path.join(contents_dir, 'Resources')
language_dir = path.join(resources_dir,
self.config.applehelp_locale + '.lproj')
+ ensuredir(language_dir)
- for d in [contents_dir, resources_dir, language_dir]:
- ensuredir(d)
-
- # Construct the Info.plist file
- toc = self.config.master_doc + self.out_suffix
+ self.build_info_plist(contents_dir)
+ self.copy_applehelp_icon(resources_dir)
+ self.build_access_page(language_dir)
+ self.build_helpindex(language_dir)
+ self.do_codesign()
+ def build_info_plist(self, contents_dir):
+ # type: (str) -> None
+ """Construct the Info.plist file."""
info_plist = {
'CFBundleDevelopmentRegion': self.config.applehelp_dev_region,
'CFBundleIdentifier': self.config.applehelp_bundle_id,
@@ -151,8 +140,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
}
if self.config.applehelp_icon is not None:
- info_plist['HPDBookIconPath'] \
- = path.basename(self.config.applehelp_icon)
+ info_plist['HPDBookIconPath'] = path.basename(self.config.applehelp_icon)
if self.config.applehelp_kb_url is not None:
info_plist['HPDBookKBProduct'] = self.config.applehelp_kb_product
@@ -162,34 +150,37 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
info_plist['HPDBookRemoteURL'] = self.config.applehelp_remote_url
logger.info(bold(__('writing Info.plist... ')), nonl=True)
- with open(path.join(contents_dir, 'Info.plist'), 'wb') as fb:
- plistlib.dump(info_plist, fb)
+ with open(path.join(contents_dir, 'Info.plist'), 'wb') as f:
+ plistlib.dump(info_plist, f)
logger.info(__('done'))
- # Copy the icon, if one is supplied
+ def copy_applehelp_icon(self, resources_dir):
+ # type: (str) -> None
+ """Copy the icon, if one is supplied."""
if self.config.applehelp_icon:
logger.info(bold(__('copying icon... ')), nonl=True)
try:
- copyfile(path.join(self.srcdir, self.config.applehelp_icon),
- path.join(resources_dir, info_plist['HPDBookIconPath']))
-
+ applehelp_icon = path.join(self.srcdir, self.config.applehelp_icon)
+ copy_asset_file(applehelp_icon, resources_dir)
logger.info(__('done'))
except Exception as err:
- logger.warning(__('cannot copy icon file %r: %s'),
- path.join(self.srcdir, self.config.applehelp_icon), err)
- del info_plist['HPDBookIconPath']
+ logger.warning(__('cannot copy icon file %r: %s'), applehelp_icon, err)
- # Build the access page
+ def build_access_page(self, language_dir):
+ # type: (str) -> None
+ """Build the access page."""
logger.info(bold(__('building access page...')), nonl=True)
- with open(path.join(language_dir, '_access.html'), 'w') as ft:
- ft.write(access_page_template % {
- 'toc': html.escape(toc, quote=True),
- 'title': html.escape(self.config.applehelp_title)
- })
+ context = {
+ 'toc': self.config.master_doc + self.out_suffix,
+ 'title': self.config.applehelp_title,
+ }
+ copy_asset_file(path.join(template_dir, '_access.html_t'), language_dir, context)
logger.info(__('done'))
- # Generate the help index
+ def build_helpindex(self, language_dir):
+ # type: (str) -> None
+ """Generate the help index."""
logger.info(bold(__('generating help index... ')), nonl=True)
args = [
@@ -213,25 +204,20 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
if self.config.applehelp_disable_external_tools:
logger.info(__('skipping'))
-
logger.warning(__('you will need to index this help book with:\n %s'),
- ' '.join([pipes.quote(arg) for arg in args]))
+ ' '.join([shlex.quote(arg) for arg in args]))
else:
try:
- p = subprocess.Popen(args,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
-
- output = p.communicate()[0]
-
- if p.returncode != 0:
- raise AppleHelpIndexerFailed(output)
- else:
- logger.info(__('done'))
+ subprocess.run(args, stdout=PIPE, stderr=STDOUT, check=True)
+ logger.info(__('done'))
except OSError:
raise AppleHelpIndexerFailed(__('Command not found: %s') % args[0])
+ except CalledProcessError as exc:
+ raise AppleHelpCodeSigningFailed(exc.stdout)
- # If we've been asked to, sign the bundle
+ def do_codesign(self):
+ # type: () -> None
+ """If we've been asked to, sign the bundle."""
if self.config.applehelp_codesign_identity:
logger.info(bold(__('signing help book... ')), nonl=True)
@@ -248,21 +234,15 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
if self.config.applehelp_disable_external_tools:
logger.info(__('skipping'))
logger.warning(__('you will need to sign this help book with:\n %s'),
- ' '.join([pipes.quote(arg) for arg in args]))
+ ' '.join([shlex.quote(arg) for arg in args]))
else:
try:
- p = subprocess.Popen(args,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
-
- output = p.communicate()[0]
-
- if p.returncode != 0:
- raise AppleHelpCodeSigningFailed(output)
- else:
- logger.info(__('done'))
+ subprocess.run(args, stdout=PIPE, stderr=STDOUT, check=True)
+ logger.info(__('done'))
except OSError:
raise AppleHelpCodeSigningFailed(__('Command not found: %s') % args[0])
+ except CalledProcessError as exc:
+ raise AppleHelpCodeSigningFailed(exc.stdout)
def setup(app):
diff --git a/sphinx/templates/applehelp/_access.html_t b/sphinx/templates/applehelp/_access.html_t
new file mode 100644
index 000000000..aa6b2dcc4
--- /dev/null
+++ b/sphinx/templates/applehelp/_access.html_t
@@ -0,0 +1,12 @@
+
+
+
+ {{ title|e }}
+
+
+
+
+
+
+