immutable_default_args 0.0.9
Very small package to automatically safeguard mutable function arguments, preventing them from being modified.
License: MIT

===========================
Immutable default arguments
===========================

.. image:: https://img.shields.io/pypi/v/immutable-default-args.svg
    :target: https://pypi.python.org/pypi/immutable-default-args
    :alt: PyPI Package

.. image:: https://img.shields.io/pypi/pyversions/immutable-default-args.svg
    :target: https://pypi.python.org/pypi/immutable-default-args
    :alt: PyPI Python Versions

.. image:: https://img.shields.io/pypi/l/immutable-default-args.svg
    :target: https://pypi.python.org/pypi/immutable-default-args
    :alt: PyPI Package License

.. image:: https://travis-ci.org/timmwagener/immutable_default_args.svg?branch=develop
    :target: https://travis-ci.org/timmwagener/immutable_default_args
    :alt: Current build status for Travis CI

.. image:: https://ci.appveyor.com/api/projects/status/l67sbo0uis1kyxe9?svg=true
    :target: https://ci.appveyor.com/project/timmwagener/immutable-default-args
    :alt: Current build status for AppVeyor

.. image:: https://landscape.io/github/timmwagener/immutable_default_args/develop/landscape.svg?style=flat
   :target: https://landscape.io/github/timmwagener/immutable_default_args/develop
   :alt: 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 <http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument>`_ 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 <http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument>`_ 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.