Metadata-Version: 1.1
Name: choicesenum
Version: 0.7.0
Summary: Python's Enum with extra powers to play nice with labels and choices fields
Home-page: https://github.com/loggi/python-choicesenum
Author: Fernando Macedo
Author-email: fgmacedo@gmail.com
License: BSD license
Description: ============
        Choices Enum
        ============
        
        
        .. image:: https://img.shields.io/pypi/v/choicesenum.svg
                :target: https://pypi.python.org/pypi/choicesenum
        
        .. image:: https://travis-ci.org/loggi/python-choicesenum.svg?branch=master
                :target: https://travis-ci.org/loggi/python-choicesenum
        
        .. image:: https://readthedocs.org/projects/python-choicesenum/badge/?version=latest
                :target: https://python-choicesenum.readthedocs.io/en/latest/?badge=latest
                :alt: Documentation Status
        
        .. image:: https://coveralls.io/repos/github/loggi/python-choicesenum/badge.svg?branch=master
                :target: https://coveralls.io/github/loggi/python-choicesenum?branch=master
        
        
        Python's Enum with extra powers to play nice with labels and choices fields.
        
        * Free software: BSD license
        * Documentation: https://python-choicesenum.readthedocs.io.
        
        ------------
        Installation
        ------------
        
        Install ``choicesenum`` using pip::
        
            $ pip install choicesenum
        
        --------
        Features
        --------
        
        * An ``ChoicesEnum`` that can be used to create constant groups.
        * ``ChoicesEnum`` can define labels to be used in `choices` fields.
        * Django fields included:  ``EnumCharField`` and ``EnumIntegerField``.
        * All ``ChoicesEnum`` types can be compared against their primitive values directly.
        * Support (tested) for Python 2.7, 3.5, 3.6, 3.7 and 3.8.
        * Support (tested) for Django 1.9, 1.10, 1.11, 2.0, 2.1, 2.2 and 3.0.
        
        --------------
        Usage examples
        --------------
        
        Example with ``HttpStatuses``:
        
        .. code:: python
        
            class HttpStatuses(ChoicesEnum):
                OK = 200
                BAD_REQUEST = 400
                UNAUTHORIZED = 401
                FORBIDDEN = 403
        
        Example with ``Colors``:
        
        .. code:: python
        
            from choicesenum import ChoicesEnum
        
            class Colors(ChoicesEnum):
                RED = '#f00', 'Vermelho'
                GREEN = '#0f0', 'Verde'
                BLUE = '#00f', 'Azul'
        
        
        Comparison
        ----------
        
        All `Enum` types can be compared against their values:
        
        .. code:: python
        
            assert HttpStatuses.OK == 200
            assert HttpStatuses.BAD_REQUEST == 400
            assert HttpStatuses.UNAUTHORIZED == 401
            assert HttpStatuses.FORBIDDEN == 403
        
            status_code = HttpStatuses.OK
            assert 200 <= status_code <= 300
        
            assert Colors.RED == '#f00'
            assert Colors.GREEN == '#0f0'
            assert Colors.BLUE == '#00f'
        
        
        Label for free
        --------------
        
        All `Enum` types have by default a `display` derived from the enum identifier:
        
        .. code:: python
        
            assert HttpStatuses.OK.display == 'Ok'
            assert HttpStatuses.BAD_REQUEST.display == 'Bad request'
            assert HttpStatuses.UNAUTHORIZED.display == 'Unauthorized'
            assert HttpStatuses.FORBIDDEN.display == 'Forbidden'
        
        
        You can easily define your own custom display for an `Enum` item using a tuple:
        
        
        .. code:: python
        
            class HttpStatuses(ChoicesEnum):
                OK = 200, 'Everything is fine'
                BAD_REQUEST = 400, 'You did a mistake'
                UNAUTHORIZED = 401, 'I know your IP'
                FORBIDDEN = 403
        
            assert HttpStatuses.OK.display == 'Everything is fine'
            assert HttpStatuses.BAD_REQUEST.display == 'You did a mistake'
            assert HttpStatuses.UNAUTHORIZED.display == 'I know your IP'
            assert HttpStatuses.FORBIDDEN.display == 'Forbidden'
        
        
        Dynamic properties
        ------------------
        
        For each enum item, a dynamic property ``is_<enum_item>`` is generated to allow
        quick boolean checks:
        
        .. code:: python
        
            color = Colors.RED
            assert color.is_red
            assert not color.is_blue
            assert not color.is_green
        
        This feature is usefull to avoid comparing a received enum value against a know enum item.
        
        For example, you can replace code like this:
        
        .. code:: python
        
            # status = HttpStatuses.BAD_REQUEST
        
            def check_status(status):
                if status == HttpStatuses.OK:
                    print("Ok!")
        
        To this:
        
        .. code:: python
        
            def check_status(status):
                if status.is_ok:
                    print("Ok!")
        
        
        Custom methods and properties
        -----------------------------
        
        You can declare custom properties and methods:
        
        .. code:: python
        
            class HttpStatuses(ChoicesEnum):
                OK = 200, 'Everything is fine'
                BAD_REQUEST = 400, 'You did a mistake'
                UNAUTHORIZED = 401, 'I know your IP'
                FORBIDDEN = 403
        
                @property
                def is_error(self):
                    return self >= self.BAD_REQUEST
        
            assert HttpStatuses.OK.is_error is False
            assert HttpStatuses.BAD_REQUEST.is_error is True
            assert HttpStatuses.UNAUTHORIZED.is_error is True
        
        Iteration
        ---------
        
        The enum type is iterable:
        
        .. code:: python
        
            >>> for color in Colors:
            ...     print(repr(color))
            Color('#f00').RED
            Color('#0f0').GREEN
            Color('#00f').BLUE
        
        
        Order is guaranteed only for py3.4+. For fixed order in py2.7, you
        can implement a magic attribute ``_order_``:
        
        .. code:: python
        
            from choicesenum import ChoicesEnum
        
            class Colors(ChoicesEnum):
                _order_ = 'RED GREEN BLUE'
        
                RED = '#f00', 'Vermelho'
                GREEN = '#0f0', 'Verde'
                BLUE = '#00f', 'Azul'
        
        Choices
        -------
        
        Use ``.choices()`` method to receive a list of tuples ``(item, display)``:
        
        .. code:: python
        
            assert list(Colors.choices()) == [
                ('#f00', 'Vermelho'),
                ('#0f0', 'Verde'),
                ('#00f', 'Azul'),
            ]
        
        Values
        -------
        
        Use ``.values()`` method to receive a list of the inner values:
        
        .. code:: python
        
            assert Colors.values() == ['#f00', '#0f0', '#00f', ]
        
        Options
        -------
        
        Even if a ``ChoicesEnum`` class is an iterator by itself, you can use ``.options()`` to convert the enum items to a list:
        
        .. code:: python
        
            assert Colors.options() == [Colors.RED, Colors.GREEN, Colors.BLUE]
        
        A "dict like" get
        -----------------
        
        Use ``.get(value, default=None)`` method to receive ``default`` if ``value`` is not an item of enum:
        
        .. code:: python
        
            assert Colors.get(Colors.RED) == Colors.RED
            assert Colors.get('#f00') == Colors.RED
            assert Colors.get('undefined_color') is None
            assert Colors.get('undefined_color', Colors.RED) == Colors.RED
        
        Compatibility
        -------------
        
        The enum item can be used whenever the value is needed:
        
        .. code:: python
        
            assert u'Currrent color is {c} ({c.display})'.format(c=color) ==\
                   u'Currrent color is #f00 (Vermelho)'
        
        Even in dicts and sets, as it shares the same `hash()` from his value:
        
        .. code:: python
        
            d = {
                HttpStatuses.OK.value: "using value",
                HttpStatuses.BAD_REQUEST: "using enum",
                401: "from original value",
            }
            assert d[HttpStatuses.OK] == "using value"
            assert d[HttpStatuses.BAD_REQUEST.value] == "using enum"
            assert d[HttpStatuses.OK] == d[HttpStatuses.OK.value]
            assert d[HttpStatuses.UNAUTHORIZED] == d[401]
        
        There's also optimistic casting of inner types:
        
        .. code:: python
        
            assert int(HttpStatuses.OK) == 200
            assert float(HttpStatuses.OK) == 200.0
            assert str(HttpStatuses.BAD_REQUEST) == "400"
        
        
        Check membership:
        
        .. code:: python
        
            assert HttpStatuses.OK in HttpStatuses
            assert 200 in HttpStatuses
            assert 999 not in HttpStatuses
        
        
        JSON
        ....
        
        If you want json serialization, you have at least two options:
        
        1. Patch the default serializer.
        2. Write a custom JSONEncoder.
        
        ChoicesEnum comes with a handy patch funtion, you need to add this
        code to somewhere at the top of everything to automagically add
        json serialization capabilities:
        
        .. code:: python
        
            from choicesenum.patches import patch_json
            patch_json()
        
        .. note::
        
            Eventually ``__json__`` will be added to the stdlib, see
            https://bugs.python.org/issue27362
        
        
        ------
        Django
        ------
        
        Fields
        ------
        
        Usage with the custom Django fields:
        
        .. code:: python
        
            from django.db import models
            from choicesenum.django.fields import EnumCharField
        
            class ColorModel(models.Model):
                color = EnumCharField(
                    max_length=100,
                    enum=Colors,
                    default=Colors.GREEN,
                )
        
            instance = ColorModel()
            assert instance.color ==  Colors.GREEN
            assert instance.color.is_green is True
            assert instance.color.value == Colors.GREEN.value == '#0f0'
            assert instance.color.display == Colors.GREEN.display
        
            instance.color = '#f00'
            assert instance.color == '#f00'
            assert instance.color.value == '#f00'
            assert instance.color.display == 'Vermelho'
        
        
        Is guaranteed that the field value is *always* a `ChoicesEnum` item. Pay
        attention that the field will only accept valid values for the ``Enum`` in use,
        so if your field allow `null`, your enum should also:
        
        .. code:: python
        
            from django.db import models
            from choicesenum import ChoicesEnum
            from choicesenum.django.fields import EnumIntegerField
        
            class UserStatus(ChoicesEnum):
                UNDEFINED = None
                PENDING = 1
                ACTIVE = 2
                INACTIVE = 3
                DELETED = 4
        
        
            class User(models.Model):
                status = EnumIntegerField(enum=UserStatus, null=True, )
        
            instance = User()
            assert instance.status.is_undefined is True
            assert instance.status.value is None
            assert instance.status == UserStatus.UNDEFINED
            assert instance.status.display == 'Undefined'
        
            # again...
            instance.status = None
            assert instance.status.is_undefined is True
        
        
        --------
        Graphene
        --------
        
        Usage with Graphene_ Enums:
        
        .. _Graphene: http://docs.graphene-python.org/en/latest/types/enums/#usage-with-python-enums
        
        .. code:: python
        
            UserStatusEnum = graphene.Enum.from_enum(UserStatus)
        
        
        ----------
        Schematics
        ----------
        
        Usage with Schematics_ Enums:
        
        .. _Schematics: https://schematics.readthedocs.io/en/latest/usage/types.html
        
        .. code:: python
        
            from schematics.models import Model as SchematicModel
            from schematics.types import StringType, DateTimeType
            from choicesenum import ChoicesEnum
            from choicesenum.schematics.types import ChoicesEnumType
        
            class HttpStatus(ChoicesEnum):
                OK = 200
                BAD_REQUEST = 400
                UNAUTHORIZED = 401
                FORBIDDEN = 403
        
            class CustomSchematicModel(SchematicModel):
                name = StringType(required=True, max_length=255)
                created = DateTimeType(required=True, formats=('%d/%m/%Y', ''))
                http = ChoicesEnumType(HttpStatuses, required=True)
        
        
        -------
        History
        -------
        
        0.7.0 (2020-08-02)
        ------------------
        
        * Add support Django 3.0 (tks @klette).
        * Drop support for Python 3.4.
        * Fix issue when using Django EnumIntegerField on Admin.
        
        
        0.6.0 (2019-09-05)
        ------------------
        
        * Adding schematics contrib type ChoicesEnumType.
        * Drop support for Django 1.6, 1.7, 1.8.
        
        
        0.5.3 (2019-02-06)
        ------------------
        
        * Fix Django migrations with default values for Django 1.7+.
        
        
        0.5.2 (2019-01-18)
        ------------------
        
        * Optimize member check and dynamic creation of `is_<name>` properties.
        
        
        0.5.1 (2019-01-04)
        ------------------
        
        * Fix readme RST (requires new Pypi upload).
        
        
        0.5.0 (2019-01-04)
        ------------------
        
        * Membership test (item in Enum) returning valid results for primitive values.
        * New dict-like `.get` method able to return a default value (thanks @leandrogs).
        * Django: Support Postgres array functions and queries (thanks @tomfa).
        * Django: Support for deferring an enum field using `queryset.defer()` (thanks @noamkush).
        * Django: 2.1 support.
        
        
        0.4.0 (2018-07-13)
        ------------------
        
        * Optimistic casting of inner types (thanks @gabisurita).
        * Optional stdlib patch to automagic json serialization support.
        * Add Python3.7 to the test matrix.
        
        
        0.3.0 (2018-06-22)
        ------------------
        
        * Official Django 2.0 support (0.2.2 just works fine too).
        * ``ChoicesEnum`` sharing the same hash() as his value. Can be used to retrieve/restore items in dicts (`d[enum] == d[enum.value]`).
        
        0.2.2 (2017-12-01)
        ------------------
        
        * Fix: Support queries through `select_related` with no `None` value defined (thanks @klette).
        
        
        0.2.1 (2017-09-30)
        ------------------
        
        * Fix South migrations for Django 1.6.
        
        
        0.2.0 (2017-09-11)
        ------------------
        
        * ``ChoicesEnum`` items are comparable by their values (==, !=, >, >=, <, <=) (thanks @jodal).
        * +``ChoicesEnum.values``: Returns all the Enum's raw values (eq: ``[x.value for x in Enum]``).
        
        0.1.7 (2017-09-10)
        ------------------
        
        * Fix: ``ChoicesEnum`` is now hashable (thanks @jodal).
        
        
        0.1.6 (2017-09-08)
        ------------------
        
        * Fix: Proxy ``__len__`` calls to the inner enum value.
        
        
        0.1.5 (2017-09-05)
        ------------------
        
        * +ChoicesEnum.description: Alias for `label`, allow enum descriptors to be used by Graphene.
        
        
        0.1.4 (2017-08-28)
        ------------------
        
        * Fix South migrations for Django 1.6.
        * ``ChoicesEnum`` repr can be used to reconstruct an instance (``item == eval(repr(item))``).
        
        
        0.1.3 (2017-08-28)
        ------------------
        
        * Fix sdist not including sub-modules (django contrib).
        
        0.1.2 (2017-08-27)
        ------------------
        
        * README fixes and improvements.
        
        0.1.0 (2017-08-27)
        ------------------
        
        * First release on PyPI.
        
Keywords: choicesenum
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
