Skip to content

Commit

Permalink
Merge pull request #5983 from tk0miya/separate_applehelp
Browse files Browse the repository at this point in the history
Separate applehelp to sphinxcontrib package
  • Loading branch information
tk0miya authored Feb 5, 2019
2 parents 20edbe9 + c439731 commit ff80d2f
Show file tree
Hide file tree
Showing 11 changed files with 32 additions and 318 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Dependencies
* The sphinxcontrib-websupport package is no longer a dependency
* Some packages are separated to sub packages:

- sphinxcontrib.applehelp
- sphinxcontrib.devhelp
- sphinxcontrib.jsmath
- sphinxcontrib.qthelp
Expand Down
5 changes: 5 additions & 0 deletions doc/extdev/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ The following is a list of deprecated interfaces.
- 4.0
- ``docutils.nodes.abbreviation``

* - ``sphinx.builders.applehelp``
- 2.0
- 4.0
- ``sphinxcontrib.applehelp``

* - ``sphinx.builders.devhelp``
- 2.0
- 4.0
Expand Down
6 changes: 5 additions & 1 deletion doc/usage/builders/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The builder's "name" must be given to the **-b** command-line option of

.. _Qt help: https://doc.qt.io/qt-4.8/qthelp-framework.html

.. module:: sphinx.builders.applehelp
.. module:: sphinxcontrib.applehelp
.. class:: AppleHelpBuilder

This builder produces an Apple Help Book based on the same output as the
Expand All @@ -117,6 +117,10 @@ The builder's "name" must be given to the **-b** command-line option of

.. versionadded:: 1.3

.. versionchanged:: 2.0

Moved to sphinxcontrib.applehelp from sphinx.builders package.

.. module:: sphinxcontrib.devhelp
.. class:: DevhelpBuilder

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
sys.exit(1)

