Metadata-Version: 1.1
Name: nulltype
Version: 2.0.7
Summary: Makes null types parallel to, but different from, None
Home-page: https://bitbucket.org/jeunice/nulltype
Author: Jonathan Eunice
Author-email: jonathan.eunice@gmail.com
License: UNKNOWN
Description: 
        | |version| |downloads| |supported-versions| |supported-implementations|
        
        
        .. |version| image:: http://img.shields.io/pypi/v/nulltype.png?style=flat
            :alt: PyPI Package latest release
            :target: https://pypi.python.org/pypi/nulltype
        
        .. |downloads| image:: http://img.shields.io/pypi/dm/nulltype.png?style=flat
            :alt: PyPI Package monthly downloads
            :target: https://pypi.python.org/pypi/nulltype
        
        .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/nulltype.svg
            :alt: Supported versions
            :target: https://pypi.python.org/pypi/nulltype
        
        .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/nulltype.svg
            :alt: Supported implementations
            :target: https://pypi.python.org/pypi/nulltype
        
        Helps define 'null' types different from, but parallel to, ``None``.
        
        ``None`` is a great `sentinel value <http://en.wikipedia.org/wiki/Sentinel_value>`_
        and a classic implementation of the
        `null object pattern <http://en.wikipedia.org/wiki/Null_Object_pattern>`_.
        
        But there are times that you need more than one nullish value to
        represent different aspects of emptiness. "Nothing there" is
        logically different from "undefined," "prohibited,"
        "end of data" and other kinds of null.
        
        The core function of ``nulltype``
        is representing emptiness and falsity in a way that doesn't overload ``None``
        (or ``False``, ``0``, ``{}``, ``[]``, ``""``, or any of the other possible
        "there's nothing here!" values).
        It helps create designated identifiers with specific meanings
        such as ``Passthrough``, ``Prohibited``, and ``Undefined``.
        
        Usage
        =====
        
        ::
        
            from nulltype import NullType
        
            Empty = NullType('Empty')
        
            # following just to show it's working
            assert bool(Empty) == False
            assert len(Empty) == 0
            assert list(Empty) == []
            assert Empty.some_attribute is Empty
            assert Empty[22] is Nothing
            assert Empty("hey", 12) is Empty
        
        That created a custom ``NullType``. You can create as many
        of them as you like. For your convenience, two default
        values, ``Null`` and ``Nothing``, are exported. That way,
        if you don't really want to create your own, you can
        import a pre-constituted null value, such as::
        
            from nulltype import Nothing
        
        Dereferencing
        =============
        
        Alternate null types can be particularly useful when parsing
        data or traversing data structures which might or might not be
        present. This is common in dealing with the data returned by
        `REST <http://en.wikipedia.org/wiki/Representational_state_transfer>`_
        APIs, for instance.
        
        As one example, `the documentation for Google's Gmail API <https://developers.google.com/gmail/api/quickstart/quickstart-python>`_
        suggests the following code::
        
            threads = gmail_service.users().threads().list(userId='me').execute()
            if threads['threads']:
                for thread in threads['threads']:
                    print 'Thread ID: %s' % (thread['id'])
        
        But there is a lot going on there to avoid a problematic deference.
        If instead you have a ``Nothing`` null type defined, the code is
        shorter (and avoids an extra, very transient variable)::
        
            results = gmail_service.users().threads().list(userId='me').execute()
            for thread in results.get('threads', Nothing):
                print 'Thread ID: %s' % (thread['id'])
        
        Three lines versus four may not seem like a big advantage, but the value
        increases with the complexity of the task. Many such "if it's there, then..."
        constructs are deeply nested when dealing with API results, XML parse trees,
        and other fundamentally nested information sources.
        
        While you could almost do this in stock Python, unlike ``Nothing``, ``None``
        is not iterable--as the error message will quickly inform you if you try.
        (It would be possible to use a null list ``[]`` as the alternative value for
        ``get``, or a global equivalent such as ``EMPTYLIST``. Such uses are not
        broadly idiomatic, however, going by the documentation of many parsers and
        APIs.) The ``EMPTYLIST`` approach also is very specific to routines
        returning lists, whereas the "go ahead, get it if you can" ``nulltype``
        model works well for chains of attribute access as well::
        
            results.get("payload", Nothing).get("headers", Nothing)
        
        will return the correct object if it's there, but ``Nothing`` otherwise.
        And if you then try to test it (e.g. with ``if`` or a logical expression)
        or iterate over it (e.g. with ``for``), it will act as though it's an empty
        list, or ``False``--whatever is most useful in a given context .
        
        ``Nothing`` isn't nothing. It's something that will simplify your code.
        
        General Sentinels and Distinguished Values
        ==========================================
        
        While ``nulltype`` is frequently used to define new kinds of "empty" values,
        it's actually a bit more general. ``NullType`` instances are good
        general-purpose sentinels. You can easily wherever you migth have previously
        used::
        
            class MySentinel(object):
                pass
        
        Instead::
        
            MySentinel = NullType('MySentinel')
        
        Will now give you a value with known truthiness properties and a nicer
        printed representation.
        
        Uniqueness
        ==========
        
        ``NullType`` instances are meant to be
        `singletons <http://en.wikipedia.org/wiki/Singleton_pattern>`_, with just one per
        program. They almost are, though technically multiple ``NullType`` instances are
        reasonable, making it more of a `multiton
        pattern <http://en.wikipedia.org/wiki/Multiton_pattern>`_.
        
        The uniqueness of each singleton is currently not enforced, making it a usage
        convention rather than strict law. With even minimal care, this is a problem
        roughly 0% of the time.
        
        Notes
        =====
        
         * Similar modules include `sentinels <http://pypi.python.org/pypi/sentinels>`_ and `null
           <http://pypi.python.org/pypi/null>`_. Of these, I prefer ``sentinels`` because it
           is clearly Python 3 ready, includes a ``pickle`` mechanism.
        
         * The author, `Jonathan Eunice <mailto:jonathan.eunice@gmail.com>`_ or
           `@jeunice on Twitter <http://twitter.com/jeunice>`_
           welcomes your comments and suggestions.
        
        Recent Changes
        ==============
        
         *  Version 2.0 starts major upgrade from just Boolean operations being nulled
            to essentially all sorts of accesses and updates being nulled. It defines two
            default ``NullType`` instances, ``Null`` and ``Nothing``. The ability
            to have anonymous (unnamed) nulls has been removed as superfluous.
        
         *  Automated multi-version testing managed with the wonderful
            `pytest <http://pypi.python.org/pypi/pytest>`_,
            `pytest-cov <http://pypi.python.org/pypi/pytest>`_,
            and `tox <http://pypi.python.org/pypi/tox>`_.
            Successfully packaged for, and tested against, all late-model versions of
            Python: 2.6, 2.7, 3.2, 3.3, 3.4, as well as PyPy 2.5.1 (based on 2.7.9)
            and PyPy3 2.4.0 (based on 3.2.5).
        
         *  The author, `Jonathan Eunice <mailto:jonathan.eunice@gmail.com>`_ or
            `@jeunice on Twitter <http://twitter.com/jeunice>`_
            welcomes your comments and suggestions.
        
        Installation
        ============
        
        ::
        
            pip install -U nulltype
        
        To ``easy_install`` under a specific Python version (3.3 in this example)::
        
            python3.3 -m easy_install nulltype
        
        (You may need to prefix these with ``sudo`` to authorize installation. In
        environments without super-user privileges, you may want to use ``pip``'s
        ``--user`` option, to install only for a single user, rather than
        system-wide.)
        
Keywords: null none singleton sentinel
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Operating System :: OS Independent
Classifier: License :: OSI Approved :: BSD License
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
