Code Monkey home page Code Monkey logo

flake8-mutable's Introduction

flake8-mutable

PyPI version

Motivation

Python's default arguments are evaluated at definition as opposed to when the function is invoked. This leads to unexpected behavior, as mutations persist between calls. For a more detailed explanation, see The Hitchhiker's Guide to Python.

Example

def fnc(a, b={}):
    pass

foo.py:2:14: M511 - mutable default arg of type Dict

Installation

pip install flake8-mutable

Changes

[1.1.0] 2016-11-26
  • Callables
[1.0.6] 2016-11-26
  • added MANIFEST.in

License

MIT

flake8-mutable's People

Contributors

achiang avatar ar4s avatar diox avatar dopplershift avatar jaap3 avatar yoichi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

flake8-mutable's Issues

Deprecate for bugbear?

flake8-bugbear[1] includes a check for this:

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.

Since this repository is no longer maintained, one should consider using bugbear.

flake8 does not report mutable arguments (workaround)

When I run flake8 with flake8-mutable it fails to provide a warning.

bash-3.2$ cat testme.py
def fnc(a, b={}):
    b[a] = "hi"
    print(b)
    pass


fnc("a")
fnc("b")
fnc("c")
bash-3.2$ flake8 testme.py
bash-3.2$ python testme.py
{'a': 'hi'}
{'a': 'hi', 'b': 'hi'}
{'a': 'hi', 'b': 'hi', 'c': 'hi'}
bash-3.2$ flake8 --version
3.6.0 (flake-mutable: 1.2.0, mccabe: 0.6.1, pycodestyle: 2.4.0, pyflakes: 2.0.0) CPython 3.7.0 on Darwin

workaround - install flake8-bugbear instead

pip install flake8-bugbear

bash-3.2$ flake8 --version
3.6.0 (flake8-bugbear: 18.8.0, mccabe: 0.6.1, pycodestyle: 2.4.0, pyflakes: 2.0.0) CPython 3.7.0 on Darwin
bash-3.2$ flake8 testme.py
testme.py:1:14: B006 Do not use mutable data structures for argument defaults. All calls reuse one instance of that data structure, persisting changes between them.
bash-3.2$ 

Example code is not Linted.

Version

  • OS: Mac OS 10.15.2
  • Python Version: 3.7.4
  • Virtual environment: pyenv installed by Homebrew

Expected Behavior

$ flake8 foo.py
main.py:2:14: M511 - mutable default arg of type Dict

Current Behavior

$ flake8 foo.py

Details

I installed flake8-mutable 1.2.0.

$ pip install flake8-mutable
Collecting flake8-mutable
  Downloading flake8-mutable-1.2.0.tar.gz (3.0 kB)
Collecting flake8
  Using cached flake8-3.7.9-py2.py3-none-any.whl (69 kB)
Collecting pyflakes<2.2.0,>=2.1.0
  Using cached pyflakes-2.1.1-py2.py3-none-any.whl (59 kB)
Collecting mccabe<0.7.0,>=0.6.0
  Using cached mccabe-0.6.1-py2.py3-none-any.whl (8.6 kB)
Collecting entrypoints<0.4.0,>=0.3.0
  Using cached entrypoints-0.3-py2.py3-none-any.whl (11 kB)
Collecting pycodestyle<2.6.0,>=2.5.0
  Using cached pycodestyle-2.5.0-py2.py3-none-any.whl (51 kB)
Installing collected packages: pyflakes, mccabe, entrypoints, pycodestyle, flake8, flake8-mutable
    Running setup.py install for flake8-mutable ... done
Successfully installed entrypoints-0.3 flake8-3.7.9 flake8-mutable-1.2.0 mccabe-0.6.1 pycodestyle-2.5.0 pyflakes-2.1.1

And, I saved the sample code in my computer.

$ cat << EOF >> foo.py
def fnc(a, b={}):
    pass
EOF

$ cat foo.py 
def fnc(a, b={}):
    pass

I tried to lint against foo.py, but I don't find the error message.

$ flake8 foo.py

Fails with `TypeError: 'Name' object is not iterable`

$ flake8                                                                                                                                                                                                    
Traceback (most recent call last):                                                                                                                                                                                 
  File ".../bin/flake8", line 11, in <module>                                                                                                                                                                      
    sys.exit(main())                                                                                                                                                                                               
  File ".../lib/python2.7/site-packages/flake8/main.py", line 33, in main                                                                                                                                          
    report = flake8_style.check_files()                                                                                                                                                                            
  File ".../lib/python2.7/site-packages/flake8/engine.py", line 181, in check_files                                                                                                                                
    return self._retry_serial(self._styleguide.check_files, paths=paths)                                                                                                                                           
  File ".../lib/python2.7/site-packages/flake8/engine.py", line 172, in _retry_serial                                                                                                                              
    return func(*args, **kwargs)                                                                                                                                                                                   
  File ".../lib/python2.7/site-packages/pep8.py", line 1840, in check_files                                                                                                                                        
    self.input_dir(path)                                                                                                                                                                                           
  File ".../lib/python2.7/site-packages/pep8.py", line 1876, in input_dir                                                                                                                                          
    runner(os.path.join(root, filename))                                                                                                                                                                           
  File ".../lib/python2.7/site-packages/flake8/engine.py", line 126, in input_file                                                                                                                                 
    return fchecker.check_all(expected=expected, line_offset=line_offset)                                                                                                                                          
  File ".../lib/python2.7/site-packages/pep8.py", line 1574, in check_all                                                                                                                                          
    self.check_ast()                                                                                                                                                                                               
  File ".../lib/python2.7/site-packages/pep8.py", line 1521, in check_ast                                                                                                                                          
    for lineno, offset, text, check in checker.run():                                                                                                                                                              
  File ".../lib/python2.7/site-packages/mutable_defaults.py", line 44, in run                                                                                                                                      
    unexplored_nodes.extend(node.body)                                                                                                                                                                             
TypeError: 'Name' object is not iterable  
$ pip freeze
flake8==2.5.4
flake8-mutable==1.0.3
mccabe==0.4.0
pep8==1.7.0
pycodestyle==2.0.0
pyflakes==1.0.0

does not report errors for class constructors

class Container:
    def __init__(self, data=[]):
        self.data = data
    def add(v):
        self.data.append(v)

The intent in my class was that you could construct and populate in one call.

I fixed it as follows:

class Container:
    def __init__(self, data=[]):
        self.data = list(data) # enforce a copy
    def add(v):
        self.data.append(v)

but flake8 does not report the problem

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.