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
Flake8 extension to provide force-check option

flake8-force Flake8 extension to provide force-check option. When this option is enabled, flake8 performs all checks even if the target file cannot be

Kenichi Maehashi 9 Oct 29, 2022
A simple plugin that allows running mypy from PyCharm and navigate between errors

mypy-PyCharm-plugin The plugin provides a simple terminal to run fast mypy daemon from PyCharm with a single click or hotkey and easily navigate throu

Dropbox 301 Dec 09, 2022
The mypy playground. Try mypy with your web browser.

mypy-playground The mypy playground provides Web UI to run mypy in the sandbox: Features Web UI and sandbox for running mypy eas

Yusuke Miyazaki 57 Jan 02, 2023
MyPy types for WSGI applications

WSGI Types for Python This is an attempt to bring some type safety to WSGI applications using Python's new typing features (TypedDicts, Protocols). It

Blake Williams 2 Aug 18, 2021
Code audit tool for python.

Pylama Code audit tool for Python and JavaScript. Pylama wraps these tools: pycodestyle (formerly pep8) © 2012-2013, Florent Xicluna; pydocstyle (form

Kirill Klenov 967 Jan 07, 2023
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
Tools for improving Python imports

imptools Tools for improving Python imports. Installation pip3 install imptools Overview Detailed docs import_path Import a module from any path on th

Danijar Hafner 7 Aug 07, 2022
Mylint - My really simple rendition of how a linter works.

mylint My really simple rendition of how a linter works. This original version was written for my AST article. Since then I've added tests and turned

Tushar Sadhwani 2 Dec 29, 2021
Collection of awesome Python types, stubs, plugins, and tools to work with them.

Awesome Python Typing Collection of awesome Python types, stubs, plugins, and tools to work with them. Contents Static type checkers Dynamic type chec

TypedDjango 1.2k Jan 04, 2023
open source tools to generate mypy stubs from protobufs

mypy-protobuf: Generate mypy stub files from protobuf specs We just released a new major release mypy-protobuf 2. on 02/02/2021! It includes some back

Dropbox 527 Jan 03, 2023
Pyright extension for coc.nvim

coc-pyright Pyright extension for coc.nvim Install :CocInstall coc-pyright Note: Pyright may not work as expected if can't detect project root correct

Heyward Fann 1.1k Jan 02, 2023
Unbearably fast O(1) runtime type-checking in pure Python.

Look for the bare necessities, the simple bare necessities. Forget about your worries and your strife. — The Jungle Book.

beartype 1.4k Jan 01, 2023
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
Simple Python style checker in one Python file

pycodestyle (formerly called pep8) - Python style guide checker pycodestyle is a tool to check your Python code against some of the style conventions

Python Code Quality Authority 4.7k Jan 01, 2023
A simple program which checks Python source files for errors

Pyflakes A simple program which checks Python source files for errors. Pyflakes analyzes programs and detects various errors. It works by parsing the

Python Code Quality Authority 1.2k Dec 30, 2022
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
Flake8 extension for checking quotes in python

Flake8 Extension to lint for quotes. Major update in 2.0.0 We automatically encourage avoiding escaping quotes as per PEP 8. To disable this, use --no

Zachary Heller 157 Dec 13, 2022
Design by contract for Python. Write bug-free code. Add a few decorators, get static analysis and tests for free.

A Python library for design by contract (DbC) and checking values, exceptions, and side-effects. In a nutshell, deal empowers you to write bug-free co

Life4 473 Dec 28, 2022
Flashcards - A flash card application with 2 optional command line arguments

Flashcards A flash card application with 2 optional command line arguments impor

Özgür Yildirim 2 Jul 15, 2022
flake8 plugin to catch useless `assert` statements

flake8-useless-assert flake8 plugin to catch useless assert statements Download or install on the PyPI page Violations Code Description Example ULA001

1 Feb 12, 2022