A plugin for Flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle.

Overview

flake8-bugbear

https://travis-ci.org/PyCQA/flake8-bugbear.svg?branch=master

A plugin for Flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle:

bug·bear  (bŭg′bâr′)
n.
1. A cause of fear, anxiety, or irritation: *Overcrowding is often
   a bugbear for train commuters.*
2. A difficult or persistent problem: *"One of the major bugbears of
   traditional AI is the difficulty of programming computers to
   recognize that different but similar objects are instances of the
   same type of thing" (Jack Copeland).*
3. A fearsome imaginary creature, especially one evoked to frighten
   children.

It is felt that these lints don't belong in the main Python tools as they are very opinionated and do not have a PEP or standard behind them. Due to flake8 being designed to be extensible, the original creators of these lints believed that a plugin was the best route. This has resulted in better development velocity for contributors and adaptive deployment for flake8 users.

Installation

Install from pip with:

pip install flake8-bugbear

It will then automatically be run as part of flake8; you can check it has been picked up with:

$ flake8 --version
3.5.0 (assertive: 1.0.1, flake8-bugbear: 18.2.0, flake8-comprehensions: 1.4.1, mccabe: 0.6.1, pycodestyle: 2.3.1, pyflakes: 1.6.0) CPython 3.7.0 on Darwin

Development

If you'd like to do a PR we have development instructions here.

List of warnings

B001: Do not use bare except:, it also catches unexpected events like memory errors, interrupts, system exit, and so on. Prefer except Exception:. If you're sure what you're doing, be explicit and write except BaseException:. Disable E722 to avoid duplicate warnings.

B002: Python does not support the unary prefix increment. Writing ++n is equivalent to +(+(n)), which equals n. You meant n += 1.

B003: Assigning to os.environ doesn't clear the environment. Subprocesses are going to see outdated variables, in disagreement with the current process. Use os.environ.clear() or the env= argument to Popen.

B004: Using hasattr(x, '__call__') to test if x is callable is unreliable. If x implements custom __getattr__ or its __call__ is itself not callable, you might get misleading results. Use callable(x) for consistent results.

B005: Using .strip() with multi-character strings is misleading the reader. It looks like stripping a substring. Move your character set to a constant if this is deliberate. Use .replace() or regular expressions to remove string fragments.

B006: Do not use mutable data structures for argument defaults. They are created during function definition time. All calls to the function reuse this one instance of that data structure, persisting changes between them.

B007: Loop control variable not used within the loop body. If this is intended, start the name with an underscore.

B008: Do not perform function calls in argument defaults. The call is performed only once at function definition time. All calls to your function will reuse the result of that definition-time function call. If this is intended, assign the function call to a module-level variable and use that variable as a default value.

B009: Do not call getattr(x, 'attr'), instead use normal property access: x.attr. Missing a default to getattr will cause an AttributeError to be raised for non-existent properties. There is no additional safety in using getattr if you know the attribute name ahead of time.

B010: Do not call setattr(x, 'attr', val), instead use normal property access: x.attr = val. There is no additional safety in using setattr if you know the attribute name ahead of time.

B011: Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError().

B012: Use of break, continue or return inside finally blocks will silence exceptions or override return values from the try or except blocks. To silence an exception, do it explicitly in the except block. To properly use a break, continue or return refactor your code so these statements are not in the finally block.

B013: A length-one tuple literal is redundant. Write except SomeError: instead of except (SomeError,):.

B014: Redundant exception types in except (Exception, TypeError):. Write except Exception:, which catches exactly the same exceptions.

B015: Pointless comparison. This comparison does nothing but waste CPU instructions. Either prepend assert or remove it.

B016: Cannot raise a literal. Did you intend to return it or raise an Exception?

Python 3 compatibility warnings

These have higher risk of false positives but discover regressions that are dangerous to slip through when test coverage is not great. Let me know if a popular library is triggering any of the following warnings for valid code.

B301: Python 3 does not include .iter* methods on dictionaries. The default behavior is to return iterables. Simply remove the iter prefix from the method. For Python 2 compatibility, also prefer the Python 3 equivalent if you expect that the size of the dict to be small and bounded. The performance regression on Python 2 will be negligible and the code is going to be the clearest. Alternatively, use six.iter* or future.utils.iter*.

