diff --git a/CHANGES b/CHANGES index 6501975eb..7f7b28a4e 100644 --- a/CHANGES +++ b/CHANGES @@ -111,6 +111,8 @@ Bugs fixed * Inline math in parsed-literal is not rendered well by LaTeX (ref #3340) * #3308: Parsed-literals don't wrap very long lines with pdf builder (ref #3340) * #3295: Could not import extension sphinx.builders.linkcheck +* #3285: autosummary: asterisks are escaped twice +* LaTeX, pass dvipdfm option to geometry package for Japanese documents (ref #3363) Release 1.5.1 (released Dec 13, 2016) diff --git a/doc/config.rst b/doc/config.rst index c8a99a5ab..5613d0bd6 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1523,8 +1523,8 @@ These options influence LaTeX output. See further :doc:`latex`. backslash or ampersand must be represented by the proper LaTeX commands if they are to be inserted literally. * *author*: Author for the LaTeX document. The same LaTeX markup caveat as - for *title* applies. Use ``\and`` to separate multiple authors, as in: - ``'John \and Sarah'``. + for *title* applies. Use ``\\and`` to separate multiple authors, as in: + ``'John \\and Sarah'`` (backslashes must be Python-escaped to reach LaTeX). * *documentclass*: Normally, one of ``'manual'`` or ``'howto'`` (provided by Sphinx and based on ``'report'``, resp. ``'article'``; Japanese documents use ``'jsbook'``, resp. ``'jreport'``.) "howto" (non-Japanese) @@ -1656,6 +1656,11 @@ These options influence LaTeX output. See further :doc:`latex`. ``'\\usepackage[margin=1in,marginparwidth=0.5in]{geometry}'``. .. versionadded:: 1.5 + + .. versionchanged:: 1.5.2 + For Japanese documents also ``dvipdfm`` option is passed to + ``geometry``. + ``'babel'`` "babel" package inclusion, default ``'\\usepackage{babel}'`` (the suitable document language string is passed as class option, and diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 4f3ce4c65..4995c0261 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -319,7 +319,6 @@ class Autosummary(Directive): else: max_chars = max(10, max_item_chars - len(display_name)) sig = mangle_signature(sig, max_chars=max_chars) - sig = sig.replace('*', r'\*') # -- Grab the summary diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 199ec86e9..3eea2ffe7 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -120,7 +120,7 @@ % some font styling. \DeclareStringOption[\sffamily\bfseries]{HeaderFamily} % colours -% same problems as for dimensions: we want the key handler to use \definecolor +% same problems as for dimensions: we want the key handler to use \definecolor. % first, some colours with no prefix, for backwards compatibility \newcommand*{\sphinxDeclareColorOption}[2]{% \definecolor{#1}#2% @@ -162,8 +162,8 @@ % user interface: options can be changed midway in a document! \newcommand\sphinxsetup[1]{\setkeys{sphinx}{#1}} -% this is the \ltx@ifundefined of ltxcmds.sty, which is loaded by -% hyperref.sty, but we need it before, and the first release of +% this is the \ltx@ifundefined of ltxcmds.sty, which was loaded by +% kvoptions already, (and later by hyperref), but the first release of % ltxcmds.sty as in TL2009/Debian has wrong definition. \newcommand{\spx@ifundefined}[1]{% \ifcsname #1\endcsname @@ -211,7 +211,8 @@ \pagestyle{empty} % start this way -% Use this to set the font family for headers and other decor: +% Since Sphinx 1.5, users should use HeaderFamily key to 'sphinxsetup' rather +% than defining their own \py@HeaderFamily command (which is still possible). \newcommand{\py@HeaderFamily}{\spx@opt@HeaderFamily} % Redefine the 'normal' header/footer style when using "fancyhdr" package: @@ -287,9 +288,9 @@ % - with possibly of a top caption, non-separable by pagebreak. % - and usable inside tables or footnotes ("footnotehyper-sphinx"). -% For maintaining compatibility with Sphinx < 1.5, we define and use these -% when (unmodified) Verbatim will be needed. But Sphinx >= 1.5 does not modify -% original Verbatim anyhow. +% For extensions which use \OriginalVerbatim and compatibility with Sphinx < +% 1.5, we define and use these when (unmodified) Verbatim will be needed. But +% Sphinx >= 1.5 does not modify the \Verbatim macro anymore. \let\OriginalVerbatim \Verbatim \let\endOriginalVerbatim\endVerbatim @@ -376,7 +377,7 @@ % {, <, #, %, $, ' and ": go to next line. % _, }, ^, &, >, - and ~: stay at end of broken line. % Use of \textquotesingle for straight quote. -% FIXME: convert this to package options +% FIXME: convert this to package options ? \newcommand*\sphinxbreaksbeforelist {% \do\PYGZob\{\do\PYGZlt\<\do\PYGZsh\#\do\PYGZpc\%% {, <, #, %, \do\PYGZdl\$\do\PYGZdq\"% $, " @@ -398,8 +399,8 @@ \def\sphinx@verbatim@nolig@list {\do \`}% % Some characters . , ; ? ! / are not pygmentized. -% This macro makes them "active" and they will insert potential linebreaks -% In math mode, the characters are de-activated. +% This macro makes them "active" and they will insert potential linebreaks. +% Not compatible with math mode (cf \sphinxunactivateextras). \newcommand*\sphinxbreaksbeforeactivelist {}% none \newcommand*\sphinxbreaksafteractivelist {\do\.\do\,\do\;\do\?\do\!\do\/} \newcommand*\sphinxbreaksviaactive {% @@ -554,18 +555,19 @@ } \newcommand*\sphinxbreaksviaactiveinparsedliteral{% \sphinxbreaksviaactive % by default handles . , ; ? ! / - \do\-% we need also the hyphen character + \do\-% we need also the hyphen character (ends up "as is" in parsed-literal) \lccode`\~`\~ % % update \dospecials as it is used by \url - % but deactivation will already have been done hence commented out + % but deactivation will already have been done hence this is unneeded: % \expandafter\def\expandafter\dospecials\expandafter{\dospecials % \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist\do\-}% } \newcommand*\sphinxbreaksatspaceinparsedliteral{% \lccode`~32 \lowercase{\let~}\spx@verbatim@space\lccode`\~`\~ } -% now the hack for \url to work (hyperref is required dependency): -% the aim it to deactivate - . , ; ? ! / in \url's argument +% now the hack for \url to work (hyperref is assumed in use): +% the aim it to deactivate - . , ; ? ! / in \url's argument. +% also the space token, but not end of lines which we assume don't arise there. \def\spx@hack@hyper@normalise {% \expandafter\spx@hack@hyper@normalise@aux\hyper@normalise \spx@hack@hyper@normalise@aux\hyper@n@rmalise\relax\spx@undefined @@ -581,6 +583,7 @@ }% \newcommand*{\sphinxunactivateextras}{\let\do\@makeother \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist\do\-}% +% the \catcode13=5\relax (deactivate end of input lines) is left to callers \newcommand*{\sphinxunactivateextrasandspace}{\catcode32=10\relax \sphinxunactivateextras}% % now for the modified alltt environment @@ -597,7 +600,9 @@ % alltt takes care of the ' as derivative ("prime") in math mode \everymath\expandafter{\the\everymath\sphinxunactivateextrasandspace \catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }% - \everydisplay\expandafter{\the\everydisplay\sphinxunactivateextrasandspace +% not sure if displayed math (align,...) can end up in parsed-literal, anyway + \everydisplay\expandafter{\the\everydisplay + \catcode13=5\sphinxunactivateextrasandspace \catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }% \fi } {\end{alltt}} diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 56182755b..336fe0ac2 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -126,6 +126,8 @@ ADDITIONAL_SETTINGS = { }, 'platex': { 'latex_engine': 'platex', + 'geometry': ('\\usepackage[margin=1in,marginparwidth=0.5in,dvipdfm]' + '{geometry}'), }, } # type: Dict[unicode, Dict[unicode, unicode]] diff --git a/tests/roots/test-autosummary/dummy_module.py b/tests/roots/test-autosummary/dummy_module.py index 1f4a47378..d24d7604f 100644 --- a/tests/roots/test-autosummary/dummy_module.py +++ b/tests/roots/test-autosummary/dummy_module.py @@ -71,5 +71,5 @@ class C: ''' -def func(arg_): +def func(arg_, *args, **kwargs): """Test function take an argument ended with underscore.""" diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 84c73d632..f53b7c2c5 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -95,3 +95,11 @@ def test_get_items_summary(app, status, warning): for key, expected in iteritems(expected_values): assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\ ' expected %r' % (key, autosummary_items[key], expected) + + # check an item in detail + assert 'func' in autosummary_items + func_attrs = ('func', + '(arg_, *args, **kwargs)', + 'Test function take an argument ended with underscore.', + 'dummy_module.func') + assert autosummary_items['func'] == func_attrs diff --git a/utils/CHANGES_template b/utils/CHANGES_template new file mode 100644 index 000000000..344a49eae --- /dev/null +++ b/utils/CHANGES_template @@ -0,0 +1,17 @@ +Release x.y.z (in development) +============================== + +Incompatible changes +-------------------- + +Deprecated +---------- + +Features added +-------------- + +Bugs fixed +---------- + +Testing +-------- diff --git a/utils/bump_version.py b/utils/bump_version.py new file mode 100755 index 000000000..617c33c0c --- /dev/null +++ b/utils/bump_version.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import os +import re +import sys +from datetime import datetime +from contextlib import contextmanager + +script_dir = os.path.dirname(__file__) +package_dir = os.path.abspath(os.path.join(script_dir, '..')) + +RELEASE_TYPE = {'a': 'alpha', 'b': 'beta'} + + +def stringify_version(version_info): + if version_info[2] == 0: + return '.'.join(str(v) for v in version_info[:2]) + else: + return '.'.join(str(v) for v in version_info[:3]) + + +def bump_version(path, version_info): + version = stringify_version(version_info) + release = version + if version_info[3] != 'final': + version += '+' + + with open(path, 'r+') as f: + body = f.read() + body = re.sub("(?<=__version__ = ')[^']+", version, body) + body = re.sub("(?<=__released__ = ')[^']+", release, body) + body = re.sub("(?<=version_info = )\(.*\)", str(version_info), body) + + f.seek(0) + f.truncate(0) + f.write(body) + + +def parse_version(version): + matched = re.search('^(\d+)\.(\d+)$', version) + if matched: + major, minor = matched.groups() + return (int(major), int(minor), 0, 'final', 0) + + matched = re.search('^(\d+)\.(\d+)\.(\d+)$', version) + if matched: + major, minor, rev = matched.groups() + return (int(major), int(minor), int(rev), 'final', 0) + + matched = re.search('^(\d+)\.(\d+)\s*(a|b|alpha|beta)(\d+)$', version) + if matched: + major, minor, typ, relver = matched.groups() + release = RELEASE_TYPE.get(typ, typ) + return (int(major), int(minor), 0, release, int(relver)) + + matched = re.search('^(\d+)\.(\d+)\.(\d+)\s*(a|b|alpha|beta)(\d+)$', version) + if matched: + major, minor, rev, typ, relver = matched.groups() + release = RELEASE_TYPE.get(typ, typ) + return (int(major), int(minor), int(rev), release, int(relver)) + + raise RuntimeError('Unknown vesion: %s' % version) + + +class Skip(Exception): + pass + + +@contextmanager +def processing(message): + try: + print(message + ' ... ', end='') + yield + except Skip as exc: + print('skip: %s' % exc) + except: + print('error') + raise + else: + print('done') + + +class Changes(object): + def __init__(self, path): + self.path = path + self.fetch_version() + + def fetch_version(self): + with open(self.path) as f: + version = f.readline().strip() + matched = re.search('^Release (.*) \((.*)\)$', version) + if matched is None: + raise RuntimeError('Unknown CHANGES format: %s' % version) + + self.version, self.release_date = matched.groups() + self.version_info = parse_version(self.version) + if self.release_date == 'in development': + self.in_development = True + else: + self.in_development = False + + def finalize_release_date(self): + release_date = datetime.now().strftime('%b %d, %Y') + heading = 'Release %s (released %s)' % (self.version, release_date) + + with open(self.path, 'r+') as f: + f.readline() # skip first two lines + f.readline() + body = f.read() + + f.seek(0) + f.truncate(0) + f.write(heading + '\n') + f.write('=' * len(heading) + '\n') + f.write(body) + + def add_release(self, version_info): + if version_info[-2:] in (('beta', 0), ('final', 0)): + version = stringify_version(version_info) + else: + reltype = version_info[3] + version = '%s %s%s' % (stringify_version(version_info), + RELEASE_TYPE.get(reltype, reltype), + version_info[4] or '') + heading = 'Release %s (in development)' % version + + with open(os.path.join(script_dir, 'CHANGES_template')) as f: + f.readline() # skip first two lines + f.readline() + tmpl = f.read() + + with open(self.path, 'r+') as f: + body = f.read() + + f.seek(0) + f.truncate(0) + f.write(heading + '\n') + f.write('=' * len(heading) + '\n') + f.write(tmpl) + f.write('\n') + f.write(body) + + +def main(): + if len(sys.argv) != 2: + print("bump_version.py [version]") + return -1 + + version_info = parse_version(sys.argv[-1]) + + with processing("Rewriting sphinx/__init__.py"): + bump_version(os.path.join(package_dir, 'sphinx/__init__.py'), version_info) + + with processing('Rewriting CHANGES'): + changes = Changes(os.path.join(package_dir, 'CHANGES')) + if changes.version_info == version_info: + if changes.in_development: + changes.finalize_release_date() + else: + raise Skip('version not changed') + else: + if changes.in_development: + print('WARNING: last version is not released yet: %s' % changes.version) + changes.add_release(version_info) + + +if __name__ == '__main__': + main() diff --git a/utils/release-checklist b/utils/release-checklist index c4c9f48bf..610ab9d19 100644 --- a/utils/release-checklist +++ b/utils/release-checklist @@ -9,8 +9,8 @@ Release checklist * Run `(cd sphinx/locale; tx pull -a -f)` * Run `python setup.py compile_catalog` -* Update version info in sphinx/__init__.py -* Update release date in CHANGES +* `python utils/bump_version.py x.y.z` +* Check diff by `git diff` * `git commit -am 'Bump to x.y.z final'` * `make clean` * `python setup.py compile_grammar` @@ -21,7 +21,8 @@ Release checklist * `git push origin stable --tags` * open https://readthedocs.org/dashboard/sphinx/versions/ and enable the released version * Add new version/milestone to tracker categories -* Update version info, add new CHANGES entry for next version +* `python utils/bump_version.py a.b.cb0` (ex. 1.5.3b0) +* Check diff by `git diff` * `git commit -am 'Bump version'` * `git push origin stable` * `git checkout master`