Skip to main content

Very small package to automatically safeguard mutable function arguments, preventing them from being modified.

Project description

PyPI Package PyPI Python Versions PyPI Package License Current build status for Travis CI Current build status for AppVeyor Code Health

This module provides facilities for turning mutable default function arguments into immutable ones. It is fairly lightweight and has no non-standard dependencies. You can install this package with the standard pip command:

$ pip install immutable_default_args

The issue with mutable argument default values is pretty well known in Python. Basically mutable default values are assigned once at define time and can then be modified within the function body which might come as a surprise. Here is the example from the stackoverfow thread:

def foo(a=[]):
    a.append(5)
    return a

>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
...

The default way of preventing this behaviour is to use None as the default and check for it in the function body, like so:

def foo(a=None):
    a = a if (type(a) is list) else []
    a.append(5)
    return a

>>> foo()
[5]
>>> foo()
[5]
...

Usage

This package aims to offer two additional options to fix this issue:

  • With a handy function decorator @fix_mutable_kwargs to fix a certain function.
  • With a metaclass ImmutableDefaultArguments to fix all methods, classmethods and staticmethods at once.

Using the decorator:

from immutable_default_args import fix_mutable_kwargs

@fix_mutable_kwargs
def foo(a=[]):
    a.append(5)
    return a

>>> foo()
[5]
>>> foo()
[5]
...

It doesn’t matter if the iterable is empty or not:

@fix_mutable_kwargs
def foo(a=[1, 2, {'key': 'value'}, 3, 4]):
    a.append(5)
    return a

>>> foo()
[1, 2, {'key': 'value'}, 3, 4, 5]
>>> foo()
[1, 2, {'key': 'value'}, 3, 4, 5]
...

Fixing all mutable default values for all methods of an object via the ImmutableDefaultArguments metaclass:

class Foo(object):

    __metaclass__ = ImmutableDefaultArguments  # Py2 syntax

    def foo(self, a=[]):
        a.append(5)
        return a

    @classmethod  # staticmethods work as well
    def foo_classmethod(cls, a=[]):
        a.append(5)
        return a

instance_of_foo = Foo()
>>> instance_of_foo.foo()
[5]
>>> instance_of_foo.foo()
[5]
...
>>> Foo.foo_classmethod()
[5]
>>> Foo.foo_classmethod()
[5]

Compatibility

The immutable_default_args package is tested against Py2/3 and is supported from Py2.7 upstream.

Changelog

0.0.8 (08.05.2016)

  • Add .landscape.yml and badges and more jazz.

0.0.7 (08.05.2016)

  • Add CI and badges and all that jazz.

0.0.5 (08.05.2016)

  • Fixed documentation

0.0.2 (08.05.2016)

  • Added @fix_mutable_kwargs decorator
  • Refactorings/Cleanup

0.0.1 (08.05.2016)

  • First release. Included only ImmutableDefaultArguments metaclass

License

You are free to do whatever you like with the code. Please note that I am not accountable for anything that might have happened as a result of executing the code from the immutable_default_args package….ever.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, size & hash SHA256 hash help File type Python version Upload date
immutable_default_args-0.0.9-py2.py3-none-any.whl (9.1 kB) Copy SHA256 hash SHA256 Wheel 3.4
immutable_default_args-0.0.9.zip (9.7 kB) Copy SHA256 hash SHA256 Source None

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN SignalFx SignalFx Supporter DigiCert DigiCert EV certificate StatusPage StatusPage Status page