diff options
author | Keewis <keewis@posteo.de> | 2020-08-18 15:47:53 +0200 |
---|---|---|
committer | Keewis <keewis@posteo.de> | 2020-08-18 15:47:53 +0200 |
commit | 3c24021972b972fbfc282ed1772ff098f2b835b2 (patch) | |
tree | ba72ac3cf66ee040e61a63bc2bccaa3237448c37 | |
parent | b69c5119b52f664c1b44a45ba627c487be7c3c63 (diff) | |
parent | 9d48cb9798a1f2eea8a800689dde6648e260916f (diff) | |
download | sphinx-git-3c24021972b972fbfc282ed1772ff098f2b835b2.tar.gz |
Merge branch '3.x' into preprocess-other-sections
32 files changed, 417 insertions, 426 deletions
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c9009b90e..226532b79 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,5 +2,8 @@ blank_issues_enabled: false # default: true contact_links: - name: Question + url: https://stackoverflow.com/questions/tagged/python-sphinx + about: For Q&A purpose, please use Stackoverflow with the tag python-sphinx +- name: Discussion url: https://groups.google.com/forum/#!forum/sphinx-users - about: For Q&A purpose, please use sphinx-users mailing list. + about: For general discussion, please use sphinx-users mailing list. @@ -1,4 +1,4 @@ -Release 3.2.0 (in development) +Release 3.3.0 (in development) ============================== Dependencies @@ -10,6 +10,69 @@ Incompatible changes Deprecated ---------- +Features added +-------------- + +Bugs fixed +---------- + +* #8085: i18n: Add support for having single text domain +* #8093: The highlight warning has wrong location in some builders (LaTeX, + singlehtml and so on) + +Testing +-------- + +Release 3.2.2 (in development) +============================== + +Dependencies +------------ + +Incompatible changes +-------------------- + +Deprecated +---------- + +Features added +-------------- + +Bugs fixed +---------- + +Testing +-------- + +Release 3.2.1 (released Aug 14, 2020) +===================================== + +Features added +-------------- + +* #8095: napoleon: Add :confval:`napoleon_preprocess_types` to enable the type + preprocessor for numpy style docstrings +* #8114: C and C++, parse function attributes after parameters and qualifiers. + +Bugs fixed +---------- + +* #8074: napoleon: Crashes during processing C-ext module +* #8088: napoleon: "Inline literal start-string without end-string" warning in + Numpy style Parameters section +* #8084: autodoc: KeyError is raised on documenting an attribute of the broken + class +* #8091: autodoc: AttributeError is raised on documenting an attribute on Python + 3.5.2 +* #8099: autodoc: NameError is raised when target code uses ``TYPE_CHECKING`` +* C++, fix parsing of template template paramters, broken by the fix of #7944 + +Release 3.2.0 (released Aug 08, 2020) +===================================== + +Deprecated +---------- + * ``sphinx.ext.autodoc.members_set_option()`` * ``sphinx.ext.autodoc.merge_special_members_option()`` * ``sphinx.writers.texinfo.TexinfoWriter.desc`` @@ -56,6 +119,7 @@ Features added :confval:`c_warn_on_allowed_pre_v3`` to ``True``. The functionality is immediately deprecated. * #7999: C, add support for named variadic macro arguments. +* #8071: Allow to suppress "self referenced toctrees" warning Bugs fixed ---------- @@ -71,6 +135,8 @@ Bugs fixed when ``:inherited-members:`` option given * #8032: autodoc: A type hint for the instance variable defined at parent class is not shown in the document of the derived class +* #8041: autodoc: An annotated instance variable on super class is not + documented when derived class has other annotated instance variables * #7839: autosummary: cannot handle umlauts in function names * #7865: autosummary: Failed to extract summary line when abbreviations found * #7866: autosummary: Failed to extract correct summary line when docstring @@ -80,6 +146,8 @@ Bugs fixed module has submodules * #4258: napoleon: decorated special methods are not shown * #7799: napoleon: parameters are not escaped for combined params in numpydoc +* #7780: napoleon: multiple paramaters declaration in numpydoc was wrongly + recognized when napoleon_use_params=True * #7715: LaTeX: ``numfig_secnum_depth > 1`` leads to wrong figure links * #7846: html theme: XML-invalid files were generated * #7894: gettext: Wrong source info is shown when using rst_epilog @@ -106,34 +174,9 @@ Bugs fixed * #7986: CSS: make "highlight" selector more robust * #7944: C++, parse non-type template parameters starting with a dependent qualified name. - -Testing --------- - -Release 3.1.3 (in development) -============================== - -Dependencies ------------- - -Incompatible changes --------------------- - -Deprecated ----------- - -Features added --------------- - -Bugs fixed ----------- - * C, don't deepcopy the entire symbol table and make a mess every time an enumerator is handled. -Testing --------- - Release 3.1.2 (released Jul 05, 2020) ===================================== @@ -64,10 +64,6 @@ type-check: doclinter: python utils/doclinter.py CHANGES *.rst doc/ -.PHONY: pylint -pylint: - @pylint --rcfile utils/pylintrc sphinx - .PHONY: test test: @$(PYTHON) -m pytest -v $(TEST) diff --git a/doc/internals/contributing.rst b/doc/internals/contributing.rst index 0e464478a..1f4a31013 100644 --- a/doc/internals/contributing.rst +++ b/doc/internals/contributing.rst @@ -12,6 +12,9 @@ Getting help The Sphinx community maintains a number of mailing lists and IRC channels. +Stack Overflow with tag `python-sphinx`_ + Questions and answers about use and development. + sphinx-users <sphinx-users@googlegroups.com> Mailing list for user support. @@ -21,6 +24,7 @@ sphinx-dev <sphinx-dev@googlegroups.com> #sphinx-doc on irc.freenode.net IRC channel for development questions and user support. +.. _python-sphinx: https://stackoverflow.com/questions/tagged/python-sphinx Bug Reports and Feature Requests -------------------------------- diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index add78326b..3fc3a5306 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -756,9 +756,15 @@ documentation on :ref:`intl` for details. If true, a document's text domain is its docname if it is a top-level project file and its very base directory otherwise. + If set to string, all document's text domain is this string, making all + documents use single text domain. + By default, the document ``markup/code.rst`` ends up in the ``markup`` text domain. With this option set to ``False``, it is ``markup/code``. + .. versionchanged:: 3.3 + The string value is now accepted. + .. confval:: gettext_uuid If true, Sphinx generates uuid information for version tracking in message diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 52bbdcc65..fde2345a8 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -32,8 +32,8 @@ if 'PYTHONWARNINGS' not in os.environ: warnings.filterwarnings('ignore', "'U' mode is deprecated", DeprecationWarning, module='docutils.io') -__version__ = '3.2.0' -__released__ = '3.2.0' # used when Sphinx builds its own docs +__version__ = '3.3.0+' +__released__ = '3.3.0' # used when Sphinx builds its own docs #: Version info for better programmatic use. #: @@ -43,7 +43,7 @@ __released__ = '3.2.0' # used when Sphinx builds its own docs #: #: .. versionadded:: 1.2 #: Before version 1.2, check the string ``sphinx.__version__``. -version_info = (3, 2, 0, 'final', 0) +version_info = (3, 3, 0, 'beta', 0) package_dir = path.abspath(path.dirname(__file__)) diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 8e30762e9..f8a19c57a 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -316,7 +316,7 @@ class MessageCatalogBuilder(I18nBuilder): def setup(app: Sphinx) -> Dict[str, Any]: app.add_builder(MessageCatalogBuilder) - app.add_config_value('gettext_compact', True, 'gettext') + app.add_config_value('gettext_compact', True, 'gettext', Any) app.add_config_value('gettext_location', True, 'gettext') app.add_config_value('gettext_uuid', False, 'gettext') app.add_config_value('gettext_auto_build', True, 'env') diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 65786b5de..d8ccc2e3d 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -32,7 +32,7 @@ from sphinx.transforms import SphinxTransform from sphinx.transforms.post_transforms import ReferencesResolver from sphinx.util import logging from sphinx.util.cfamily import ( - NoOldIdError, ASTBaseBase, ASTBaseParenExprList, + NoOldIdError, ASTBaseBase, ASTAttribute, ASTBaseParenExprList, verify_description_mode, StringifyTransform, BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral, identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re, @@ -652,8 +652,9 @@ class ASTFunctionParameter(ASTBase): class ASTParameters(ASTBase): - def __init__(self, args: List[ASTFunctionParameter]) -> None: + def __init__(self, args: List[ASTFunctionParameter], attrs: List[ASTAttribute]) -> None: self.args = args + self.attrs = attrs @property def function_params(self) -> List[ASTFunctionParameter]: @@ -669,6 +670,9 @@ class ASTParameters(ASTBase): first = False res.append(str(a)) res.append(')') + for attr in self.attrs: + res.append(' ') + res.append(transform(attr)) return ''.join(res) def describe_signature(self, signode: TextElement, mode: str, @@ -683,6 +687,9 @@ class ASTParameters(ASTBase): arg.describe_signature(param, 'markType', env, symbol=symbol) paramlist += param signode += paramlist + for attr in self.attrs: + signode += nodes.Text(' ') + attr.describe_signature(signode) class ASTDeclSpecsSimple(ASTBaseBase): @@ -2572,7 +2579,15 @@ class DefinitionParser(BaseParser): self.fail( 'Expecting "," or ")" in parameters, ' 'got "%s".' % self.current_char) - return ASTParameters(args) + + attrs = [] + while True: + attr = self._parse_attribute() + if attr is None: + break + attrs.append(attr) + + return ASTParameters(args, attrs) def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple: """Just parse the simple ones.""" diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 46708b846..92d578427 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1879,7 +1879,8 @@ class ASTNoexceptSpec(ASTBase): class ASTParametersQualifiers(ASTBase): def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool, refQual: str, exceptionSpec: ASTNoexceptSpec, trailingReturn: "ASTType", - override: bool, final: bool, initializer: str) -> None: + override: bool, final: bool, attrs: List[ASTAttribute], + initializer: str) -> None: self.args = args self.volatile = volatile self.const = const @@ -1888,6 +1889,7 @@ class ASTParametersQualifiers(ASTBase): self.trailingReturn = trailingReturn self.override = override self.final = final + self.attrs = attrs self.initializer = initializer @property @@ -1947,6 +1949,9 @@ class ASTParametersQualifiers(ASTBase): res.append(' final') if self.override: res.append(' override') + for attr in self.attrs: + res.append(' ') + res.append(transform(attr)) if self.initializer: res.append(' = ') res.append(self.initializer) @@ -1988,6 +1993,9 @@ class ASTParametersQualifiers(ASTBase): _add_anno(signode, 'final') if self.override: _add_anno(signode, 'override') + for attr in self.attrs: + signode += nodes.Text(' ') + attr.describe_signature(signode) if self.initializer: _add_text(signode, '= ' + str(self.initializer)) @@ -5709,6 +5717,13 @@ class DefinitionParser(BaseParser): override = self.skip_word_and_ws( 'override') # they can be permuted + attrs = [] + while True: + attr = self._parse_attribute() + if attr is None: + break + attrs.append(attr) + self.skip_ws() initializer = None if self.skip_string('='): @@ -5725,7 +5740,7 @@ class DefinitionParser(BaseParser): return ASTParametersQualifiers( args, volatile, const, refQual, exceptionSpec, trailingReturn, - override, final, initializer) + override, final, attrs, initializer) def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple: """Just parse the simple ones.""" @@ -6251,6 +6266,7 @@ class DefinitionParser(BaseParser): # ========================================================================== def _parse_template_paramter(self) -> ASTTemplateParam: + self.skip_ws() if self.skip_word('template'): # declare a tenplate template parameter nestedParams = self._parse_template_parameter_list() diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index cf3364494..8ce9fa365 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -594,7 +594,9 @@ class BuildEnvironment: def traverse_toctree(parent: str, docname: str) -> Iterator[Tuple[str, str]]: if parent == docname: - logger.warning(__('self referenced toctree found. Ignored.'), location=docname) + logger.warning(__('self referenced toctree found. Ignored.'), + location=docname, type='toc', + subtype='circular') return # traverse toctree by pre-order diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 832ee4a92..b61a96c84 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -18,6 +18,7 @@ from types import ModuleType from typing import ( Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union ) +from typing import get_type_hints from docutils.statemachine import StringList @@ -1605,8 +1606,21 @@ class DataDocumenter(ModuleLevelDocumenter): sourcename = self.get_sourcename() if not self.options.annotation: # obtain annotation for this data - annotations = getattr(self.parent, '__annotations__', {}) - if annotations and self.objpath[-1] in annotations: + try: + annotations = get_type_hints(self.parent) + except NameError: + # Failed to evaluate ForwardRef (maybe TYPE_CHECKING) + annotations = safe_getattr(self.parent, '__annotations__', {}) + except TypeError: + annotations = {} + except KeyError: + # a broken class found (refs: https://github.com/sphinx-doc/sphinx/issues/8084) + annotations = {} + except AttributeError: + # AttributeError is raised on 3.5.2 (fixed by 3.5.3) + annotations = {} + + if self.objpath[-1] in annotations: objrepr = stringify_typehint(annotations.get(self.objpath[-1])) self.add_line(' :type: ' + objrepr, sourcename) else: @@ -1971,8 +1985,21 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): sourcename = self.get_sourcename() if not self.options.annotation: # obtain type annotation for this attribute - annotations = getattr(self.parent, '__annotations__', {}) - if annotations and self.objpath[-1] in annotations: + try: + annotations = get_type_hints(self.parent) + except NameError: + # Failed to evaluate ForwardRef (maybe TYPE_CHECKING) + annotations = safe_getattr(self.parent, '__annotations__', {}) + except TypeError: + annotations = {} + except KeyError: + # a broken class found (refs: https://github.com/sphinx-doc/sphinx/issues/8084) + annotations = {} + except AttributeError: + # AttributeError is raised on 3.5.2 (fixed by 3.5.3) + annotations = {} + + if self.objpath[-1] in annotations: objrepr = stringify_typehint(annotations.get(self.objpath[-1])) self.add_line(' :type: ' + objrepr, sourcename) else: diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 031911de2..133ce1439 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -18,6 +18,10 @@ from sphinx.pycode import ModuleAnalyzer from sphinx.util import logging from sphinx.util.inspect import isclass, isenumclass, safe_getattr +if False: + # For type annotation + from typing import Type # NOQA + logger = logging.getLogger(__name__) @@ -158,6 +162,24 @@ Attribute = NamedTuple('Attribute', [('name', str), ('value', Any)]) +def _getmro(obj: Any) -> Tuple["Type", ...]: + """Get __mro__ from given *obj* safely.""" + __mro__ = safe_getattr(obj, '__mro__', None) + if isinstance(__mro__, tuple): + return __mro__ + else: + return tuple() + + +def _getannotations(obj: Any) -> Mapping[str, Any]: + """Get __annotations__ from given *obj* safely.""" + __annotations__ = safe_getattr(obj, '__annotations__', None) + if isinstance(__annotations__, Mapping): + return __annotations__ + else: + return {} + + def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable, analyzer: ModuleAnalyzer = None) -> Dict[str, Attribute]: """Get members and attributes of target object.""" @@ -199,11 +221,11 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable, continue # annotation only member (ex. attr: int) - if hasattr(subject, '__annotations__') and isinstance(subject.__annotations__, Mapping): - for name in subject.__annotations__: - name = unmangle(subject, name) + for i, cls in enumerate(_getmro(subject)): + for name in _getannotations(cls): + name = unmangle(cls, name) if name and name not in members: - members[name] = Attribute(name, True, INSTANCEATTR) + members[name] = Attribute(name, i == 0, INSTANCEATTR) if analyzer: # append instance attributes (cf. self.attr1) if analyzer knows diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 855affa95..739636d7e 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -298,6 +298,16 @@ class Autosummary(SphinxDirective): raise exc # re-raise ImportError if instance attribute not found + def create_documenter(self, app: Sphinx, obj: Any, + parent: Any, full_name: str) -> "Documenter": + """Get an autodoc.Documenter class suitable for documenting the given + object. + + Wraps get_documenter and is meant as a hook for extensions. + """ + doccls = get_documenter(app, obj, parent) + return doccls(self.bridge, full_name) + def get_items(self, names: List[str]) -> List[Tuple[str, str, str, str]]: """Try to import the given names, and return a list of ``[(name, signature, summary_string, real_name), ...]``. @@ -329,8 +339,7 @@ class Autosummary(SphinxDirective): full_name = modname + '::' + full_name[len(modname) + 1:] # NB. using full_name here is important, since Documenters # handle module prefixes slightly differently - doccls = get_documenter(self.env.app, obj, parent) - documenter = doccls(self.bridge, full_name) + documenter = self.create_documenter(self.env.app, obj, parent, full_name) if not documenter.parse_name(): logger.warning(__('failed to parse name %s'), real_name, location=self.get_source_info()) diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py index 6cab63c9f..e62ef7152 100644 --- a/sphinx/ext/napoleon/__init__.py +++ b/sphinx/ext/napoleon/__init__.py @@ -41,6 +41,7 @@ class Config: napoleon_use_param = True napoleon_use_rtype = True napoleon_use_keyword = True + napoleon_preprocess_types = False napoleon_type_aliases = None napoleon_custom_sections = None @@ -237,9 +238,12 @@ class Config: :returns: *bool* -- True if successful, False otherwise + napoleon_preprocess_types : :obj:`bool` (Defaults to False) + Enable the type preprocessor for numpy style docstrings. + napoleon_type_aliases : :obj:`dict` (Defaults to None) Add a mapping of strings to string, translating types in numpy - style docstrings. + style docstrings. Only works if ``napoleon_preprocess_types = True``. napoleon_custom_sections : :obj:`list` (Defaults to None) Add a list of custom sections to include, expanding the list of parsed sections. @@ -268,6 +272,7 @@ class Config: 'napoleon_use_param': (True, 'env'), 'napoleon_use_rtype': (True, 'env'), 'napoleon_use_keyword': (True, 'env'), + 'napoleon_preprocess_types': (False, 'env'), 'napoleon_type_aliases': (None, 'env'), 'napoleon_custom_sections': (None, 'env') } diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index 05b96d3e2..39f5626ce 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -266,13 +266,16 @@ class GoogleDocstring: _descs = self.__class__(_descs, self._config).lines() return _name, _type, _descs - def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False - ) -> List[Tuple[str, str, List[str]]]: + def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False, + multiple: bool = False) -> List[Tuple[str, str, List[str]]]: self._consume_empty() fields = [] while not self._is_section_break(): _name, _type, _desc = self._consume_field(parse_type, prefer_type) - if _name or _type or _desc: + if multiple and _name: + for name in _name.split(","): + fields.append((name.strip(), _type, _desc)) + elif _name or _type or _desc: fields.append((_name, _type, _desc,)) return fields @@ -681,10 +684,12 @@ class GoogleDocstring: return self._format_fields(_('Other Parameters'), self._consume_fields()) def _parse_parameters_section(self, section: str) -> List[str]: - fields = self._consume_fields() if self._config.napoleon_use_param: + # Allow to declare multiple parameters at once (ex: x, y: int) + fields = self._consume_fields(multiple=True) return self._format_docutils_params(fields) else: + fields = self._consume_fields() return self._format_fields(_('Parameters'), fields) def _parse_raises_section(self, section: str) -> List[str]: @@ -1072,7 +1077,10 @@ class NumpyDocstring(GoogleDocstring): super().__init__(docstring, config, app, what, name, obj, options) def _get_location(self) -> str: - filepath = inspect.getfile(self._obj) if self._obj is not None else None + try: + filepath = inspect.getfile(self._obj) if self._obj is not None else None + except TypeError: + filepath = None name = self._name if filepath is None and name is None: @@ -1103,11 +1111,12 @@ class NumpyDocstring(GoogleDocstring): if prefer_type and not _type: _type, _name = _name, _type - _type = _convert_numpy_type_spec( - _type, - location=self._get_location(), - translations=self._config.napoleon_type_aliases or {}, - ) + if self._config.napoleon_preprocess_types: + _type = _convert_numpy_type_spec( + _type, + location=self._get_location(), + translations=self._config.napoleon_type_aliases or {}, + ) indent = self._get_indent(line) + 1 _desc = self._dedent(self._consume_indented_block(indent)) diff --git a/sphinx/registry.py b/sphinx/registry.py index 0aec0a9fd..4d1e9eb72 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -367,7 +367,14 @@ class SphinxComponentRegistry: logger.debug('[app] adding js_file: %r, %r', filename, attributes) self.js_files.append((filename, attributes)) + def has_latex_package(self, name: str) -> bool: + packages = self.latex_packages + self.latex_packages_after_hyperref + return bool([x for x in packages if x[0] == name]) + def add_latex_package(self, name: str, options: str, after_hyperref: bool = False) -> None: + if self.has_latex_package(name): + logger.warn("latex package '%s' already included" % name) + logger.debug('[app] adding latex package: %r', name) if after_hyperref: self.latex_packages_after_hyperref.append((name, options)) diff --git a/sphinx/util/cfamily.py b/sphinx/util/cfamily.py index a67b2a0ad..0edea128c 100644 --- a/sphinx/util/cfamily.py +++ b/sphinx/util/cfamily.py @@ -391,7 +391,7 @@ class BaseParser: % startPos) return self.definition[startPos:self.pos] - def _parse_attribute(self) -> ASTAttribute: + def _parse_attribute(self) -> Optional[ASTAttribute]: self.skip_ws() # try C++11 style startPos = self.pos diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index 2177fc7b7..41407f4e1 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -14,7 +14,7 @@ import warnings from collections import namedtuple from datetime import datetime, timezone from os import path -from typing import Callable, Generator, List, Set, Tuple +from typing import Callable, Generator, List, Set, Tuple, Union import babel.dates from babel.messages.mofile import write_mo @@ -128,8 +128,10 @@ def find_catalog(docname: str, compaction: bool) -> str: return ret -def docname_to_domain(docname: str, compation: bool) -> str: +def docname_to_domain(docname: str, compation: Union[bool, str]) -> str: """Convert docname to domain for catalogs.""" + if isinstance(compation, str): + return compation if compation: return docname.split(SEP, 1)[0] else: diff --git a/sphinx/util/template.py b/sphinx/util/template.py index 18047d687..bb078a2a2 100644 --- a/sphinx/util/template.py +++ b/sphinx/util/template.py @@ -84,6 +84,8 @@ class LaTeXRenderer(SphinxRenderer): self.env.variable_end_string = '%>' self.env.block_start_string = '<%' self.env.block_end_string = '%>' + self.env.comment_start_string = '<#' + self.env.comment_end_string = '<#' class ReSTRenderer(SphinxRenderer): diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 4375bf326..8813c2d12 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -450,7 +450,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): highlighted = self.highlighter.highlight_block( node.rawsource, lang, opts=opts, linenos=linenos, - location=(self.builder.current_docname, node.line), **highlight_args + location=node, **highlight_args ) starttag = self.starttag(node, 'div', suffix='', CLASS='highlight-%s notranslate' % lang) diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index c1252f4d0..4ceeaafdf 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -402,7 +402,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): highlighted = self.highlighter.highlight_block( node.rawsource, lang, opts=opts, linenos=linenos, - location=(self.builder.current_docname, node.line), **highlight_args + location=node, **highlight_args ) starttag = self.starttag(node, 'div', suffix='', CLASS='highlight-%s notranslate' % lang) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 73a22a76b..b77202951 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -651,7 +651,7 @@ class LaTeXTranslator(SphinxTranslator): if len(node.children) != 1 and not isinstance(node.children[0], nodes.Text): logger.warning(__('document title is not a single Text node'), - location=(self.curfilestack[-1], node.line)) + location=node) if not self.elements['title']: # text needs to be escaped since it is inserted into # the output literally @@ -684,7 +684,7 @@ class LaTeXTranslator(SphinxTranslator): else: logger.warning(__('encountered title node not in section, topic, table, ' 'admonition or sidebar'), - location=(self.curfilestack[-1], node.line or '')) + location=node) self.body.append('\\sphinxstyleothertitle{') self.context.append('}\n') self.in_title = 1 @@ -1762,7 +1762,7 @@ class LaTeXTranslator(SphinxTranslator): hlcode = self.highlighter.highlight_block( node.rawsource, lang, opts=opts, linenos=linenos, - location=(self.curfilestack[-1], node.line), **highlight_args + location=node, **highlight_args ) if self.in_footnote: self.body.append('\n\\sphinxSetupCodeBlockInFootnote') diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 8c52a0868..5ad2831dd 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -628,7 +628,7 @@ class TexinfoTranslator(SphinxTranslator): elif not isinstance(parent, nodes.section): logger.warning(__('encountered title node not in section, topic, table, ' 'admonition or sidebar'), - location=(self.curfilestack[-1], node.line)) + location=node) self.visit_rubric(node) else: try: @@ -1186,7 +1186,7 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('\n@caption{') else: logger.warning(__('caption not inside a figure.'), - location=(self.curfilestack[-1], node.line)) + location=node) def depart_caption(self, node: Element) -> None: if (isinstance(node.parent, nodes.figure) or @@ -1262,11 +1262,11 @@ class TexinfoTranslator(SphinxTranslator): def unimplemented_visit(self, node: Element) -> None: logger.warning(__("unimplemented node type: %r"), node, - location=(self.curfilestack[-1], node.line)) + location=node) def unknown_visit(self, node: Node) -> None: logger.warning(__("unknown node type: %r"), node, - location=(self.curfilestack[-1], node.line)) + location=node) def unknown_departure(self, node: Node) -> None: pass diff --git a/tests/roots/test-ext-autodoc/target/TYPE_CHECKING.py b/tests/roots/test-ext-autodoc/target/TYPE_CHECKING.py new file mode 100644 index 000000000..aa7eb99a6 --- /dev/null +++ b/tests/roots/test-ext-autodoc/target/TYPE_CHECKING.py @@ -0,0 +1,8 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from io import StringIO + + +class Foo: + attr1: "StringIO" diff --git a/tests/roots/test-ext-autodoc/target/typed_vars.py b/tests/roots/test-ext-autodoc/target/typed_vars.py index 43c58deb0..ba9657f18 100644 --- a/tests/roots/test-ext-autodoc/target/typed_vars.py +++ b/tests/roots/test-ext-autodoc/target/typed_vars.py @@ -28,4 +28,4 @@ class Class: class Derived(Class): - pass + attr7: int diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py index 1c86b8daa..074602ea9 100644 --- a/tests/test_build_gettext.py +++ b/tests/test_build_gettext.py @@ -174,3 +174,21 @@ def test_gettext_template_msgid_order_in_sphinxpot(app): 'msgid "This is Template 2\\.".*'), result, flags=re.S) + + +@pytest.mark.sphinx( + 'gettext', srcdir='root-gettext', + confoverrides={'gettext_compact': 'documentation'}) +def test_build_single_pot(app): + app.builder.build_all() + + assert (app.outdir / 'documentation.pot').isfile() + + result = (app.outdir / 'documentation.pot').read_text() + assert re.search( + ('msgid "Todo".*' + 'msgid "Like footnotes.".*' + 'msgid "The minute.".*' + 'msgid "Generated section".*'), + result, + flags=re.S) diff --git a/tests/test_domain_c.py b/tests/test_domain_c.py index 71bf251e9..b6f72287e 100644 --- a/tests/test_domain_c.py +++ b/tests/test_domain_c.py @@ -497,17 +497,16 @@ def test_attributes(): parse('member', 'paren_attr({]}) int f') # position: decl specs - check('function', 'static inline __attribute__(()) void f()', - {1: 'f'}, + check('function', 'static inline __attribute__(()) void f()', {1: 'f'}, output='__attribute__(()) static inline void f()') - check('function', '[[attr1]] [[attr2]] void f()', - {1: 'f'}, - output='[[attr1]] [[attr2]] void f()') + check('function', '[[attr1]] [[attr2]] void f()', {1: 'f'}) # position: declarator check('member', 'int *[[attr]] i', {1: 'i'}) check('member', 'int *const [[attr]] volatile i', {1: 'i'}, output='int *[[attr]] volatile const i') check('member', 'int *[[attr]] *i', {1: 'i'}) + # position: parameters + check('function', 'void f() [[attr1]] [[attr2]]', {1: 'f'}) # issue michaeljones/breathe#500 check('function', 'LIGHTGBM_C_EXPORT int LGBM_BoosterFree(int handle)', diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 118227cd7..558d69911 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -764,6 +764,7 @@ def test_templates(): check('class', "template<template<typename> typename> {key}A", {2: "II0E0E1A"}) check('class', "template<template<typename> typename ...T> {key}A", {2: "II0EDpE1A"}) check('class', "template<template<typename> typename...> {key}A", {2: "II0EDpE1A"}) + check('class', "template<typename T, template<typename> typename...> {key}A", {2: "I0I0EDpE1A"}) check('class', "template<int> {key}A", {2: "I_iE1A"}) check('class', "template<int T> {key}A", {2: "I_iE1A"}) @@ -937,15 +938,15 @@ def test_attributes(): check('function', 'static inline __attribute__(()) void f()', {1: 'f', 2: '1fv'}, output='__attribute__(()) static inline void f()') - check('function', '[[attr1]] [[attr2]] void f()', - {1: 'f', 2: '1fv'}, - output='[[attr1]] [[attr2]] void f()') + check('function', '[[attr1]] [[attr2]] void f()', {1: 'f', 2: '1fv'}) # position: declarator check('member', 'int *[[attr]] i', {1: 'i__iP', 2: '1i'}) check('member', 'int *const [[attr]] volatile i', {1: 'i__iPVC', 2: '1i'}, output='int *[[attr]] volatile const i') check('member', 'int &[[attr]] i', {1: 'i__iR', 2: '1i'}) check('member', 'int *[[attr]] *i', {1: 'i__iPP', 2: '1i'}) + # position: parameters and qualifiers + check('function', 'void f() [[attr1]] [[attr2]]', {1: 'f', 2: '1fv'}) def test_xref_parsing(): diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index d6f973f49..90a2ec95a 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -1580,12 +1580,7 @@ def test_autodoc_typed_instance_variables(app): ' :module: target.typed_vars', '', '', - ' .. py:attribute:: Derived.attr2', - ' :module: target.typed_vars', - ' :type: int', - '', - '', - ' .. py:attribute:: Derived.descr4', + ' .. py:attribute:: Derived.attr7', ' :module: target.typed_vars', ' :type: int', '', @@ -1615,6 +1610,47 @@ def test_autodoc_typed_instance_variables(app): ] +@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is available since python3.6.') +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_autodoc_typed_inherited_instance_variables(app): + options = {"members": None, + "undoc-members": True, + "inherited-members": True} + actual = do_autodoc(app, 'class', 'target.typed_vars.Derived', options) + assert list(actual) == [ + '', + '.. py:class:: Derived()', + ' :module: target.typed_vars', + '', + '', + ' .. py:attribute:: Derived.attr1', + ' :module: target.typed_vars', + ' :type: int', + ' :value: 0', + '', + '', + ' .. py:attribute:: Derived.attr2', + ' :module: target.typed_vars', + ' :type: int', + '', + '', + ' .. py:attribute:: Derived.attr3', + ' :module: target.typed_vars', + ' :value: 0', + '', + '', + ' .. py:attribute:: Derived.attr7', + ' :module: target.typed_vars', + ' :type: int', + '', + '', + ' .. py:attribute:: Derived.descr4', + ' :module: target.typed_vars', + ' :type: int', + '', + ] + + @pytest.mark.sphinx('html', testroot='ext-autodoc') def test_autodoc_GenericAlias(app): options = {"members": None, @@ -1704,6 +1740,28 @@ def test_autodoc_Annotated(app): ] +@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is required.') +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_autodoc_TYPE_CHECKING(app): + options = {"members": None, + "undoc-members": None} + actual = do_autodoc(app, 'module', 'target.TYPE_CHECKING', options) + assert list(actual) == [ + '', + '.. py:module:: target.TYPE_CHECKING', + '', + '', + '.. py:class:: Foo()', + ' :module: target.TYPE_CHECKING', + '', + '', + ' .. py:attribute:: Foo.attr1', + ' :module: target.TYPE_CHECKING', + ' :type: StringIO', + '', + ] + + @pytest.mark.sphinx('html', testroot='pycode-egg') def test_autodoc_for_egged_code(app): options = {"members": None, diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py index 9613e57d7..538227514 100644 --- a/tests/test_ext_napoleon_docstring.py +++ b/tests/test_ext_napoleon_docstring.py @@ -66,19 +66,19 @@ Sample namedtuple subclass Quick description of attr1 - :type: :class:`Arbitrary type` + :type: Arbitrary type .. attribute:: attr2 Quick description of attr2 - :type: :class:`Another arbitrary type` + :type: Another arbitrary type .. attribute:: attr3 Adds a newline after the type - :type: :class:`Type` + :type: Type """ self.assertEqual(expected, actual) @@ -1311,12 +1311,34 @@ class NumpyDocstringTest(BaseDocstringTest): config = Config( napoleon_use_param=False, napoleon_use_rtype=False, - napoleon_use_keyword=False) + napoleon_use_keyword=False, + napoleon_preprocess_types=True) for docstring, expected in self.docstrings: actual = str(NumpyDocstring(dedent(docstring), config)) expected = dedent(expected) self.assertEqual(expected, actual) + def test_type_preprocessor(self): + docstring = dedent(""" + Single line summary + + Parameters + ---------- + arg1:str + Extended + description of arg1 + """) + + config = Config(napoleon_preprocess_types=False, napoleon_use_param=False) + actual = str(NumpyDocstring(docstring, config)) + expected = dedent(""" + Single line summary + + :Parameters: **arg1** (*str*) -- Extended + description of arg1 + """) + self.assertEqual(expected, actual) + def test_parameters_with_class_reference(self): docstring = """\ Parameters @@ -1340,6 +1362,32 @@ param1 : :class:`MyClass <name.space.MyClass>` instance """ self.assertEqual(expected, actual) + def test_multiple_parameters(self): + docstring = """\ +Parameters +---------- +x1, x2 : array_like + Input arrays, description of ``x1``, ``x2``. + +""" + + config = Config(napoleon_use_param=False) + actual = str(NumpyDocstring(docstring, config)) + expected = """\ +:Parameters: **x1, x2** (*array_like*) -- Input arrays, description of ``x1``, ``x2``. +""" + self.assertEqual(expected, actual) + + config = Config(napoleon_use_param=True) + actual = str(NumpyDocstring(dedent(docstring), config)) + expected = """\ +:param x1: Input arrays, description of ``x1``, ``x2``. +:type x1: array_like +:param x2: Input arrays, description of ``x1``, ``x2``. +:type x2: array_like +""" + self.assertEqual(expected, actual) + def test_parameters_without_class_reference(self): docstring = """\ Parameters @@ -1351,7 +1399,7 @@ param1 : MyClass instance config = Config(napoleon_use_param=False) actual = str(NumpyDocstring(docstring, config)) expected = """\ -:Parameters: **param1** (:class:`MyClass instance`) +:Parameters: **param1** (*MyClass instance*) """ self.assertEqual(expected, actual) @@ -1359,7 +1407,7 @@ param1 : MyClass instance actual = str(NumpyDocstring(dedent(docstring), config)) expected = """\ :param param1: -:type param1: :class:`MyClass instance` +:type param1: MyClass instance """ self.assertEqual(expected, actual) @@ -1448,7 +1496,7 @@ arg_ : type expected = """ :ivar arg_: some description -:vartype arg_: :class:`type` +:vartype arg_: type """ config = Config(napoleon_use_ivar=True) @@ -1468,7 +1516,7 @@ arg_ : type expected = """ :ivar arg\\_: some description -:vartype arg\\_: :class:`type` +:vartype arg\\_: type """ config = Config(napoleon_use_ivar=True) @@ -1913,59 +1961,59 @@ definition_after_normal_text : int expected = """One line summary. :param no_list: -:type no_list: :class:`int` +:type no_list: int :param one_bullet_empty: * -:type one_bullet_empty: :class:`int` +:type one_bullet_empty: int :param one_bullet_single_line: - first line -:type one_bullet_single_line: :class:`int` +:type one_bullet_single_line: int :param one_bullet_two_lines: + first line continued -:type one_bullet_two_lines: :class:`int` +:type one_bullet_two_lines: int :param two_bullets_single_line: - first line - second line -:type two_bullets_single_line: :class:`int` +:type two_bullets_single_line: int :param two_bullets_two_lines: * first line continued * second line continued -:type two_bullets_two_lines: :class:`int` +:type two_bullets_two_lines: int :param one_enumeration_single_line: 1. first line -:type one_enumeration_single_line: :class:`int` +:type one_enumeration_single_line: int :param one_enumeration_two_lines: 1) first line continued -:type one_enumeration_two_lines: :class:`int` +:type one_enumeration_two_lines: int :param two_enumerations_one_line: (iii) first line (iv) second line -:type two_enumerations_one_line: :class:`int` +:type two_enumerations_one_line: int :param two_enumerations_two_lines: a. first line continued b. second line continued -:type two_enumerations_two_lines: :class:`int` +:type two_enumerations_two_lines: int :param one_definition_one_line: item 1 first line -:type one_definition_one_line: :class:`int` +:type one_definition_one_line: int :param one_definition_two_lines: item 1 first line continued -:type one_definition_two_lines: :class:`int` +:type one_definition_two_lines: int :param two_definitions_one_line: item 1 first line item 2 second line -:type two_definitions_one_line: :class:`int` +:type two_definitions_one_line: int :param two_definitions_two_lines: item 1 first line @@ -1973,14 +2021,14 @@ definition_after_normal_text : int item 2 second line continued -:type two_definitions_two_lines: :class:`int` +:type two_definitions_two_lines: int :param one_definition_blank_line: item 1 first line extra first line -:type one_definition_blank_line: :class:`int` +:type one_definition_blank_line: int :param two_definitions_blank_lines: item 1 @@ -1993,12 +2041,12 @@ definition_after_normal_text : int second line extra second line -:type two_definitions_blank_lines: :class:`int` +:type two_definitions_blank_lines: int :param definition_after_normal_text: text line item 1 first line -:type definition_after_normal_text: :class:`int` +:type definition_after_normal_text: int """ config = Config(napoleon_use_param=True) actual = str(NumpyDocstring(docstring, config)) @@ -2092,7 +2140,7 @@ definition_after_normal_text : int item 1 first line """ - config = Config(napoleon_use_param=False) + config = Config(napoleon_use_param=False, napoleon_preprocess_types=True) actual = str(NumpyDocstring(docstring, config)) self.assertEqual(expected, actual) @@ -2273,6 +2321,7 @@ definition_after_normal_text : int config = Config( napoleon_use_param=True, napoleon_use_rtype=True, + napoleon_preprocess_types=True, napoleon_type_aliases=translations, ) actual = str(NumpyDocstring(docstring, config)) @@ -26,6 +26,7 @@ extras = test setenv = PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils + PYTEST_ADDOPTS = --color yes commands= pytest --durations 25 {posargs} @@ -40,16 +41,6 @@ extras = commands = flake8 {posargs} -[testenv:pylint] -basepython = python3 -description = - Run source code analyzer. -deps = - pylint - {[testenv]deps} -commands = - pylint --rcfile utils/pylintrc sphinx - [testenv:coverage] basepython = python3 description = diff --git a/utils/pylintrc b/utils/pylintrc deleted file mode 100644 index c2b338b79..000000000 --- a/utils/pylintrc +++ /dev/null @@ -1,301 +0,0 @@ -# lint Python modules using external checkers. -# -# This is the main checker controlling the other ones and the reports -# generation. It is itself both a raw checker and an astng checker in order -# to: -# * handle message activation / deactivation at the module level -# * handle some basic but necessary stats'data (number of classes, methods...) -# -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Profiled execution. -profile=no - -# Add <file or directory> to the black list. It should be a base name, not a -# path. You may set this option multiple times. -ignore=.svn - -# Pickle collected data for later comparisons. -persistent=yes - -# Set the cache size for astng objects. -cache-size=500 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable only checker(s) with the given id(s). This option conflict with the -# disable-checker option -#enable-checker= - -# Enable all checker(s) except those with the given id(s). This option conflict -# with the disable-checker option -#disable-checker= - -# Enable all messages in the listed categories. -#enable-msg-cat= - -# Disable all messages in the listed categories. -#disable-msg-cat= - -# Enable the message(s) with the given id(s). -#enable-msg= - -# Disable the message(s) with the given id(s). -disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201,W0613,W0612,W0622 - - -[REPORTS] - -# set the output format. Available formats are text, parseable, colorized and -# html -output-format=colorized - -# Include message's id in output -include-ids=yes - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells wether to display a full report or only the messages -reports=yes - -# Python expression which should return a note less than 10 (10 is the highest -# note).You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (R0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (R0004). -comment=no - -# Enable the report(s) with the given id(s). -#enable-report= - -# Disable the report(s) with the given id(s). -#disable-report= - - -# checks for -# * unused variables / imports -# * undefined variables -# * redefinition of variable from builtins or from an outer scope -# * use of variable before assigment -# -[VARIABLES] - -# Tells wether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching names used for dummy variables (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -# try to find bugs in the code using type inference -# -[TYPECHECK] - -# Tells wether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# When zope mode is activated, consider the acquired-members option to ignore -# access to some undefined attributes. -zope=no - -# List of members which are usually get through zope's acquisition mecanism and -# so shouldn't trigger E0201 when accessed (need zope=yes to be considered). -acquired-members=REQUEST,acl_users,aq_parent - - -# checks for : -# * doc strings -# * modules / classes / functions / methods / arguments / variables name -# * number of arguments, local variables, branchs, returns and statements in -# functions, methods -# * required module attributes -# * dangerous default values as arguments -# * redefinition of function / method / class -# * uses of the global statement -# -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# List of builtins function names that should not be used, separated by a comma -bad-functions=apply,input - - -# checks for sign of poor/misdesign: -# * number of methods, attributes, local variables... -# * size, complexity of functions, methods -# -[DESIGN] - -# Maximum number of arguments for function / method -max-args=12 - -# Maximum number of locals for function / method body -max-locals=30 - -# Maximum number of return / yield for function / method body -max-returns=12 - -# Maximum number of branch for function / method body -max-branchs=30 - -# Maximum number of statements in function / method body -max-statements=60 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=20 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=0 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -# checks for -# * external modules dependencies -# * relative / wildcard imports -# * cyclic imports -# * uses of deprecated modules -# -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report R0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report R0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report R0402 must -# not be disabled) -int-import-graph= - - -# checks for : -# * methods without self as first argument -# * overridden methods signature -# * access only to existant members via self -# * attributes not defined in the __init__ method -# * supported interfaces implementation -# * unreachable code -# -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - - -# checks for similarities and duplicated code. This computation may be -# memory / CPU intensive, so you should disable it if you experiments some -# problems. -# -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=10 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - - -# checks for: -# * warning notes in the code -# * PEP 263: source code with non ascii character but no encoding declaration -# -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -# checks for : -# * unauthorized constructions -# * strict indentation -# * line length -# * use of <> instead of != -# -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=90 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' |