Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set N818 to check error suffix on exception names. #157

Merged
merged 11 commits into from
Apr 18, 2021
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -70,6 +70,8 @@ These error codes are emitted:
+------+-------------------------------------------------------+
| N817 | camelcase imported as acronym |
+------+-------------------------------------------------------+
| N818 | error suffix in exception names |
+------+-------------------------------------------------------+

Options
-------
5 changes: 5 additions & 0 deletions run_tests.py
Original file line number Diff line number Diff line change
@@ -75,6 +75,10 @@ class OptionsManager(optparse.OptionParser):
def __init__(self, *args, **kwargs):
optparse.OptionParser.__init__(self, *args, **kwargs)
self.config_options = []
self.ignore = []

def extend_default_ignore(self, new_ignores):
self.ignore += new_ignores


def parse_options(checker, options):
@@ -85,6 +89,7 @@ def parse_options(checker, options):
options_manager.add_option('--ignore', default=[])
options_manager.add_option('--extend-ignore', default=[])
options_manager.add_option('--enable-extensions', default=[])
options_manager.add_option('--extended-default-ignore', default=[])
checker.add_options(options_manager)
processed_options, _ = options_manager.parse_args(options)
checker.parse_options(processed_options)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ def run_tests(self):
license='Expat license',
package_dir={'': 'src'},
py_modules=['pep8ext_naming'],
install_requires=['flake8_polyfill>=1.0.2,<2'],
install_requires=['flake8>=3.9.1', 'flake8_polyfill>=1.0.2,<2'],
zip_safe=False,
entry_points={
'flake8.extension': [
23 changes: 23 additions & 0 deletions src/pep8ext_naming.py
Original file line number Diff line number Diff line change
@@ -167,6 +167,7 @@ def add_options(cls, parser):
help='List of method decorators pep8-naming plugin '
'should consider staticmethods (Defaults to '
'%default)')
parser.extend_default_ignore(['N818'])

@classmethod
def parse_options(cls, options):
@@ -291,6 +292,25 @@ class ClassNameCheck(BaseASTCheck):
Classes for internal use have a leading underscore in addition.
"""
N801 = "class name '{name}' should use CapWords convention"
N818 = "exception name '{name}' should be named with an Error suffix"

def get_class_def(self, name, parents):
for parent in parents:
for definition in parent.body:
is_class_definition = isinstance(definition, ast.ClassDef)
if is_class_definition and definition.name == name:
return definition

def superclass_names(self, name, parents):
class_ids = set()
class_def = self.get_class_def(name, parents)
if not class_def:
return class_ids
for base in class_def.bases:
if hasattr(base, "id"):
class_ids.add(base.id)
class_ids.update(self.superclass_names(base.id, parents))
return class_ids

def visit_classdef(self, node, parents, ignore=None):
name = node.name
@@ -299,6 +319,9 @@ def visit_classdef(self, node, parents, ignore=None):
name = name.strip('_')
if not name[:1].isupper() or '_' in name:
yield self.err(node, 'N801', name=name)
superclasses = self.superclass_names(name, parents)
if "Exception" in superclasses and not name.endswith("Error"):
yield self.err(node, 'N818', name=name)


class FunctionNameCheck(BaseASTCheck):
30 changes: 30 additions & 0 deletions testsuite/N818.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#: Okay
class ActionError(Exception):
pass
#: N818
class ActionClass(Exception):
pass
#: Okay
class ActionError(Exception):
pass
class DeepActionError(ActionError):
pass
#: N818
class ActionError(Exception):
pass
class DeepActionClass(ActionError):
pass
#: Okay
class MixinError(Exception):
pass
class Mixin:
pass
class MixinActionError(Mixin, MixinError):
pass
#: N818
class MixinError(Exception):
pass
class Mixin:
pass
class MixinActionClass(Mixin, MixinError):
pass
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -6,15 +6,15 @@ commands = python run_tests.py

[testenv:py27-flake8]
deps =
flake8
flake8 >= 3.9.1
commands =
flake8 {posargs} src/pep8ext_naming.py
python setup.py check --restructuredtext

[testenv:py38-flake8]
basepython = python3.8
deps =
flake8
flake8 >= 3.9.1
commands =
flake8 {posargs} src/pep8ext_naming.py
python setup.py check --restructuredtext