B302: Python 3 does not include .view* methods on dictionaries. The default behavior is to return viewables. Simply remove the view prefix from the method. For Python 2 compatibility, also prefer the Python 3 equivalent if you expect that the size of the dict to be small and bounded. The performance regression on Python 2 will be negligible and the code is going to be the clearest. Alternatively, use six.view* or future.utils.view*.

B303: The __metaclass__ attribute on a class definition does nothing on Python 3. Use class MyClass(BaseClass, metaclass=...). For Python 2 compatibility, use six.add_metaclass.

B304: sys.maxint is not a thing on Python 3. Use sys.maxsize.

B305: .next() is not a thing on Python 3. Use the next() builtin. For Python 2 compatibility, use six.next().

B306: BaseException.message has been deprecated as of Python 2.6 and is removed in Python 3. Use str(e) to access the user-readable message. Use e.args to access arguments passed to the exception.

Opinionated warnings

The following warnings are disabled by default because they are controversial. They may or may not apply to you, enable them explicitly in your configuration if you find them useful. Read below on how to enable.

B901: Using return x in a generator function used to be syntactically invalid in Python 2. In Python 3 return x can be used in a generator as a return value in conjunction with yield from. Users coming from Python 2 may expect the old behavior which might lead to bugs. Use native async def coroutines or mark intentional return x usage with # noqa on the same line.

B902: Invalid first argument used for method. Use self for instance methods, and cls for class methods (which includes __new__ and __init_subclass__) or instance methods of metaclasses (detected as classes directly inheriting from type).

B903: Use collections.namedtuple (or typing.NamedTuple) for data classes that only set attributes in an __init__ method, and do nothing else. If the attributes should be mutable, define the attributes in __slots__ to save per-instance memory and to prevent accidentally creating additional attributes on instances.

B950: Line too long. This is a pragmatic equivalent of pycodestyle's E501: it considers "max-line-length" but only triggers when the value has been exceeded by more than 10%. You will no longer be forced to reformat code due to the closing parenthesis being one character too far to satisfy the linter. At the same time, if you do significantly violate the line length, you will receive a message that states what the actual limit is. This is inspired by Raymond Hettinger's "Beyond PEP 8" talk and highway patrol not stopping you if you drive < 5mph too fast. Disable E501 to avoid duplicate warnings.

How to enable opinionated warnings

To enable these checks, specify a --select command-line option or select= option in your config file. As of Flake8 3.0, this option is a whitelist (checks not listed are being implicitly disabled), so you have to explicitly specify all checks you want enabled. For example:

[flake8]
max-line-length = 80
max-complexity = 12
...
ignore = E501
select = C,E,F,W,B,B901

Note that we're enabling the complexity checks, the PEP8 pycodestyle errors and warnings, the pyflakes fatals and all default Bugbear checks. Finally, we're also specifying B901 as a check that we want enabled. Some checks might need other flake8 checks disabled - e.g. E501 must be disabled for B950 to be hit.

If you'd like all optional warnings to be enabled for you (future proof your config!), say B9 instead of B901. You will need Flake8 3.2+ for this feature.

Note that pycodestyle also has a bunch of warnings that are disabled by default. Those get enabled as soon as there is an ignore = line in your configuration. I think this behavior is surprising so Bugbear's opinionated warnings require explicit selection.

Tests

Just run:

python tests/test_bugbear.py

License

MIT

Change Log

