Skip to content

Commit

Permalink
Implement new check, N819: TypedDict variable naming
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Patrick committed Jan 20, 2022
1 parent 9d199f1 commit 5ab9b69
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 16 deletions.
5 changes: 4 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ These error codes are emitted:
+---------+-----------------------------------------------------------------+
| _`N818` | error suffix in exception names (`exceptions`_) |
+---------+-----------------------------------------------------------------+
| _`N819` | mixedCase variable in TypedDict subclass |
| | (distinct from `N815`_ for selective enforcement) |
+---------+-----------------------------------------------------------------+

.. _class names: https://www.python.org/dev/peps/pep-0008/#class-names
.. _constants: https://www.python.org/dev/peps/pep-0008/#constants
Expand All @@ -88,7 +91,7 @@ The following flake8 options are added:

--ignore-names Ignore errors for specific names or glob patterns.

Currently, this option can only be used for N802, N803, N804, N805, N806, N815, and N816 errors.
Currently, this option can only be used for N802, N803, N804, N805, N806, N815, N816 and N819 errors.

Default: ``setUp,tearDown,setUpClass,tearDownClass,asyncSetUp,asyncTearDown,setUpTestData,failureException,longMessage,maxDiff``.

Expand Down
13 changes: 10 additions & 3 deletions src/pep8ext_naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,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'])
parser.extend_default_ignore(['N818', 'N819'])

@classmethod
def parse_options(cls, options):
Expand Down Expand Up @@ -449,13 +449,15 @@ class VariablesCheck(BaseASTCheck):
N806 = "variable '{name}' in function should be lowercase"
N815 = "variable '{name}' in class scope should not be mixedCase"
N816 = "variable '{name}' in global scope should not be mixedCase"
N819 = "variable '{name}' in TypedDict should not be mixedCase"

def _find_errors(self, assignment_target, parents, ignore):
for parent_func in reversed(parents):
if isinstance(parent_func, ast.ClassDef):
if "TypedDict" in parent_func.superclasses:
return
checker = self.class_variable_check
checker = self.typeddict_variable_check
else:
checker = self.class_variable_check
break
if isinstance(parent_func, FUNC_NODES):
checker = partial(self.function_variable_check, parent_func)
Expand Down Expand Up @@ -544,6 +546,11 @@ def function_variable_check(func, var_name):
return None
return 'N806'

@staticmethod
def typeddict_variable_check(name):
if is_mixed_case(name):
return 'N819'


def _extract_names(assignment_target):
"""Yield assignment_target ids."""
Expand Down
6 changes: 6 additions & 0 deletions testsuite/N815.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ class C:
#: Okay(--ignore-names=*Case)
class C:
mixed_Case = 0
#: N815
class TypedDict:
mixedCase: str
#: N815
class TypedDict:
more_Mixed_Case: str
12 changes: 0 additions & 12 deletions testsuite/N815_py38.py

This file was deleted.

18 changes: 18 additions & 0 deletions testsuite/N819_py36.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# python_version >= '3.6'
#: Okay
class MyDict(TypedDict):
snake_case: str
#: N819
class MyDict(TypedDict):
mixedCase: str
#: N819
class MyDict(TypedDict):
snake_case: str
class MyOtherDict(MyDict):
more_Mixed_Case: str
#: Okay(--ignore-names=mixedCase)
class MyDict(TypedDict):
mixedCase: str
#: Okay(--ignore-names=*Case)
class MyDict(TypedDict):
mixedCase: str

0 comments on commit 5ab9b69

Please sign in to comment.