summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES24
-rw-r--r--setup.py1
-rw-r--r--sphinx/application.py3
-rw-r--r--sphinx/builders/gettext.py6
-rw-r--r--sphinx/domains/cpp.py308
-rw-r--r--sphinx/util/compat.py4
-rw-r--r--tests/roots/test-intl/index.txt7
-rw-r--r--tests/roots/test-intl/xx/LC_MESSAGES/index.po3
-rw-r--r--tests/test_domain_cpp.py36
-rw-r--r--tests/test_intl.py2
-rw-r--r--utils/release-checklist12
11 files changed, 276 insertions, 130 deletions
diff --git a/CHANGES b/CHANGES
index b86bcd594..e8721e5cb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -56,7 +56,7 @@ Bugs fixed
Testing
--------
-Release 2.0.0 beta2 (in development)
+Release 2.0.0 beta3 (in development)
====================================
Dependencies
@@ -65,8 +65,6 @@ Dependencies
Incompatible changes
--------------------
-* texinfo: image files are copied into ``name-figure`` directory
-
Deprecated
----------
@@ -76,6 +74,20 @@ Features added
Bugs fixed
----------
+Testing
+--------
+
+Release 2.0.0 beta2 (released Mar 21, 2019)
+===========================================
+
+Incompatible changes
+--------------------
+
+* texinfo: image files are copied into ``name-figure`` directory
+
+Bugs fixed
+----------
+
* #6096: html: Anchor links are not added to figures
* #3620: html: Defer searchindex.js rather than loading it via ajax
* #6113: html: Table cells and list items have large margins
@@ -89,7 +101,11 @@ Bugs fixed
* AssertionError is raised when custom ``citation_reference`` node having
classes attribute refers missing citation (refs: #6147)
* #2155: Support ``code`` directive
-* #4872: ext.inheritance_diagram: correctly describe behavior of ``parts`` option in docs, allow negative values.
+* C++, fix parsing of braced initializers.
+* #6172: AttributeError is raised for old styled index nodes
+* #4872: inheritance_diagram: correctly describe behavior of ``parts`` option in
+ docs, allow negative values.
+* #6178: i18n: Captions missing in translations for hidden TOCs
Testing
--------
diff --git a/setup.py b/setup.py
index eccceebb3..30f8625c8 100644
--- a/setup.py
+++ b/setup.py
@@ -172,6 +172,7 @@ setup(
author_email='georg@python.org',
description='Python documentation generator',
long_description=long_desc,
+ long_description_content_type='text/x-rst',
zip_safe=False,
classifiers=[
'Development Status :: 5 - Production/Stable',
diff --git a/sphinx/application.py b/sphinx/application.py
index dcd143712..aee9f4410 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -832,9 +832,6 @@ class Sphinx:
For the role content, you have the same syntactical possibilities as
for standard Sphinx roles (see :ref:`xref-syntax`).
- This method is also available under the deprecated alias
- :meth:`add_description_unit`.
-
.. versionchanged:: 1.8
Add *override* keyword.
"""
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index c885499ed..f26b831da 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -16,6 +16,7 @@ from os import path, walk, getenv
from time import time
from uuid import uuid4
+from sphinx import addnodes
from sphinx.builders import Builder
from sphinx.domains.python import pairindextypes
from sphinx.errors import ThemeError
@@ -142,6 +143,11 @@ class I18nBuilder(Builder):
# type: (str, nodes.document) -> None
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
+ for toctree in self.env.tocs[docname].traverse(addnodes.toctree):
+ for node, msg in extract_messages(toctree):
+ node.uid = '' # type: ignore # Hack UUID model
+ catalog.add(msg, node)
+
for node, msg in extract_messages(doctree):
catalog.add(msg, node)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index e60f61f2c..6760328d4 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -1159,15 +1159,12 @@ class ASTNoexceptExpr(ASTBase):
class ASTNewExpr(ASTBase):
- def __init__(self, rooted, isNewTypeId, typ, initList, initType):
- # type: (bool, bool, ASTType, List[Any], str) -> None
+ def __init__(self, rooted, isNewTypeId, typ, initList):
+ # type: (bool, bool, ASTType, Any) -> None
self.rooted = rooted
self.isNewTypeId = isNewTypeId
self.typ = typ
self.initList = initList
- self.initType = initType
- if self.initList is not None:
- assert self.initType in ')}'
def _stringify(self, transform):
# type: (Callable[[Any], str]) -> str
@@ -1181,15 +1178,7 @@ class ASTNewExpr(ASTBase):
else:
assert False
if self.initList is not None:
- if self.initType == ')':
- res.append('(')
- first = True
- for e in self.initList:
- if not first:
- res.append(', ')
- first = False
- res.append(transform(e))
- res.append(self.initType)
+ res.append(transform(self.initList))
return ''.join(res)
def get_id(self, version):
@@ -1200,13 +1189,7 @@ class ASTNewExpr(ASTBase):
res.append('_')
res.append(self.typ.get_id(version))
if self.initList is not None:
- if self.initType == ')':
- res.append('pi')
- for e in self.initList:
- res.append(e.get_id(version))
- res.append('E')
- else:
- assert False
+ res.append(self.initList.get_id(version))
else:
res.append('E')
return ''.join(res)
@@ -1221,17 +1204,7 @@ class ASTNewExpr(ASTBase):
else:
assert False
if self.initList is not None:
- if self.initType == ')':
- signode.append(nodes.Text('('))
- first = True
- for e in self.initList:
- if not first:
- signode.append(nodes.Text(', '))
- first = False
- e.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
- else:
- assert False
+ self.initList.describe_signature(signode, mode, env, symbol)
class ASTDeleteExpr(ASTBase):
@@ -1323,38 +1296,24 @@ class ASTTypeId(ASTBase):
class ASTPostfixCallExpr(ASTBase):
- def __init__(self, exprs):
- self.exprs = exprs
+ def __init__(self, lst):
+ # type: (Union[ASTParenExprList, ASTBracedInitList]) -> None
+ self.lst = lst
def _stringify(self, transform):
# type: (Callable[[Any], str]) -> str
- res = ['(']
- first = True
- for e in self.exprs:
- if not first:
- res.append(', ')
- first = False
- res.append(transform(e))
- res.append(')')
- return ''.join(res)
+ return transform(self.lst)
def get_id(self, idPrefix, version):
# type: (str, int) -> str
res = ['cl', idPrefix]
- for e in self.exprs:
+ for e in self.lst.exprs:
res.append(e.get_id(version))
res.append('E')
return ''.join(res)
def describe_signature(self, signode, mode, env, symbol):
- signode.append(nodes.Text('('))
- first = True
- for e in self.exprs:
- if not first:
- signode.append(nodes.Text(', '))
- first = False
- e.describe_signature(signode, mode, env, symbol)
- signode.append(nodes.Text(')'))
+ self.lst.describe_signature(signode, mode, env, symbol)
class ASTPostfixArray(ASTBase):
@@ -3232,18 +3191,85 @@ class ASTDeclaratorNameParamQual(ASTBase):
self.paramQual.describe_signature(signode, mode, env, symbol)
+class ASTParenExprList(ASTBase):
+ def __init__(self, exprs):
+ # type: (List[Any]) -> None
+ self.exprs = exprs
+
+ def get_id(self, version):
+ # type: (int) -> str
+ return "pi%sE" % ''.join(e.get_id(version) for e in self.exprs)
+
+ def _stringify(self, transform):
+ # type: (Callable[[Any], str]) -> str
+ exprs = [transform(e) for e in self.exprs]
+ return '(%s)' % ', '.join(exprs)
+
+ def describe_signature(self, signode, mode, env, symbol):
+ # type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
+ _verify_description_mode(mode)
+ signode.append(nodes.Text('('))
+ first = True
+ for e in self.exprs:
+ if not first:
+ signode.append(nodes.Text(', '))
+ else:
+ first = False
+ e.describe_signature(signode, mode, env, symbol)
+ signode.append(nodes.Text(')'))
+
+
+class ASTBracedInitList(ASTBase):
+ def __init__(self, exprs, trailingComma):
+ # type: (List[Any], bool) -> None
+ self.exprs = exprs
+ self.trailingComma = trailingComma
+
+ def get_id(self, version):
+ # type: (int) -> str
+ return "il%sE" % ''.join(e.get_id(version) for e in self.exprs)
+
+ def _stringify(self, transform):
+ # type: (Callable[[Any], str]) -> str
+ exprs = [transform(e) for e in self.exprs]
+ trailingComma = ',' if self.trailingComma else ''
+ return '{%s%s}' % (', '.join(exprs), trailingComma)
+
+ def describe_signature(self, signode, mode, env, symbol):
+ # type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
+ _verify_description_mode(mode)
+ signode.append(nodes.Text('{'))
+ first = True
+ for e in self.exprs:
+ if not first:
+ signode.append(nodes.Text(', '))
+ else:
+ first = False
+ e.describe_signature(signode, mode, env, symbol)
+ if self.trailingComma:
+ signode.append(nodes.Text(','))
+ signode.append(nodes.Text('}'))
+
+
class ASTInitializer(ASTBase):
- def __init__(self, value):
+ def __init__(self, value, hasAssign=True):
+ # type: (Any, bool) -> None
self.value = value
+ self.hasAssign = hasAssign
def _stringify(self, transform):
# type: (Callable[[Any], str]) -> str
- return ' = ' + transform(self.value)
+ val = transform(self.value)
+ if self.hasAssign:
+ return ' = ' + val
+ else:
+ return val
def describe_signature(self, signode, mode, env, symbol):
# type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
_verify_description_mode(mode)
- signode.append(nodes.Text(' = '))
+ if self.hasAssign:
+ signode.append(nodes.Text(' = '))
self.value.describe_signature(signode, 'markType', env, symbol)
@@ -4844,35 +4870,67 @@ class DefinitionParser:
return res
return self._parse_nested_name()
- def _parse_expression_list_or_braced_init_list(self):
- # type: () -> Tuple[List[Any], str]
+ def _parse_initializer_list(self, name, open, close):
+ # type: (str, str, str) -> Tuple[List[Any], bool]
+ # Parse open and close with the actual initializer-list inbetween
+ # -> initializer-clause '...'[opt]
+ # | initializer-list ',' initializer-clause '...'[opt]
self.skip_ws()
- if self.skip_string_and_ws('('):
- close = ')'
- name = 'parenthesized expression-list'
- elif self.skip_string_and_ws('{'):
- close = '}'
- name = 'braced-init-list'
- self.fail('Sorry, braced-init-list not yet supported.')
- else:
+ if not self.skip_string_and_ws(open):
return None, None
+ if self.skip_string(close):
+ return [], False
+
exprs = []
- self.skip_ws()
- if not self.skip_string(close):
- while True:
- self.skip_ws()
- expr = self._parse_expression(inTemplate=False)
- self.skip_ws()
- if self.skip_string('...'):
- exprs.append(ASTPackExpansionExpr(expr))
- else:
- exprs.append(expr)
- self.skip_ws()
- if self.skip_string(close):
- break
- if not self.skip_string(','):
- self.fail("Error in %s, expected ',' or '%s'." % (name, close))
- return exprs, close
+ trailingComma = False
+ while True:
+ self.skip_ws()
+ expr = self._parse_expression(inTemplate=False)
+ self.skip_ws()
+ if self.skip_string('...'):
+ exprs.append(ASTPackExpansionExpr(expr))
+ else:
+ exprs.append(expr)
+ self.skip_ws()
+ if self.skip_string(close):
+ break
+ if not self.skip_string_and_ws(','):
+ self.fail("Error in %s, expected ',' or '%s'." % (name, close))
+ if self.current_char == close and close == '}':
+ self.pos += 1
+ trailingComma = True
+ break
+ return exprs, trailingComma
+
+ def _parse_paren_expression_list(self):
+ # type: () -> ASTParenExprList
+ # -> '(' expression-list ')'
+ # though, we relax it to also allow empty parens
+ # as it's needed in some cases
+ #
+ # expression-list
+ # -> initializer-list
+ exprs, trailingComma = self._parse_initializer_list("parenthesized expression-list",
+ '(', ')')
+ if exprs is None:
+ return None
+ return ASTParenExprList(exprs)
+
+ def _parse_braced_init_list(self):
+ # type: () -> ASTBracedInitList
+ # -> '{' initializer-list ','[opt] '}'
+ # | '{' '}'
+ exprs, trailingComma = self._parse_initializer_list("braced-init-list", '{', '}')
+ if exprs is None:
+ return None
+ return ASTBracedInitList(exprs, trailingComma)
+
+ def _parse_expression_list_or_braced_init_list(self):
+ # type: () -> Union[ASTParenExprList, ASTBracedInitList]
+ paren = self._parse_paren_expression_list()
+ if paren is not None:
+ return paren
+ return self._parse_braced_init_list()
def _parse_postfix_expression(self):
# -> primary
@@ -4980,7 +5038,7 @@ class DefinitionParser:
raise self._make_multi_error(errors, header)
# and now parse postfixes
- postFixes = []
+ postFixes = [] # type: List[Any]
while True:
self.skip_ws()
if prefixType in ['expr', 'cast', 'typeid']:
@@ -5000,7 +5058,7 @@ class DefinitionParser:
self.pos -= 3
else:
name = self._parse_nested_name()
- postFixes.append(ASTPostfixMember(name)) # type: ignore
+ postFixes.append(ASTPostfixMember(name))
continue
if self.skip_string('->'):
if self.skip_string('*'):
@@ -5008,21 +5066,17 @@ class DefinitionParser:
self.pos -= 3
else:
name = self._parse_nested_name()
- postFixes.append(ASTPostfixMemberOfPointer(name)) # type: ignore
+ postFixes.append(ASTPostfixMemberOfPointer(name))
continue
if self.skip_string('++'):
- postFixes.append(ASTPostfixInc()) # type: ignore
+ postFixes.append(ASTPostfixInc())
continue
if self.skip_string('--'):
- postFixes.append(ASTPostfixDec()) # type: ignore
+ postFixes.append(ASTPostfixDec())
continue
- lst, typ = self._parse_expression_list_or_braced_init_list()
+ lst = self._parse_expression_list_or_braced_init_list()
if lst is not None:
- if typ == ')':
- postFixes.append(ASTPostfixCallExpr(lst)) # type: ignore
- else:
- assert typ == '}'
- assert False
+ postFixes.append(ASTPostfixCallExpr(lst))
continue
break
if len(postFixes) == 0:
@@ -5105,10 +5159,8 @@ class DefinitionParser:
decl = self._parse_declarator(named=False, paramMode="new")
else:
self.fail("Sorry, parenthesised type-id in new expression not yet supported.")
- lst, typ = self._parse_expression_list_or_braced_init_list()
- if lst:
- assert typ in ")}"
- return ASTNewExpr(rooted, isNewTypeId, ASTType(declSpecs, decl), lst, typ)
+ lst = self._parse_expression_list_or_braced_init_list()
+ return ASTNewExpr(rooted, isNewTypeId, ASTType(declSpecs, decl), lst)
# delete-expression
pos = self.pos
rooted = self.skip_string('::')
@@ -5267,7 +5319,7 @@ class DefinitionParser:
value = self.matched_text
else:
# TODO: add handling of more bracket-like things, and quote handling
- brackets = {'(': ')', '[': ']', '<': '>'}
+ brackets = {'(': ')', '{': '}', '[': ']', '<': '>'}
symbols = [] # type: List[str]
while not self.eof:
if (len(symbols) == 0 and self.current_char in end):
@@ -5825,30 +5877,52 @@ class DefinitionParser:
def _parse_initializer(self, outer=None, allowFallback=True):
# type: (str, bool) -> ASTInitializer
+ # initializer # global vars
+ # -> brace-or-equal-initializer
+ # | '(' expression-list ')'
+ #
+ # brace-or-equal-initializer # member vars
+ # -> '=' initializer-clause
+ # | braced-init-list
+ #
+ # initializer-clause # function params, non-type template params (with '=' in front)
+ # -> assignment-expression
+ # | braced-init-list
+ #
+ # we don't distinguish between global and member vars, so disallow paren:
+ #
+ # -> braced-init-list # var only
+ # | '=' assignment-expression
+ # | '=' braced-init-list
self.skip_ws()
- # TODO: support paren and brace initialization for memberObject
+ if outer == 'member':
+ bracedInit = self._parse_braced_init_list()
+ if bracedInit is not None:
+ return ASTInitializer(bracedInit, hasAssign=False)
+
if not self.skip_string('='):
return None
+
+ bracedInit = self._parse_braced_init_list()
+ if bracedInit is not None:
+ return ASTInitializer(bracedInit)
+
+ if outer == 'member':
+ fallbackEnd = [] # type: List[str]
+ elif outer == 'templateParam':
+ fallbackEnd = [',', '>']
+ elif outer is None: # function parameter
+ fallbackEnd = [',', ')']
else:
- if outer == 'member':
- def parser():
- return self._parse_assignment_expression(inTemplate=False)
- value = self._parse_expression_fallback([], parser,
- allow=allowFallback)
- elif outer == 'templateParam':
- def parser():
- return self._parse_assignment_expression(inTemplate=True)
- value = self._parse_expression_fallback([',', '>'], parser,
- allow=allowFallback)
- elif outer is None: # function parameter
- def parser():
- return self._parse_assignment_expression(inTemplate=False)
- value = self._parse_expression_fallback([',', ')'], parser,
- allow=allowFallback)
- else:
- self.fail("Internal error, initializer for outer '%s' not "
- "implemented." % outer)
- return ASTInitializer(value)
+ self.fail("Internal error, initializer for outer '%s' not "
+ "implemented." % outer)
+
+ inTemplate = outer == 'templateParam'
+
+ def parser():
+ return self._parse_assignment_expression(inTemplate=inTemplate)
+ value = self._parse_expression_fallback(fallbackEnd, parser, allow=allowFallback)
+ return ASTInitializer(value)
def _parse_type(self, named, outer=None):
# type: (Union[bool, str], str) -> ASTType
diff --git a/sphinx/util/compat.py b/sphinx/util/compat.py
index 1567bad9e..5d8cbb3db 100644
--- a/sphinx/util/compat.py
+++ b/sphinx/util/compat.py
@@ -58,12 +58,12 @@ class IndexEntriesMigrator(SphinxTransform):
def apply(self, **kwargs):
# type: (Any) -> None
for node in self.document.traverse(addnodes.index):
- for entries in node['entries']:
+ for i, entries in enumerate(node['entries']):
if len(entries) == 4:
source, line = get_source_line(node)
warnings.warn('An old styled index node found: %r at (%s:%s)' %
(node, source, line), RemovedInSphinx40Warning)
- entries.extend([None])
+ node['entries'][i] = entries + (None,)
def setup(app):
diff --git a/tests/roots/test-intl/index.txt b/tests/roots/test-intl/index.txt
index cd63b5ec3..1e09294f9 100644
--- a/tests/roots/test-intl/index.txt
+++ b/tests/roots/test-intl/index.txt
@@ -30,3 +30,10 @@ CONTENTS
refs
section
topic
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Hidden Toc
+ :hidden:
+
+ only
diff --git a/tests/roots/test-intl/xx/LC_MESSAGES/index.po b/tests/roots/test-intl/xx/LC_MESSAGES/index.po
index 76ef049f0..a4646f1ec 100644
--- a/tests/roots/test-intl/xx/LC_MESSAGES/index.po
+++ b/tests/roots/test-intl/xx/LC_MESSAGES/index.po
@@ -19,6 +19,9 @@ msgstr ""
msgid "Table of Contents"
msgstr "TABLE OF CONTENTS"
+msgid "Hidden Toc"
+msgstr "HIDDEN TOC"
+
msgid "testdata for i18n"
msgstr "TESTDATA FOR I18N"
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index 0cd3445a5..46019b4a9 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -194,6 +194,8 @@ def test_expressions():
exprCheck('new int()', 'nw_ipiE')
exprCheck('new int(5, 42)', 'nw_ipiL5EL42EE')
exprCheck('::new int', 'nw_iE')
+ exprCheck('new int{}', 'nw_iilE')
+ exprCheck('new int{5, 42}', 'nw_iilL5EL42EE')
# delete-expression
exprCheck('delete p', 'dl1p')
exprCheck('delete [] p', 'da1p')
@@ -673,6 +675,40 @@ def test_template_args():
{2: "I0E21enable_if_not_array_t"})
+def test_initializers():
+ idsMember = {1: 'v__T', 2:'1v'}
+ idsFunction = {1: 'f__T', 2: '1f1T'}
+ idsTemplate = {2: 'I_1TE1fv', 4: 'I_1TE1fvv'}
+ # no init
+ check('member', 'T v', idsMember)
+ check('function', 'void f(T v)', idsFunction)
+ check('function', 'template<T v> void f()', idsTemplate)
+ # with '=', assignment-expression
+ check('member', 'T v = 42', idsMember)
+ check('function', 'void f(T v = 42)', idsFunction)
+ check('function', 'template<T v = 42> void f()', idsTemplate)
+ # with '=', braced-init
+ check('member', 'T v = {}', idsMember)
+ check('function', 'void f(T v = {})', idsFunction)
+ check('function', 'template<T v = {}> void f()', idsTemplate)
+ check('member', 'T v = {42, 42, 42}', idsMember)
+ check('function', 'void f(T v = {42, 42, 42})', idsFunction)
+ check('function', 'template<T v = {42, 42, 42}> void f()', idsTemplate)
+ check('member', 'T v = {42, 42, 42,}', idsMember)
+ check('function', 'void f(T v = {42, 42, 42,})', idsFunction)
+ check('function', 'template<T v = {42, 42, 42,}> void f()', idsTemplate)
+ check('member', 'T v = {42, 42, args...}', idsMember)
+ check('function', 'void f(T v = {42, 42, args...})', idsFunction)
+ check('function', 'template<T v = {42, 42, args...}> void f()', idsTemplate)
+ # without '=', braced-init
+ check('member', 'T v{}', idsMember)
+ check('member', 'T v{42, 42, 42}', idsMember)
+ check('member', 'T v{42, 42, 42,}', idsMember)
+ check('member', 'T v{42, 42, args...}', idsMember)
+ # other
+ check('member', 'T v = T{}', idsMember)
+
+
def test_attributes():
# style: C++
check('member', '[[]] int f', {1: 'f__i', 2: '1f'})
diff --git a/tests/test_intl.py b/tests/test_intl.py
index ddb22ef9f..a052266b8 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -606,6 +606,8 @@ def test_html_meta(app):
assert expected_expr in result
expected_expr = '<meta content="I18N, SPHINX, MARKUP" name="keywords" />'
assert expected_expr in result
+ expected_expr = '<p class="caption"><span class="caption-text">HIDDEN TOC</span></p>'
+ assert expected_expr in result
@sphinx_intl
diff --git a/utils/release-checklist b/utils/release-checklist
index 84cbb3829..12cbe6381 100644
--- a/utils/release-checklist
+++ b/utils/release-checklist
@@ -12,7 +12,8 @@ for stable releases
* ``git commit -am 'Bump to X.Y.Z final'``
* ``make clean``
* ``python setup.py release bdist_wheel sdist``
-* ``twine upload dist/<Sphinx-X.Y.Z files> --sign --identity [your GPG key]``
+* ``twine check dist/Sphinx-X.Y.Z*``
+* ``twine upload dist/Sphinx-X.Y.Z* --sign --identity [your GPG key]``
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
* ``git tag vX.Y.Z``
* ``python utils/bump_version.py --in-develop X.Y.Zb0`` (ex. 1.5.3b0)
@@ -39,7 +40,8 @@ for first beta releases
* ``git commit -am 'Bump to X.Y.0 beta1'``
* ``make clean``
* ``python setup.py release bdist_wheel sdist``
-* ``twine upload dist/<Sphinx-X.Y.Z files> --sign --identity [your GPG key]``
+* ``twine check dist/Sphinx-X.Y.Z*``
+* ``twine upload dist/Sphinx-X.Y.Z* --sign --identity [your GPG key]``
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
* ``git tag vX.Y.0b1``
* ``python utils/bump_version.py --in-develop X.Y.0b2`` (ex. 1.6.0b2)
@@ -69,7 +71,8 @@ for other beta releases
* ``git commit -am 'Bump to X.Y.0 betaN'``
* ``make clean``
* ``python setup.py release bdist_wheel sdist``
-* ``twine upload dist/<Sphinx-X.Y.Z files> --sign --identity [your GPG key]``
+* ``twine check dist/Sphinx-X.Y.Z*``
+* ``twine upload dist/Sphinx-X.Y.Z* --sign --identity [your GPG key]``
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
* ``git tag vX.Y.0bN``
* ``python utils/bump_version.py --in-develop X.Y.0bM`` (ex. 1.6.0b3)
@@ -98,7 +101,8 @@ for major releases
* ``git commit -am 'Bump to X.Y.0 final'``
* ``make clean``
* ``python setup.py release bdist_wheel sdist``
-* ``twine upload dist/<Sphinx-X.Y.Z files> --sign --identity [your GPG key]``
+* ``twine check dist/Sphinx-X.Y.Z*``
+* ``twine upload dist/Sphinx-X.Y.Z* --sign --identity [your GPG key]``
* open https://pypi.org/project/Sphinx/ and check there are no obvious errors
* ``git tag vX.Y.0``
* ``python utils/bump_version.py --in-develop X.Y.1b0`` (ex. 1.6.1b0)