20.11.1

  • Support exception aliases properly in B014 (#129)
  • Add B015: Pointless comparison (#130)
  • Remove check for # noqa comments (#134)
  • Ignore exception classes which are not types (#135)
  • Introduce B016 to check for raising a literal. (#141)
  • Exclude types.MappingProxyType() from B008. (#144)

20.1.4

  • Ignore keywords for B009/B010

20.1.3

  • Silence B009/B010 for non-identifiers
  • State an ignore might be needed for optional B9x checks

20.1.2

  • Fix error on attributes-of-attributes in except (...): clauses

20.1.1

  • Allow continue/break within loops in finally clauses for B012
  • For B001, also check for except ():
  • Introduce B013 and B014 to check tuples in except (..., ): statements

20.1.0

  • Warn about continue/return/break in finally block (#100)
  • Removed a colon from the descriptive message in B008. (#96)

19.8.0

  • Fix .travis.yml syntax + add Python 3.8 + nightly tests
  • Fix black formatting + enforce via CI
  • Make B901 not apply to __await__ methods

19.3.0

  • allow 'mcs' for metaclass classmethod first arg (PyCharm default)
  • Introduce B011
  • Introduce B009 and B010
  • Exclude immutable calls like tuple() and frozenset() from B008
  • For B902, the first argument for metaclass class methods can be "mcs", matching the name preferred by PyCharm.

18.8.0

  • black format all .py files
  • Examine kw-only args for mutable defaults
  • Test for Python 3.7

18.2.0

  • packaging fixes

17.12.0

  • graduated to Production/Stable in trove classifiers
  • introduced B008

17.4.0

  • bugfix: Also check async functions for B006 + B902

17.3.0

  • introduced B903 (patch contributed by Martijn Pieters)
  • bugfix: B902 now enforces cls for instance methods on metaclasses and metacls for class methods on metaclasses

17.2.0

  • introduced B902
  • bugfix: opinionated warnings no longer invisible in Syntastic
  • bugfix: opinionated warnings stay visible when --select on the command-line is used with full three-digit error codes

16.12.2

  • bugfix: opinionated warnings no longer get enabled when user specifies ignore = in the configuration. Now they require explicit selection as documented above also in this case.

16.12.1

  • bugfix: B007 no longer crashes on tuple unpacking in for-loops

16.12.0

  • introduced B007
  • bugfix: remove an extra colon in error formatting that was making Bugbear errors invisible in Syntastic
  • marked as "Beta" in trove classifiers, it's been used in production for 8+ months

16.11.1

  • introduced B005
  • introduced B006
  • introduced B950

16.11.0

  • bugfix: don't raise false positives in B901 on closures within generators
  • gracefully fail on Python 2 in setup.py

16.10.0

  • introduced B004
  • introduced B901, thanks Markus!
  • update flake8 constraint to at least 3.0.0

16.9.0

  • introduced B003

16.7.1

  • bugfix: don't omit message code in B306's warning
  • change dependency on pep8 to dependency on pycodestyle, update flake8 constraint to at least 2.6.2

16.7.0

  • introduced B306

16.6.1

  • bugfix: don't crash on files with tuple unpacking in class bodies

16.6.0

  • introduced B002, B301, B302, B303, B304, and B305

16.4.2

  • packaging herp derp

16.4.1

  • bugfix: include tests in the source package (to make setup.py test work for everyone)
  • bugfix: explicitly open README.rst in UTF-8 in setup.py for systems with other default encodings

16.4.0

  • first published version
  • date-versioned

Authors

Glued together by Łukasz Langa. Multiple improvements by Markus Unterwaditzer, Martijn Pieters, Cooper Lees, and Ryan May.

Comments
  • B023 false alarms

    B023 false alarms

    When upgrading, some false positives were found for B023 (implimented in https://github.com/PyCQA/flake8-bugbear/pull/265).

    Example

    """B023.py"""
    def filter_values(values: list[list[int]], max_percentage: float):
        for value in values:
            filter_val = max(value) * max_percentage
            yield list(filter(lambda x: x < filter_val, value))
    
    
    $ flake8 B023.py
    bugbear_me.py:4:41: B023 Function definition does not bind loop variable 'filter_val' is valid, and doesn't fall into the 
    

    A silly example here, but one where the use of filter_val is valid.

    cc @Zac-HD In the PR you mentioned some hard to detect false positives that you were okay with. Was this kind of pattern one of the ones you had in mind?

    Thanks for this check btw, I think it's a good idea. I've fallen for this in the past!

    opened by paw-lu 24
  • Codes B301-B306 conflict with openstack/bandit (via. flake8-bandit)

    Codes B301-B306 conflict with openstack/bandit (via. flake8-bandit)

    Similar situation to #20, there are conflicts across codes B301-B306.

    https://github.com/openstack/bandit:

    The following tests were discovered and loaded:
      ...
      B301  pickle
      B302  marshal
      B303  md5
      B304  ciphers
      B305  cipher_modes
      B306  mktemp_q
    
    • https://github.com/tylerwince/flake8-bandit is "a flake8 wrapper around [bandit]"

    In my situation:

    • When both are installed, bandit is still available while bugbear is deactivated
    • If I uninstall bandit, bugbear is activated and works as expected
    opened by myii 19
  • bugbear 21.4.1 + 21.4.2 fails with AttributeError

    bugbear 21.4.1 + 21.4.2 fails with AttributeError

    Newly updated bugbear 21.4.1 fails with AttributeError:

    21:06:51 Traceback (most recent call last):
    21:06:51   File "/usr/lib/python3.6/multiprocessing/pool.py", line 119, in worker
    21:06:51     result = (True, func(*args, **kwds))
    21:06:51   File "/usr/lib/python3.6/multiprocessing/pool.py", line 44, in mapstar
    21:06:51     return list(map(*args))
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/flake8/checker.py", line 676, in _run_checks
    21:06:51     return checker.run_checks()
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/flake8/checker.py", line 589, in run_checks
    21:06:51     self.run_ast_checks()
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/flake8/checker.py", line 494, in run_ast_checks
    21:06:51     for (line_number, offset, text, _) in runner:
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 36, in run
    21:06:51     visitor.visit(self.tree)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 165, in visit
    21:06:51     super().visit(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 253, in visit
    21:06:51     return visitor(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 261, in generic_visit
    21:06:51     self.visit(item)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 165, in visit
    21:06:51     super().visit(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 253, in visit
    21:06:51     return visitor(node)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 306, in visit_ClassDef
    21:06:51     self.generic_visit(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 261, in generic_visit
    21:06:51     self.visit(item)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 165, in visit
    21:06:51     super().visit(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 253, in visit
    21:06:51     return visitor(node)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 302, in visit_FunctionDef
    21:06:51     self.generic_visit(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 261, in generic_visit
    21:06:51     self.visit(item)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 165, in visit
    21:06:51     super().visit(node)
    21:06:51   File "/usr/lib/python3.6/ast.py", line 253, in visit
    21:06:51     return visitor(node)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 321, in visit_With
    21:06:51     self.check_for_b017(node)
    21:06:51   File "/src/.tox/flake8-py36/lib/python3.6/site-packages/bugbear.py", line 442, in check_for_b017
    21:06:51     hasattr(item_context.func, "attr")
    21:06:51 AttributeError: 'Name' object has no attribute 'func'
    21:06:51 """
    

    See https://integration.wikimedia.org/ci/job/pywikibot-core-tox-docker/14952/console

    bug help wanted 
    opened by xqt 18
  • Warn against using yield and return x

    Warn against using yield and return x

    opened by untitaker 17
  • B018 wrongly detects inline variable or attribute docstrings

    B018 wrongly detects inline variable or attribute docstrings

    Having an inline attribute doc string or a module variable docstring, it is wrongly marked as B018 (sample from sphinx doc):

    module_level_variable2 = 98765
    """int: Module level variable documented inline.
    
    The docstring may span multiple lines. The type may optionally be specified
    on the first line, separated by a colon.
    """
    
    
    bug help wanted 
    opened by xqt 16
  • B001 misses some bare excepts

    B001 misses some bare excepts

    B001 and Flake8/pycodestyle E722 both check for bare_except, but B001 misses a lot of cases that E722 finds.

    We noticed this when we tried running an internal tool that looks for overlaps in checks -- we are writing some of our own and don't want to overlap -- and found that every time B001 fires E722 also fires; but the reverse is not true.

    Tool output: B001 (6786) <-> E722 (34093): 13572 occurred at same line+path B001 implies E722: 100% E722 implies B001: 19%

    I took a look at the implementations for B001 and E722 and found that bugbear uses the AST and E722 uses a regex:

    Bugbear implementation uses AST.

    def visit_ExceptHandler(self, node):
        if node.type is None:
            self.errors.append(B001(node.lineno, node.col_offset))
        self.generic_visit(node)
    

    Flake8 implementation uses regex.

    def bare_except(logical_line, noqa):
        if noqa:
            return
    
        regex = re.compile(r"except\s*:")
        match = regex.match(logical_line)
        if match:
            yield match.start(), "E722 do not use bare 'except'"
    

    From the implementation, it looks like B001 and E722 should hit the same locations every time.

    We have a platform that lets us run static analysis over a bunch of open source repositories at the same time, so I ran vanilla flake8 and bugbear at the same time to see if there was a pattern, but one wasn't immediately obvious.

    I thought this might be related to forgetting to call visit or something like that (I've been bitten by that before!) but the reason for this disparity wasn't clear to me... so I'm making this issue. Feel free to reach out to me if you have any other questions!

    Here are some examples:

    image

    image

    image

    opened by minusworld 16
  • Add B019 check to find cache decorators on class methods

    Add B019 check to find cache decorators on class methods

    As described in #217, using functools.cache/functools.lru_cache on class methods can potentially cause their instances to live longer than expected.

    I took a stab at adding a rule to catch this pattern but I have a few questions:

    1. flake8-bugbear's error messages generally try to propose a solution to make the linting error go away (besides ignoring the line), but I'm not sure about the verbiage to include. For reference, the starting point is the following:

    Use of functools.lru_cache or functools.cache on class methods can lead to memory leaks. The cache may retain instance references, preventing garbage collection.

    1. Should this be restricted to caches that are explicitly unbounded, rather than any use of a built-in cache with a class method? i.e. this would only raise for functools.cache and functools.lru_cache(maxsize=None). This seems to more specifically address the issue though some still may not want to potentially keep these instances alive, bounded cache or not.

    Related reading:

    • https://bugs.python.org/issue19859
    • https://bugs.python.org/issue44310
    • https://docs.python.org/3/faq/programming.html#how-do-i-cache-method-calls

    Resolves: #217 Resolves: #215 Resolves: #212 Resolves: #221

    opened by sco1 15
  • Add `B904` - Use `raise ... from err` in `except` clauses

    Add `B904` - Use `raise ... from err` in `except` clauses

    Closes #180, by adding a new check ~~B018~~ B904 to recommend exception chaining. For example,

    try:
        assert False
    except AssertionError:
        raise RuntimeError  # B904: Within an except clause, use `raise ... from err` ...
    

    This turned out to be remarkably easy to add to the existing code 😁

    opened by Zac-HD 15
  • Proposed check: use suppress context manager

    Proposed check: use suppress context manager

    Instead of

    try:
        do_something()
    except RuntimeError:
        pass
    

    suggest using

    with contextlib.suppress(RuntimeError):
        do_something()
    

    What do you think?

    opened by atugushev 11
  • B904: ensure the raise is in the same context with the except

    B904: ensure the raise is in the same context with the except

    Resolves #190. Introduces a simple version of context management, though more detailed analysis might need something a little bit specialized in the future (e.g stuff like this).

    opened by isidentical 10
  • extend-immutable-calls: how to configure?

    extend-immutable-calls: how to configure?

    I haven't been able to make the recently released feature extend-immutable-calls to work.

    Have I configured it wrong?

    I have verified that flake8 recognizes the config, by setting the line-length to 10 and verified flake8 warnings about line length.

    flake8 --version
    
    4.0.1 (flake8-bugbear: 21.11.29, mccabe: 0.6.1, pycodestyle: 2.8.0, pyflakes: 2.4.0) CPython 3.10.0 on
    Darwin
    

    example.py

    import fastapi
    
    
    def example_fn(data: str = fastapi.Header(None)):
        pass
    

    setup.cfg

    [flake8]
    max-line-length = 120
    extend-immutable-calls = ["fastapi.Header"]
    
    flake8 --show-source
    
    ./example.py:4:28: B008 Do not perform function calls in argument defaults.  The call is performed only once at function definition time. All calls to your function will reuse the result of that definition-time function call.  If this is intended, assign the function call to a module-level variable and use that variable as a default value.
    def example_fn(data: str = fastapi.Header(None)):
                               ^
    
    opened by DavidVujic 8
  • Recommend Counter() in place of defaultdict(int)

    Recommend Counter() in place of defaultdict(int)

    I am suggesting a new check to recommend replacing defaultdict(int) with Counter(), both of which are from the standard library collections, due to the former having a major gotcha with memory usage.

    Consider this test case:

    from collections import Counter
    from collections import defaultdict
    
    # Profiled using;
    # $ mprof run defaultdict_leak.py && mprof plot
    if True:
        # Apparent memory leak
        # Over 700MB using Python 3.9.13 on macOS
        # Over 900MB using Python 3.9.15 on Linux
        counts = defaultdict(int)
    else:
        # Low and flat memory
        # about 16MB using Python 3.9.13 on macOS
        # about 19MB using Python 3.9.15 on Linux
        counts = Counter()
    
    # Setup some sparse data
    for x in [12,34,56,78,90]:
        counts[str(x)] = 123 + x
    
    threshold = 100
    excesses = 0
    for x in range(int(1e7)):
        if threshold < counts[str(x)]:
            excesses += counts[str(x)]
    print(f"Sum of entries exceeding the threshold {threshold} is {excesses}")
    

    The apparent memory leak with defaultdict is due to the documented behaviour of recording the missing keys in the dictionary with the default value, https://docs.python.org/3/library/collections.html#collections.defaultdict says:

    ... provide a default value for the given key, this value is inserted in the dictionary for the key, and returned.

    ...

    When each key is encountered for the first time, it is not already in the mapping; so an entry is automatically created using the default_factory ...

    I assume I'm not the only person to have used defaultdict without appreciating this, and in the case of defaultdict(int) there is good alternative in Counter()

    enhancement help wanted 
    opened by peterjc 2
  • Suggest `!r` format specifier for strings like `f

    Suggest `!r` format specifier for strings like `f"foo is '{self.foo}'"`

    I've seen some code lately where a reminder about the !r format specifier would probably have helped - instead of displaying the repr, single-quotes were manually added outside the braces as in f"No value found at '{path}'". This OK, until path contains a single-quote character and then it can get confusing fast.

    I'd therefore propose warning about this case, which is conveniently easy to reliably detect using the JoinedStr and FormattedValue nodes - within a JoinedStr, warn if there is a sequence of Constant/FormattedValue/Constant, where the first constant ends and the second starts with a single or double quote character, and the formatter value has no conversion code.

    Separately, I used the regex ".*('\{[^}]+\}').*" to confirm that this is common enough to be worth linting for. It's not especially rare, and IMO pretty useful to teach people about format specifiers.

    enhancement help wanted 
    opened by Zac-HD 2
  • Report incorrect assigning of dictionary entries with a colon (`:`)

    Report incorrect assigning of dictionary entries with a colon (`:`)

    Consider the following code

    dct = {
        'a': 1,
    }
    dct['b']: 2
    print(dct)  # {'a': 1}
    

    This is actually valid python syntax, because it is typing the 'b' entry as a 2 type. But we can assume the user meant to assign an element rather than type it (especially if there's no equal on this line).

    (Recommended I post this to bugbear by pyflakes maintainers here: https://github.com/PyCQA/pyflakes/issues/756)

    enhancement help wanted 
    opened by dannysepler 2
  • Question: B027 empty method in an abstract base class

    Question: B027 empty method in an abstract base class

    Short question on the reason behind newly added B027: If we have an ABC

    from abc import ABC, abstractmethod
    
    class MyABC(ABC):
        
        def method(self):
            """
            Some method that does nothing by default. Derived classes can choose to override it.
            """
            pass
    
        @abstractmethod
        def method2(self):
            """
            Another method. Derived classes MUST define it.
            """
    

    B027 will raise on the first method for not being declared abstract.

    Is there a way of allowing it to be empty despite the class being abstract? (Besides noqa and besides overriding them with an empty method in derived classes.) I would argue that there is reason to have empty methods provided by the ABC (interface) where the default implementation is to do nothing, but that derived classes can choose to override (e.g. if they need to perform some initialization / tear down of servers in my case), as opposed to methods that must be overridden.

    opened by yannikschaelte 1
  • Require warnings.warn stacklevel argument as 2+

    Require warnings.warn stacklevel argument as 2+

    Calling warnings.warn() without a stacklevel, or a stacklevel value of <2, is nearly always a mistake. Doing so flags the warning inside the called function, rather than the caller, making it hard to fix the warning.

    flake8-bugbear could detect such invocations of warnings.warn().

    This issue inspired by @asottile's video of the day: https://www.youtube.com/watch?v=CtFdXBEwYfk . This is also something I've seen recur as a review point in Django PR's.

    enhancement help wanted 
    opened by adamchainz 1
Releases(22.12.6)
Owner
Python Code Quality Authority
Organization for code quality tools (and plugins) for the Python programming language
Python Code Quality Authority
It's not just a linter that annoys you!

README for Pylint - https://pylint.pycqa.org/ Professional support for pylint is available as part of the Tidelift Subscription. Tidelift gives softwa

Python Code Quality Authority 4.4k Jan 04, 2023
Flake8 wrapper to make it nice, legacy-friendly, configurable.

THE PROJECT IS ARCHIVED Forks: https://github.com/orsinium/forks It's a Flake8 wrapper to make it cool. Lint md, rst, ipynb, and more. Shareable and r

Life4 232 Dec 16, 2022
🦆 Better duck-typing with mypy-compatible extensions to Protocol

🦆 Quacks If it walks like a duck and it quacks like a duck, then it must be a duck Thanks to PEP544, Python now has protocols: a way to define duck t

Arie Bovenberg 9 Nov 14, 2022
Python classes with types validation at runtime.

typedclasses Python classes with types validation at runtime. (Experimental & Under Development) Installation You can install this library using Pytho

Izhar Ahmad 8 Feb 06, 2022
Automated security testing using bandit and flake8.

flake8-bandit Automated security testing built right into your workflow! You already use flake8 to lint all your code for errors, ensure docstrings ar

Tyler Wince 96 Jan 01, 2023
Flake8 plugin to validate annotations complexity

flake8-annotations-complexity An extension for flake8 to report on too complex type annotations. Complex type annotations often means bad annotations

BestDoctor 41 Dec 28, 2022
Easy saving and switching between multiple KDE configurations.

Konfsave Konfsave is a config manager. That is, it allows you to save, back up, and easily switch between different (per-user) system configurations.

42 Sep 25, 2022
Mypy plugin and stubs for SQLAlchemy

Pythonista Stubs Stubs for the Pythonista iOS API. This allows for better error detection and IDE / editor autocomplete. Installation and Usage pip in

Dropbox 521 Dec 29, 2022
Run isort, pyupgrade, mypy, pylint, flake8, and more on Jupyter Notebooks

Run isort, pyupgrade, mypy, pylint, flake8, mdformat, black, blacken-docs, and more on Jupyter Notebooks ✅ handles IPython magics robustly ✅ respects

663 Jan 08, 2023
Pylint plugin to enforce some secure coding standards for Python.

Pylint Secure Coding Standard Plugin pylint plugin that enforces some secure coding standards. Installation pip install pylint-secure-coding-standard

Nguyen Damien 2 Jan 04, 2022
A static type analyzer for Python code

pytype - 🦆 ✔ Pytype checks and infers types for your Python code - without requiring type annotations. Pytype can: Lint plain Python code, flagging c

Google 4k Dec 31, 2022
Type annotations builder for boto3 compatible with VSCode, PyCharm, Emacs, Sublime Text, pyright and mypy.

mypy_boto3_builder Type annotations builder for boto3-stubs project. Compatible with VSCode, PyCharm, Emacs, Sublime Text, mypy, pyright and other too

Vlad Emelianov 2 Dec 05, 2022
Reference implementation of sentinels for the Python stdlib

Sentinels This is a reference implementation of a utility for the definition of sentinel values in Python. This also includes a draft PEP for the incl

Tal Einat 22 Aug 27, 2022
coala provides a unified command-line interface for linting and fixing all your code, regardless of the programming languages you use.

"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." ― John F. Woods coala provides a

coala development group 3.4k Dec 29, 2022
Mypy stubs, i.e., type information, for numpy, pandas and matplotlib

Mypy type stubs for NumPy, pandas, and Matplotlib This is a PEP-561-compliant stub-only package which provides type information for matplotlib, numpy

Predictive Analytics Lab 194 Dec 19, 2022
Typed interface stubs for Pythonista iOS

Pythonista Stubs Stubs for the Pythonista iOS API. This allows for better error detection and IDE / editor autocomplete. Installation and Usage pip in

Harold Martin 12 Jul 14, 2020
An enhanced version of the Python typing library.

typingplus An enhanced version of the Python typing library that always uses the latest version of typing available, regardless of which version of Py

Contains 6 Mar 26, 2021
Utilities for pycharm code formatting (flake8 and black)

Pycharm External Tools Extentions to Pycharm code formatting tools. Currently supported are flake8 and black on a selected code block. Usage Flake8 [P

Haim Daniel 13 Nov 03, 2022
The strictest and most opinionated python linter ever!

wemake-python-styleguide Welcome to the strictest and most opinionated python linter ever. wemake-python-styleguide is actually a flake8 plugin with s

wemake.services 2.1k Jan 01, 2023
flake8 plugin that integrates isort

Flake8 meet isort Use isort to check if the imports on your python files are sorted the way you expect. Add an .isort.cfg to define how you want your

Gil Forcada Codinachs 139 Nov 08, 2022