install_requires = [
'sphinxcontrib-applehelp',
'sphinxcontrib-devhelp',
'sphinxcontrib-jsmath',
'sphinxcontrib-qthelp',
Expand Down
2 changes: 1 addition & 1 deletion sphinx/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@

builtin_extensions = (
'sphinx.addnodes',
'sphinx.builders.applehelp',
'sphinx.builders.changes',
'sphinx.builders.epub3',
'sphinx.builders.dummy',
Expand Down Expand Up @@ -106,6 +105,7 @@
'sphinx.environment.collectors.toctree',
'sphinx.environment.collectors.indexentries',
# 1st party extensions
'sphinxcontrib.applehelp',
'sphinxcontrib.devhelp',
'sphinxcontrib.qthelp',
# Strictly, alabaster theme is not a builtin extension,
Expand Down
262 changes: 18 additions & 244 deletions sphinx/builders/applehelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,262 +8,36 @@
:license: BSD, see LICENSE for details.
"""

import plistlib
import shlex
import subprocess
from os import path, environ
from subprocess import CalledProcessError, PIPE, STDOUT
import warnings

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 import SkipProgressMessage, progress_message
from sphinx.util.fileutil import copy_asset, copy_asset_file
from sphinx.util.matching import Matcher
from sphinx.util.osutil import ensuredir, make_filename
from sphinxcontrib.applehelp import (
AppleHelpCodeSigningFailed,
AppleHelpIndexerFailed,
AppleHelpBuilder,
)

from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias

if False:
# For type annotation
from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA


logger = logging.getLogger(__name__)
template_dir = path.join(package_dir, 'templates', 'applehelp')


class AppleHelpIndexerFailed(SphinxError):
category = __('Help indexer failed')


class AppleHelpCodeSigningFailed(SphinxError):
category = __('Code signing failed')


class AppleHelpBuilder(StandaloneHTMLBuilder):
"""
Builder that outputs an Apple help book. Requires Mac OS X as it relies
on the ``hiutil`` command line tool.
"""
name = 'applehelp'
epilog = __('The help book is in %(outdir)s.\n'
'Note that won\'t be able to view it unless you put it in '
'~/Library/Documentation/Help or install it in your application '
'bundle.')

# don't copy the reST source
copysource = False
supported_image_types = ['image/png', 'image/gif', 'image/jpeg',
'image/tiff', 'image/jp2', 'image/svg+xml']

# don't add links
add_permalinks = False

# this is an embedded HTML format
embedded = True

# don't generate the search index or include the search page
search = False

def init(self):
# type: () -> None
super().init()
# the output files for HTML help must be .html only
self.out_suffix = '.html'
self.link_suffix = '.html'

if self.config.applehelp_bundle_id is None:
raise SphinxError(__('You must set applehelp_bundle_id before '
'building Apple Help output'))

self.bundle_path = path.join(self.outdir,
self.config.applehelp_bundle_name + '.help')
self.outdir = path.join(self.bundle_path,
'Contents',
'Resources',
self.config.applehelp_locale + '.lproj')

def handle_finish(self):
# type: () -> None
super().handle_finish()

self.finish_tasks.add_task(self.copy_localized_files)
self.finish_tasks.add_task(self.build_helpbook)

@progress_message(__('copying localized files'))
def copy_localized_files(self):
# type: () -> None
source_dir = path.join(self.confdir, self.config.applehelp_locale + '.lproj')
target_dir = self.outdir

if path.isdir(source_dir):
excluded = Matcher(self.config.exclude_patterns + ['**/.*'])
copy_asset(source_dir, target_dir, excluded,
context=self.globalcontext, renderer=self.templates)

def build_helpbook(self):
# type: () -> None
contents_dir = path.join(self.bundle_path, 'Contents')
resources_dir = path.join(contents_dir, 'Resources')
language_dir = path.join(resources_dir,
self.config.applehelp_locale + '.lproj')
ensuredir(language_dir)

self.build_info_plist(contents_dir)
self.copy_applehelp_icon(resources_dir)
self.build_access_page(language_dir)
self.build_helpindex(language_dir)

if self.config.applehelp_codesign_identity:
self.do_codesign()

@progress_message(__('writing Info.plist'))
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,
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundlePackageType': 'BNDL',
'CFBundleShortVersionString': self.config.release,
'CFBundleSignature': 'hbwr',
'CFBundleVersion': self.config.applehelp_bundle_version,
'HPDBookAccessPath': '_access.html',
'HPDBookIndexPath': 'search.helpindex',
'HPDBookTitle': self.config.applehelp_title,
'HPDBookType': '3',
'HPDBookUsesExternalViewer': False,
}

if self.config.applehelp_icon is not None:
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
info_plist['HPDBookKBURL'] = self.config.applehelp_kb_url

if self.config.applehelp_remote_url is not None:
info_plist['HPDBookRemoteURL'] = self.config.applehelp_remote_url

with open(path.join(contents_dir, 'Info.plist'), 'wb') as f:
plistlib.dump(info_plist, f)

def copy_applehelp_icon(self, resources_dir):
# type: (str) -> None
"""Copy the icon, if one is supplied."""
if self.config.applehelp_icon:

try:
with progress_message(__('copying icon... ')):
applehelp_icon = path.join(self.srcdir, self.config.applehelp_icon)
copy_asset_file(applehelp_icon, resources_dir)
except Exception as err:
logger.warning(__('cannot copy icon file %r: %s'), applehelp_icon, err)

@progress_message(__('building access page'))
def build_access_page(self, language_dir):
# type: (str) -> None
"""Build the access page."""
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)

@progress_message(__('generating help index'))
def build_helpindex(self, language_dir):
# type: (str) -> None
"""Generate the help index."""
args = [
self.config.applehelp_indexer_path,
'-Cf',
path.join(language_dir, 'search.helpindex'),
language_dir
]

if self.config.applehelp_index_anchors is not None:
args.append('-a')

if self.config.applehelp_min_term_length is not None:
args += ['-m', '%s' % self.config.applehelp_min_term_length]

if self.config.applehelp_stopwords is not None:
args += ['-s', self.config.applehelp_stopwords]

if self.config.applehelp_locale is not None:
args += ['-l', self.config.applehelp_locale]

if self.config.applehelp_disable_external_tools:
raise SkipProgressMessage(__('you will need to index this help book with:\n %s'),
' '.join([shlex.quote(arg) for arg in args]))
else:
try:
subprocess.run(args, stdout=PIPE, stderr=STDOUT, check=True)
except OSError:
raise AppleHelpIndexerFailed(__('Command not found: %s') % args[0])
except CalledProcessError as exc:
raise AppleHelpIndexerFailed(exc.stdout)

@progress_message(__('signing help book'))
def do_codesign(self):
# type: () -> None
"""If we've been asked to, sign the bundle."""
args = [
self.config.applehelp_codesign_path,
'-s', self.config.applehelp_codesign_identity,
'-f'
]

args += self.config.applehelp_codesign_flags

args.append(self.bundle_path)

if self.config.applehelp_disable_external_tools:
raise SkipProgressMessage(__('you will need to sign this help book with:\n %s'),
' '.join([shlex.quote(arg) for arg in args]))
else:
try:
subprocess.run(args, stdout=PIPE, stderr=STDOUT, check=True)
except OSError:
raise AppleHelpCodeSigningFailed(__('Command not found: %s') % args[0])
except CalledProcessError as exc:
raise AppleHelpCodeSigningFailed(exc.stdout)
deprecated_alias('sphinx.builders.applehelp',
{
'AppleHelpCodeSigningFailed': AppleHelpCodeSigningFailed,
'AppleHelpIndexerFailed': AppleHelpIndexerFailed,
'AppleHelpBuilder': AppleHelpBuilder,
},
RemovedInSphinx40Warning)


def setup(app):
# type: (Sphinx) -> Dict[str, Any]
app.setup_extension('sphinx.builders.html')
app.add_builder(AppleHelpBuilder)

app.add_config_value('applehelp_bundle_name',
lambda self: make_filename(self.project), 'applehelp')
app.add_config_value('applehelp_bundle_id', None, 'applehelp', [str])
app.add_config_value('applehelp_dev_region', 'en-us', 'applehelp')
app.add_config_value('applehelp_bundle_version', '1', 'applehelp')
app.add_config_value('applehelp_icon', None, 'applehelp', [str])
app.add_config_value('applehelp_kb_product',
lambda self: '%s-%s' % (make_filename(self.project), self.release),
'applehelp')
app.add_config_value('applehelp_kb_url', None, 'applehelp', [str])
app.add_config_value('applehelp_remote_url', None, 'applehelp', [str])
app.add_config_value('applehelp_index_anchors', False, 'applehelp', [str])
app.add_config_value('applehelp_min_term_length', None, 'applehelp', [str])
app.add_config_value('applehelp_stopwords',
lambda self: self.language or 'en', 'applehelp')
app.add_config_value('applehelp_locale', lambda self: self.language or 'en', 'applehelp')
app.add_config_value('applehelp_title', lambda self: self.project + ' Help', 'applehelp')
app.add_config_value('applehelp_codesign_identity',
lambda self: environ.get('CODE_SIGN_IDENTITY', None),
'applehelp')
app.add_config_value('applehelp_codesign_flags',
lambda self: shlex.split(environ.get('OTHER_CODE_SIGN_FLAGS', '')),
'applehelp')
app.add_config_value('applehelp_indexer_path', '/usr/bin/hiutil', 'applehelp')
app.add_config_value('applehelp_codesign_path', '/usr/bin/codesign', 'applehelp')
app.add_config_value('applehelp_disable_external_tools', False, None)
warnings.warn('sphinx.builders.applehelp has been moved to sphinxcontrib-applehelp.',
RemovedInSphinx40Warning)
app.setup_extension('sphinxcontrib.applehelp')

return {
'version': 'builtin',
Expand Down
12 changes: 0 additions & 12 deletions sphinx/templates/applehelp/_access.html_t

This file was deleted.

3 changes: 0 additions & 3 deletions tests/roots/test-root/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@
html_last_updated_fmt = '%b %d, %Y'
html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'}

applehelp_bundle_id = 'org.sphinx-doc.Sphinx.help'
applehelp_disable_external_tools = True

latex_additional_files = ['svgimg.svg']

coverage_c_path = ['special/*.h']
Expand Down
2 changes: 0 additions & 2 deletions tests/roots/test-root/en.lproj/localized.txt

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir):
[
# note: no 'html' - if it's ok with dirhtml it's ok with html
'dirhtml', 'singlehtml', 'pickle', 'json', 'text', 'htmlhelp',
'applehelp', 'changes', 'xml', 'pseudoxml', 'linkcheck',
'changes', 'xml', 'pseudoxml', 'linkcheck',
],
)
@mock.patch('sphinx.builders.linkcheck.requests.head',
Expand Down
Loading

0 comments on commit ff80d2f

Please sign in to comment.