Metadata-Version: 1.1
Name: atpublic
Version: 0.1
Summary: public -- @public for populating __all__
Home-page: https://gitlab.com/warsaw/public
Author: Barry Warsaw
Author-email: barry@python.org
License: Apache 2.0
Description:    =========
            @public
           =========
           
           This is a very simple decorator and function which populates a module's
           ``__all__`` and optionally the module globals.  It is a standalone version of
           the implementation being proposed for Python 3.6 in `issue 26632`_ on the
           Python bug tracker.
           
           This provides both a pure-Python implementation and a C implementation.  It is
           proposed that the C implementation be added to builtins_ for Python 3.6.
           
           
           Background
           ==========
           
           ``__all__`` is great.  It has both a functional and a documentation purpose.
           
           The functional purpose is that it `directly controls`_ which module names are
           imported by the ``from <module> import *`` statement.  In the absence of an
           ``__all__``, when this statement is executed, every name in ``<module>`` that
           does not start with an underscore will be imported.  This often leads to
           importing too many names into the module.
           
           In the presence of an ``__all__``, only the names specified in this list are
           imported by the ``from <module> import *`` statement.  This in essence gives
           the ``<module>`` author a way to explicitly state which names are for public
           consumption.
           
           And that's the second purpose of ``__all__``; it serves as module
           documentation, explicitly naming the public objects it wants to export.  You
           can print a module's ``__all__`` and get an explicit declaration of its public
           API.
           
           
           The problem
           ===========
           
           However, ``__all__`` has two problems.
           
           First, its separates the declaration of a name's public export semantics from
           the implementation of that name.  Usually the ``__all__`` is put at the top of
           the module, although this isn't required, and in some cases it's `actively
           prohibited`_.  So when you're looking at the definition of a function or class
           in a module, you have to search for the ``__all__`` definition to know whether
           the function or class is intended for public consumption.
           
           This leads to the second problem, which is that it's all too easy for the
           ``__all__`` to get `out of sync`_ with the module's contents.  Often a
           function or class is renamed, removed, or added without the ``__all__`` being
           updated.  Then it's difficult to know what the module author's intent was, and
           it can lead to an exception when a string appearing in ``__all__`` doesn't
           match an existing name in the module.
           
           
           The solution
           ============
           
           The solution is to provide a way to declare a name's public-ness right at the
           point of its declaration, and to infer the name to export from that
           definition.  In this way, a module's author never explicitly sets the
           ``__all__`` so there's no way for it to get out of sync.
           
           This package, and issue 26632, propose just such a solution, in the form of a
           ``public`` builtin that can be used as either a decorator, or a callable.
           
           You'll usually use this as a decorator, for example::
           
               @public
               def foo():
                   pass
           
           or::
           
               @public
               class Bar:
                   pass
           
           If you were to print the ``__all__`` after both of those code snippets, you'd
           see::
           
               >>> print(__all__)
               ['foo', 'Bar']
           
           Note that you do not need to initialize ``__all__`` in the module, since
           ``public`` will do it for you.  Of course, if your module *already* has an
           ``__all__``, it will just append new names to the existing list.
           
           The requirements to use the ``@public`` decorator are simple: the decorated
           thing must have a ``__name__`` attribute.  Since you'll overwhelmingly use it
           to decorate functions and classes, this will always be the case.
           
           There's one other common use case that isn't covered by the ``@public``
           decorator.  Sometimes you want to declare simple constants or instances as
           publicly available.  You can't use the ``@public`` decorator for two reasons:
           constants don't have a ``__name__`` and Python's syntax doesn't allow you to
           decorate such constructs.
           
           To solve this use case, ``public`` is also a callable function accepting
           keyword arguments.  An example makes this obvious::
           
               public(SEVEN=7)
               public(a_bar=Bar())
           
           Now if you print the module's ``__all__`` you'll see::
           
               >>> print(__all__)
               ['foo', 'Bar', 'SEVEN', 'a_bar']
           
           and as should be obvious, the module contains name bindings for these
           constants::
           
               >>> print(SEVEN)
               7
               >>> print(a_bar)
               <__main__.Bar object at ...>
           
           **Note:** While you can use ``public()`` with multiple keyword arguments in a
           single call, the order of the resulting ``__all__`` entries is undefined, due
           to indeterminate dictionary sort order.  If order matters to you, call
           ``public()`` multiple times each with a single keyword argument.
           
           
           Usage
           =====
           
           To use this, just import it::
           
               >>> from public import public
           
           This package actually provides both a pure Python implementation and a C
           implementation.  It is expected/hoped that the C implementation might appear
           in Python 3.6.  By default, the import above provides you with the more
           efficient C implementation.  If for some reason you want the pure-Python
           implementation just do::
           
               >>> from public import py_public as public
           
           Having to do this import in every module you want to use it can get pretty
           tedious, so what if you could put ``public`` into Python's builtins?  Then it
           would be available in all your code for free::
           
               >>> from public import install
               >>> install()
           
           and now you can just use ``@public`` without having to import anything in your
           other modules.
           
           By default, this installs the C implementation but if you wanted to install
           the pure-Python version, just do::
           
               >>> from public import py_install
               >>> py_install
           
           
           Alternatives
           ============
           
           This isn't a unique approach to ``@public``.  Other_ implementations_ do
           exist.  There are some subtle differences between this package and those
           others.  This package:
           
           * uses keyword arguments to map names which don't have an ``__name__``
             attribute;
           * can be used to bind names and values into a module's globals;
           * provides both C and Python implementations;
           * can optionally put ``public`` in builtins.
           
           
           Author
           ======
           
           `public` is Copyright (C) 2016 Barry Warsaw
           
           Contact Barry:
           
           * barry@python.org
           * @pumpichank on Twitter
           * @warsaw on GitHub and GitLab
           
           Licensed under the terms of the Apache License 2.0.  See LICENSE.txt for
           details.
           
           
           Project details
           ===============
           
           * Project home: https://gitlab.com/warsaw/public
           * Report bugs at: https://gitlab.com/warsaw/public/issues
           * Fork the code: https://gitlab.com/warsaw/public.git
           * Documentation: http://public.readthedocs.io/en/latest/
           * PyPI: https://pypi.python.org/pypi/atpublic
           
           
           .. _`issue 26632`: http://bugs.python.org/issue26632
           .. _builtins: https://docs.python.org/3/library/builtins.html
           .. _`directly controls`: https://docs.python.org/3/tutorial/modules.html#importing-from-a-package
           .. _`actively prohibited`: http://pep8.readthedocs.io/en/latest/intro.html?highlight=e402#error-codes
           .. _`out of sync`: http://bugs.python.org/issue23883
           .. _Other: https://pypi.python.org/pypi/public
           .. _implementations: http://bugs.python.org/issue22247#msg225637
        
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
