[Python-modules-commits] [python-attrs] 02/11: Import python-attrs_16.2.0.orig.tar.gz

Tristan Seligmann mithrandi at moszumanska.debian.org
Mon Oct 10 02:57:48 UTC 2016


This is an automated email from the git hooks/post-receive script.

mithrandi pushed a commit to branch master
in repository python-attrs.

commit 02ab5d9c3a881e4198d291bc7b69b58616faf533
Author: Tristan Seligmann <mithrandi at mithrandi.net>
Date:   Mon Oct 10 01:08:21 2016 +0200

    Import python-attrs_16.2.0.orig.tar.gz
---
 .coveragerc                     |   3 +-
 .gitignore                      |   1 +
 CHANGELOG.rst                   |  71 ++++-
 CODE_OF_CONDUCT.rst             |   4 +-
 CONTRIBUTING.rst                |  10 +-
 README.rst                      |  67 ++++-
 conftest.py                     |   2 +
 docs/api.rst                    |  46 +++-
 docs/backward-compatibility.rst |  10 +-
 docs/conf.py                    |  10 +-
 docs/examples.rst               | 118 ++++++---
 docs/extending.rst              |   4 +-
 docs/how-does-it-work.rst       |  76 ++++++
 docs/index.rst                  |  27 +-
 docs/overview.rst               |  79 ++++++
 docs/why.rst                    |  31 ++-
 setup.cfg                       |   4 +-
 src/attr/__init__.py            |  15 +-
 src/attr/_compat.py             |   7 -
 src/attr/_funcs.py              | 149 ++++++++---
 src/attr/_make.py               | 561 ++++++++++++++++++++++++++--------------
 src/attr/exceptions.py          |  30 +++
 src/attr/filters.py             |   8 +-
 src/attr/validators.py          |   8 +-
 tests/__init__.py               |  77 ------
 tests/test_dark_magic.py        |  61 ++++-
 tests/test_dunders.py           |  29 ++-
 tests/test_filters.py           |  26 +-
 tests/test_funcs.py             | 253 ++++++++++++++++--
 tests/test_make.py              | 103 +++++---
 tests/test_validators.py        |   3 +-
 tests/utils.py                  | 176 +++++++++++++
 tox.ini                         |  18 +-
 33 files changed, 1578 insertions(+), 509 deletions(-)

diff --git a/.coveragerc b/.coveragerc
index d17a6aa..093c119 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,6 +1,7 @@
 [run]
 branch = True
-source = attr
+source =
+    attr
 
 [paths]
 source =
diff --git a/.gitignore b/.gitignore
index 321aae5..a4ca3f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ docs/_build/
 htmlcov
 dist
 .cache
+.hypothesis
\ No newline at end of file
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ebccfda..0d6118b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -5,6 +5,75 @@ Versions are year-based with a strict backwards compatibility policy.
 The third digit is only for regressions.
 
 
+16.2.0 (2016-09-17)
+-------------------
+
+Changes:
+^^^^^^^^
+
+- Add ``attr.astuple()`` that -- similarly to ``attr.asdict()`` -- returns the instance as a tuple.
+  `#77 <https://github.com/hynek/attrs/issues/77>`_
+- Converts now work with frozen classes.
+  `#76 <https://github.com/hynek/attrs/issues/76>`_
+- Instantiation of ``attrs`` classes with converters is now significantly faster.
+  `#80 <https://github.com/hynek/attrs/pull/80>`_
+- Pickling now works with ``__slots__`` classes.
+  `#81 <https://github.com/hynek/attrs/issues/81>`_
+- ``attr.assoc()`` now works with ``__slots__`` classes.
+  `#84 <https://github.com/hynek/attrs/issues/84>`_
+- The tuple returned by ``attr.fields()`` now also allows to access the ``Attribute`` instances by name.
+  Yes, we've subclassed ``tuple`` so you don't have to!
+  Therefore ``attr.fields(C).x`` is equivalent to the deprecated ``C.x`` and works with ``__slots__`` classes.
+  `#88 <https://github.com/hynek/attrs/issues/88>`_
+
+
+----
+
+
+16.1.0 (2016-08-30)
+-------------------
+
+Backward-incompatible changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- All instances where function arguments were called ``cl`` have been changed to the more Pythonic ``cls``.
+  Since it was always the first argument, it's doubtful anyone ever called those function with in the keyword form.
+  If so, sorry for any breakage but there's no practical deprecation path to solve this ugly wart.
+
+
+Deprecations:
+^^^^^^^^^^^^^
+
+- Accessing ``Attribute`` instances on class objects is now deprecated and will stop working in 2017.
+  If you need introspection please use the ``__attrs_attrs__`` attribute or the ``attr.fields()`` function that carry them too.
+  In the future, the attributes that are defined on the class body and are usually overwritten in your ``__init__`` method are simply removed after ``@attr.s`` has been applied.
+
+  This will remove the confusing error message if you write your own ``__init__`` and forget to initialize some attribute.
+  Instead you will get a straightforward ``AttributeError``.
+  In other words: decorated classes will work more like plain Python classes which was always ``attrs``'s goal.
+- The serious business aliases ``attr.attributes`` and ``attr.attr`` have been deprecated in favor of ``attr.attrs`` and ``attr.attrib`` which are much more consistent and frankly obvious in hindsight.
+  They will be purged from documentation immediately but there are no plans to actually remove them.
+
+
+Changes:
+^^^^^^^^
+
+- ``attr.asdict()``\ 's ``dict_factory`` arguments is now propagated on recursion.
+  `#45 <https://github.com/hynek/attrs/issues/45>`_
+- ``attr.asdict()``, ``attr.has()`` and ``attr.fields()`` are significantly faster.
+  `#48 <https://github.com/hynek/attrs/issues/48>`_
+  `#51 <https://github.com/hynek/attrs/issues/51>`_
+- Add ``attr.attrs`` and ``attr.attrib`` as a more consistent aliases for ``attr.s`` and ``attr.ib``.
+- Add ``frozen`` option to ``attr.s`` that will make instances best-effort immutable.
+  `#60 <https://github.com/hynek/attrs/issues/60>`_
+- ``attr.asdict()`` now takes ``retain_collection_types`` as an argument.
+  If ``True``, it does not convert attributes of type ``tuple`` or ``set`` to ``list``.
+  `#69 <https://github.com/hynek/attrs/issues/69>`_
+
+
+----
+
+
 16.0.0 (2016-05-23)
 -------------------
 
@@ -28,7 +97,7 @@ Changes:
 - Allow the case of initializing attributes that are set to ``init=False``.
   This allows for clean initializer parameter lists while being able to initialize attributes to default values.
   `#32 <https://github.com/hynek/attrs/issues/32>`_
-- ``attr.asdict`` can now produce arbitrary mappings instead of Python ``dict``\ s when provided with a ``dict_factory`` argument.
+- ``attr.asdict()`` can now produce arbitrary mappings instead of Python ``dict``\ s when provided with a ``dict_factory`` argument.
   `#40 <https://github.com/hynek/attrs/issues/40>`_
 - Multiple performance improvements.
 
diff --git a/CODE_OF_CONDUCT.rst b/CODE_OF_CONDUCT.rst
index fa8b5bb..4f4b8ee 100644
--- a/CODE_OF_CONDUCT.rst
+++ b/CODE_OF_CONDUCT.rst
@@ -4,7 +4,7 @@ Contributor Covenant Code of Conduct
 Our Pledge
 ----------
 
-In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
 
 Our Standards
 -------------
@@ -43,7 +43,7 @@ Enforcement
 -----------
 
 Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hs at ox.cx.
-all complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
+All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
 The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
 Further details of specific enforcement policies may be posted separately.
 
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index f24cd9e..d1cc9a5 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,18 +1,18 @@
 How To Contribute
 =================
 
-Every open source project lives from the generous help by contributors that sacrifice their time and ``attrs`` is no different.
+Every open source project lives due to generous help by contributors sacrificing their time; ``attrs`` is no different.
 
 Here are a few guidelines to get you started:
 
 - Try to limit each pull request to one change only.
 - To run the test suite, all you need is a recent tox_.
   It will ensure the test suite runs with all dependencies against all Python versions just as it will on `Travis CI`_.
-  If you lack some Python version, you can can always limit the environments like ``tox -e py27,py35`` (in that case you may want to look into pyenv_ that makes it very easy to install many different Python versions in parallel).
+  If you lack some Python versions, you can can always limit the environments like ``tox -e py27,py35`` (in that case you may want to look into pyenv_, which makes it very easy to install many different Python versions in parallel).
 - Make sure your changes pass our CI.
   You won't get any feedback until it's green unless you ask for it.
 - If your change is noteworthy, add an entry to the changelog_.
-  Use present tense, semantic newlines, and add link to your pull request.
+  Use present tense, semantic newlines, and add a link to your pull request.
 - No contribution is too small; please submit as many fixes for typos and grammar bloopers as you can!
 - Don’t break `backward compatibility`_.
 - *Always* add tests and docs for your code.
@@ -20,13 +20,13 @@ Here are a few guidelines to get you started:
 - Write `good test docstrings`_.
 - Obey `PEP 8`_ and `PEP 257`_.
 - If you address review feedback, make sure to bump the pull request.
-  Maintainers don’t receive notifications if you push new commits.
+  Maintainers don’t receive notifications when you push new commits.
 
 Please note that this project is released with a Contributor `Code of Conduct`_.
 By participating in this project you agree to abide by its terms.
 Please report any harm to `Hynek Schlawack`_ in any way you find appropriate.
 
-Thank you for considering to contribute to ``attrs``!
+Thank you for considering contributing to ``attrs``!
 
 
 .. _`Hynek Schlawack`: https://hynek.me/about/
diff --git a/README.rst b/README.rst
index 8abc731..0a5d03a 100644
--- a/README.rst
+++ b/README.rst
@@ -1,22 +1,30 @@
-======================================
-attrs: Attributes without boilerplate.
-======================================
+=====================================
+attrs: Attributes Without Boilerplate
+=====================================
 
 .. image:: https://readthedocs.org/projects/attrs/badge/?version=stable
    :target: http://attrs.readthedocs.io/en/stable/?badge=stable
    :alt: Documentation Status
 
-.. image:: https://travis-ci.org/hynek/attrs.svg
+.. image:: https://travis-ci.org/hynek/attrs.svg?branch=master
    :target: https://travis-ci.org/hynek/attrs
    :alt: CI status
 
-.. image:: https://codecov.io/github/hynek/attrs/coverage.svg?branch=master
-   :target: https://codecov.io/github/hynek/attrs?branch=master
-   :alt: Coverage
+.. image:: https://codecov.io/github/hynek/attrs/branch/master/graph/badge.svg
+  :target: https://codecov.io/github/hynek/attrs
+  :alt: Test Coverage
 
 .. teaser-begin
 
-``attrs`` is an `MIT <http://choosealicense.com/licenses/mit/>`_-licensed Python package with class decorators that ease the chores of implementing the most common attribute-related object protocols:
+``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder <http://nedbatchelder.com/blog/200605/dunder.html>`_ methods).
+
+Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
+
+.. -spiel-end-
+
+For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
+
+.. -code-begin-
 
 .. code-block:: pycon
 
@@ -25,9 +33,14 @@ attrs: Attributes without boilerplate.
    ... class C(object):
    ...     x = attr.ib(default=42)
    ...     y = attr.ib(default=attr.Factory(list))
+   ...
+   ...     def hard_math(self, z):
+   ...         return self.x * self.y * z
    >>> i = C(x=1, y=2)
    >>> i
    C(x=1, y=2)
+   >>> i.hard_math(3)
+   6
    >>> i == C(1, 2)
    True
    >>> i != C(2, 1)
@@ -40,20 +53,46 @@ attrs: Attributes without boilerplate.
    >>> C2("foo", "bar")
    C2(a='foo', b='bar')
 
-(If you don’t like the playful ``attr.s`` and ``attr.ib``, you can also use their no-nonsense aliases ``attr.attributes`` and ``attr.attr``).
 
-You just specify the attributes to work with and ``attrs`` gives you:
+After *declaring* your attributes ``attrs`` gives you:
 
+- a concise and explicit overview of the class's attributes,
 - a nice human-readable ``__repr__``,
 - a complete set of comparison methods,
 - an initializer,
-- and much more
+- and much more,
 
-*without* writing dull boilerplate code again and again.
+*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
 
 This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or confusingly behaving ``namedtuple``\ s.
+Which in turn encourages you to write *small classes* that do `one thing well <https://www.destroyallsoftware.com/talks/boundaries>`_.
+Never again violate the `single responsibility principle <https://en.wikipedia.org/wiki/Single_responsibility_principle>`_ just because implementing ``__init__`` et al is a painful drag.
+
+
+.. -testimonials-
+
+Testimonials
+============
+
+  I’m looking forward to is being able to program in Python-with-attrs everywhere.
+  It exerts a subtle, but positive, design influence in all the codebases I’ve see it used in.
+
+  -- Glyph Lefkowitz, inventor of Twisted and Software Developer at Rackspace in `The One Python Library Everyone Needs <https://glyph.twistedmatrix.com/2016/08/attrs.html>`_
+
+
+  I'm increasingly digging your attr.ocity. Good job!
+
+  -- Łukasz Langa, prolific CPython core developer and Production Engineer at Facebook
+
+.. -end-
+
+.. -project-information-
 
-So put down that type-less data structures and welcome some class into your life!
+Project Information
+===================
 
-``attrs``\ ’s documentation lives at `Read the Docs <https://attrs.readthedocs.io/>`_, the code on `GitHub <https://github.com/hynek/attrs>`_.
+``attrs`` is released under the `MIT <http://choosealicense.com/licenses/mit/>`_ license,
+its documentation lives at `Read the Docs <https://attrs.readthedocs.io/>`_,
+the code on `GitHub <https://github.com/hynek/attrs>`_,
+and the latest release on `PyPI <https://pypi.org/project/attrs/>`_.
 It’s rigorously tested on Python 2.7, 3.4+, and PyPy.
diff --git a/conftest.py b/conftest.py
index 2fd79e9..93609c6 100644
--- a/conftest.py
+++ b/conftest.py
@@ -1,7 +1,9 @@
 from __future__ import absolute_import, division, print_function
 
+import os
 
 import pytest
+from hypothesis import settings
 
 
 @pytest.fixture(scope="session")
diff --git a/docs/api.rst b/docs/api.rst
index 3c682d1..8a1edda 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -18,11 +18,11 @@ What follows is the API explanation, if you'd like a more hands-on introduction,
 Core
 ----
 
-.. autofunction:: attr.s(these=None, repr_ns=None, repr=True, cmp=True, hash=True, init=True, slots=False)
+.. autofunction:: attr.s(these=None, repr_ns=None, repr=True, cmp=True, hash=True, init=True, slots=False, frozen=False)
 
    .. note::
 
-      ``attrs`` also comes with a less playful alias ``attr.attributes``.
+      ``attrs`` also comes with a serious business alias ``attr.attrs``.
 
    For example:
 
@@ -48,14 +48,13 @@ Core
 
    .. note::
 
-      ``attrs`` also comes with a less playful alias ``attr.attr``.
+      ``attrs`` also comes with a serious business alias ``attr.attrib``.
 
 
 .. autoclass:: attr.Attribute
 
    Instances of this class are frequently used for introspection purposes like:
 
-   - Class attributes on ``attrs``-decorated classes *after* ``@attr.s`` has been applied.
    - :func:`fields` returns a tuple of them.
    - Validators get them passed as the first argument.
 
@@ -103,10 +102,17 @@ Core
       C(x=[])
 
 
+.. autoexception:: attr.exceptions.FrozenInstanceError
+.. autoexception:: attr.exceptions.AttrsAttributeNotFoundError
+.. autoexception:: attr.exceptions.NotAnAttrsClassError
+
+
+.. _helpers:
+
 Helpers
 -------
 
-``attrs`` comes with a bunch of helper methods that make the work with it easier:
+``attrs`` comes with a bunch of helper methods that make working with it easier:
 
 .. autofunction:: attr.fields
 
@@ -120,6 +126,10 @@ Helpers
       ...     y = attr.ib()
       >>> attr.fields(C)
       (Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None), Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None))
+      >>> attr.fields(C)[1]
+      Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None)
+      >>> attr.fields(C).y is attr.fields(C)[1]
+      True
 
 
 .. autofunction:: attr.has
@@ -151,12 +161,26 @@ Helpers
       {'y': {'y': 3, 'x': 2}, 'x': 1}
 
 
-``attrs`` comes with some handy helpers for filtering:
+.. autofunction:: attr.astuple
+
+   For example:
+
+   .. doctest::
+
+      >>> @attr.s
+      ... class C(object):
+      ...     x = attr.ib()
+      ...     y = attr.ib()
+      >>> attr.astuple(C(1,2))
+      (1, 2)
+
+``attrs`` includes some handy helpers for filtering:
 
 .. autofunction:: attr.filters.include
 
 .. autofunction:: attr.filters.exclude
 
+See :ref:`asdict` for examples.
 
 .. autofunction:: assoc
 
@@ -177,7 +201,6 @@ Helpers
       >>> i1 == i2
       False
 
-
 .. autofunction:: validate
 
    For example:
@@ -207,7 +230,7 @@ Validators can be globally disabled if you want to run them only in development
 Validators
 ----------
 
-``attrs`` comes with some common validators within the ``attrs.validators`` module:
+``attrs`` comes with some common validators in the ``attrs.validators`` module:
 
 
 .. autofunction:: attr.validators.instance_of
@@ -251,3 +274,10 @@ Validators
       TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>), <type 'int'>, '42')
       >>> C(None)
       C(x=None)
+
+
+Deprecated APIs
+---------------
+
+The serious business aliases used to be called ``attr.attributes`` and ``attr.attr``.
+There are no plans to remove them but they shouldn't be used in new code.
diff --git a/docs/backward-compatibility.rst b/docs/backward-compatibility.rst
index e8fff8f..52559f8 100644
--- a/docs/backward-compatibility.rst
+++ b/docs/backward-compatibility.rst
@@ -3,17 +3,17 @@ Backward Compatibility
 
 .. currentmodule:: attr
 
-``attrs`` has a very strong backward compatibility policy that is inspired by the one of the `Twisted framework <https://twistedmatrix.com/trac/wiki/CompatibilityPolicy>`_.
+``attrs`` has a very strong backward compatibility policy that is inspired by the policy of the `Twisted framework <https://twistedmatrix.com/trac/wiki/CompatibilityPolicy>`_.
 
-Put simply, you shouldn't ever be afraid to upgrade ``attrs`` if you're using its public APIs.
-If there will ever be need to break compatibility, it will be announced in the :doc:`changelog`, raise deprecation warning for a year before it's finally really broken.
+Put simply, you shouldn't ever be afraid to upgrade ``attrs`` if you're only using its public APIs.
+If there will ever be a need to break compatibility, it will be announced in the :doc:`changelog` and raise a ``DeprecationWarning`` for a year (if possible) before it's finally really broken.
 
 
 .. _exemption:
 
 .. warning::
 
-   The structure of the :class:`attr.Attribute` class is exempted from this rule.
-   It *will* change in the future since it should be considered read-only, that shouldn't matter.
+   The structure of the :class:`attr.Attribute` class is exempt from this rule.
+   It *will* change in the future, but since it should be considered read-only, that shouldn't matter.
 
    However if you intend to build extensions on top of ``attrs`` you have to anticipate that.
diff --git a/docs/conf.py b/docs/conf.py
index cacf3c2..dbfdf36 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,7 +13,6 @@
 # serve to show the default.
 
 import codecs
-import datetime
 import os
 import re
 
@@ -80,10 +79,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'attrs'
-year = datetime.date.today().year
-copyright = u'2015{0}, Hynek Schlawack'.format(
-    u'-{0}'.format(year) if year != 2015 else u""
-)
+copyright = u'2015, Hynek Schlawack'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -303,4 +299,6 @@ texinfo_documents = [
 
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/2': None}
+intersphinx_mapping = {
+    "https://docs.python.org/3": None,
+}
diff --git a/docs/examples.rst b/docs/examples.rst
index 6ab21c9..23e0ff5 100644
--- a/docs/examples.rst
+++ b/docs/examples.rst
@@ -22,7 +22,7 @@ The simplest possible usage would be:
    >>> Empty() is Empty()
    False
 
-So in other words: ``attrs`` useful even without actual attributes!
+So in other words: ``attrs`` is useful even without actual attributes!
 
 But you'll usually want some data on your classes, so let's add some:
 
@@ -33,7 +33,7 @@ But you'll usually want some data on your classes, so let's add some:
    ...     x = attr.ib()
    ...     y = attr.ib()
 
-These by default, all features are added, so you have immediately a fully functional data class with a nice ``repr`` string and comparison methods.
+By default, all features are added, so you immediately have a fully functional data class with a nice ``repr`` string and comparison methods.
 
 .. doctest::
 
@@ -46,16 +46,17 @@ These by default, all features are added, so you have immediately a fully functi
    >>> c1 == c2
    False
 
-As shown, the generated ``__init__`` method allows both for positional and keyword arguments.
+As shown, the generated ``__init__`` method allows for both positional and keyword arguments.
 
-If playful naming turns you off, ``attrs`` comes with no-nonsense aliases:
+If playful naming turns you off, ``attrs`` comes with serious business aliases:
 
 .. doctest::
 
-   >>> @attr.attributes
+   >>> from attr import attrs, attrib
+   >>> @attrs
    ... class SeriousCoordinates(object):
-   ...     x = attr.attr()
-   ...     y = attr.attr()
+   ...     x = attrib()
+   ...     y = attrib()
    >>> SeriousCoordinates(1, 2)
    SeriousCoordinates(x=1, y=2)
    >>> attr.fields(Coordinates) == attr.fields(SeriousCoordinates)
@@ -116,7 +117,7 @@ Or if you want to use properties:
       ...
    AttributeError: can't set attribute
 
-`Sub-classing <https://www.youtube.com/watch?v=3MNVP9-hglc>`_ is bad for you, but ``attrs`` will still do what you'd hope for:
+`Subclassing <https://www.youtube.com/watch?v=3MNVP9-hglc>`_ is bad for you, but ``attrs`` will still do what you'd hope for:
 
 .. doctest::
 
@@ -156,11 +157,13 @@ Therefore ``@attr.s`` comes with the ``repr_ns`` option to set it manually:
    C.D()
 
 ``repr_ns`` works on both Python 2 and 3.
-On Python 3 is overrides the implicit detection.
+On Python 3 it overrides the implicit detection.
 
 
-Converting to Dictionaries
---------------------------
+.. _asdict:
+
+Converting to Collections Types
+-------------------------------
 
 When you have a class with data, it often is very convenient to transform that class into a :class:`dict` (for example if you want to serialize it to JSON):
 
@@ -195,16 +198,41 @@ For the common case where you want to :func:`include <attr.filters.include>` or
    ...     login = attr.ib()
    ...     password = attr.ib()
    ...     id = attr.ib()
-   >>> attr.asdict(User("jane", "s33kred", 42), filter=attr.filters.exclude(User.password, int))
+   >>> attr.asdict(User("jane", "s33kred", 42),
+   ...                  filter=attr.filters.exclude(attr.fields(User).password, int))
    {'login': 'jane'}
    >>> @attr.s
    ... class C(object):
    ...     x = attr.ib()
    ...     y = attr.ib()
    ...     z = attr.ib()
-   >>> attr.asdict(C("foo", "2", 3), filter=attr.filters.include(int, C.x))
+   >>> attr.asdict(C("foo", "2", 3),
+   ...             filter=attr.filters.include(int, attr.fields(C).x))
    {'z': 3, 'x': 'foo'}
 
+Other times, all you want is a tuple and ``attrs`` won't let you down:
+
+.. doctest::
+
+   >>> import sqlite3
+   >>> import attr
+   >>> @attr.s
+   ... class Foo:
+   ...    a = attr.ib()
+   ...    b = attr.ib()
+   >>> foo = Foo(2, 3)
+   >>> with sqlite3.connect(":memory:") as conn:
+   ...    c = conn.cursor()
+   ...    c.execute("CREATE TABLE foo (x INTEGER PRIMARY KEY ASC, y)") #doctest: +ELLIPSIS
+   ...    c.execute("INSERT INTO foo VALUES (?, ?)", attr.astuple(foo)) #doctest: +ELLIPSIS
+   ...    foo2 = Foo(*c.execute("SELECT x, y FROM foo").fetchone())
+   <sqlite3.Cursor object at ...>
+   <sqlite3.Cursor object at ...>
+   >>> foo == foo2
+   True
+
+
+
 
 Defaults
 --------
@@ -220,9 +248,9 @@ And sometimes you even want mutable objects as default values (ever used acciden
    ... class Connection(object):
    ...     socket = attr.ib()
    ...     @classmethod
-   ...     def connect(cl, db_string):
-   ...        # connect somehow to db_string
-   ...        return cl(socket=42)
+   ...     def connect(cls, db_string):
+   ...        # ... connect somehow to db_string ...
+   ...        return cls(socket=42)
    >>> @attr.s
    ... class ConnectionPool(object):
    ...     db_string = attr.ib()
@@ -256,13 +284,13 @@ More information on why class methods for constructing objects are awesome can b
 Validators
 ----------
 
-Although your initializers should be as dumb as possible, it can come handy to do some kind of validation on the arguments.
+Although your initializers should be as dumb as possible, it can come in handy to do some kind of validation on the arguments.
 That's when :func:`attr.ib`\ ’s ``validator`` argument comes into play.
 A validator is simply a callable that takes three arguments:
 
-#. The *instance* that's being validated.
-#. The *attribute* that it's validating
-#. and finally the *value* that is passed for it.
+#. the *instance* that's being validated,
+#. the *attribute* that it's validating, and finally
+#. the *value* that is passed for it.
 
 If the value does not pass the validator's standards, it just raises an appropriate exception.
 Since the validator runs *after* the instance is initialized, you can refer to other attributes while validating :
@@ -283,7 +311,7 @@ Since the validator runs *after* the instance is initialized, you can refer to o
       ...
    ValueError: 'x' has to be smaller than 'y'!
 
-``attrs`` won't intercept your changes to those attributes but you can always call :func:`attr.validate` on any instance to verify, that it's still valid:
+``attrs`` won't intercept your changes to those attributes but you can always call :func:`attr.validate` on any instance to verify that it's still valid:
 
 .. doctest::
 
@@ -308,7 +336,7 @@ Since the validator runs *after* the instance is initialized, you can refer to o
       ...
    TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>), <type 'int'>, '42')
 
-If you like `zope.interface <http://docs.zope.org/zope.interface/api.html#zope-interface-interface-specification>`_, ``attrs`` also comes with a :func:`attr.validators.provides` validator:
+If you like `zope.interface <https://zopeinterface.readthedocs.io/en/latest/api.html#zope-interface-interface-specification>`_, ``attrs`` also comes with a :func:`attr.validators.provides` validator:
 
 .. doctest::
 
@@ -383,7 +411,7 @@ Slots
 -----
 
 By default, instances of classes have a dictionary for attribute storage.
-This wastes space for objects having very few instance variables.
+This wastes space for objects having very few data attributes.
 The space consumption can become significant when creating large numbers of instances.
 
 Normal Python classes can avoid using a separate dictionary for each instance of a class by `defining <https://docs.python.org/3.5/reference/datamodel.html#slots>`_ ``__slots__``.
@@ -440,19 +468,45 @@ Slot classes are a little different than ordinary, dictionary-backed classes:
 - Since non-slot classes cannot be turned into slot classes after they have been created, ``attr.s(.., slots=True)`` will *replace* the class it is applied to with a copy.
   In almost all cases this isn't a problem, but we mention it for the sake of completeness.
 
+- Using :mod:`pickle` with slot classes requires pickle protocol 2 or greater.
+  Python 2 uses protocol 0 by default so the protocol needs to be specified.
+  Python 3 uses protocol 3 by default.
+  You can support protocol 0 and 1 by implementing :meth:`__getstate__ <object.__getstate__>` and :meth:`__setstate__ <object.__setstate__>` methods yourself.
+  Those methods are created for frozen slot classes because they won't pickle otherwise.
+  `Think twice <https://www.youtube.com/watch?v=7KnfGDajDQw>`_ before using :mod:`pickle` though.
+
 All in all, setting ``slots=True`` is usually a very good idea.
 
 
-Other Goodies
--------------
+Immutability
+------------
 
-Do you like Rich Hickey?
-I'm glad to report that Clojure's core feature is part of ``attrs``: `assoc <https://clojuredocs.org/clojure.core/assoc>`_!
-I guess that means Clojure can be shut down now, sorry Rich!
+Sometimes you have instances that shouldn't be changed after instantiation.
+Immutability is especially popular in functional programming and is generally a very good thing.
+If you'd like to enforce it, ``attrs`` will try to help:
 
 .. doctest::
 
-   >>> @attr.s
+   >>> @attr.s(frozen=True)
+   ... class C(object):
+   ...     x = attr.ib()
+   >>> i = C(1)
+   >>> i.x = 2
+   Traceback (most recent call last):
+      ...
+   attr.exceptions.FrozenInstanceError: can't set attribute
+   >>> i.x
+   1
+
+Please note that true immutability is impossible in Python but it will :ref:`get <how-frozen>` you 99% there.
+By themselves, immutable classes are useful for long-lived objects that should never change; like configurations for example.
+
+In order to use them in regular program flow, you'll need a way to easily create new instances with changed attributes.
+In Clojure that function is called `assoc <https://clojuredocs.org/clojure.core/assoc>`_ and ``attrs`` shamelessly imitates it: :func:`attr.assoc`:
+
+.. doctest::
+
+   >>> @attr.s(frozen=True)
    ... class C(object):
    ...     x = attr.ib()
    ...     y = attr.ib()
@@ -465,8 +519,12 @@ I guess that means Clojure can be shut down now, sorry Rich!
    >>> i1 == i2
    False
 
+
+Other Goodies
+-------------
+
 Sometimes you may want to create a class programmatically.
-``attrs`` won't let you down:
+``attrs`` won't let you down and gives you :func:`attr.make_class` :
 
 .. doctest::
 
diff --git a/docs/extending.rst b/docs/extending.rst
index 5394371..9a40a41 100644
--- a/docs/extending.rst
+++ b/docs/extending.rst
@@ -11,8 +11,8 @@ So it is fairly simple to build your own decorators on top of ``attrs``:
 .. doctest::
 
    >>> import attr
-   >>> def print_attrs(cl):
-   ...     print(cl.__attrs_attrs__)
+   >>> def print_attrs(cls):
+   ...     print(cls.__attrs_attrs__)
    >>> @print_attrs
    ... @attr.s
    ... class C(object):
diff --git a/docs/how-does-it-work.rst b/docs/how-does-it-work.rst
new file mode 100644
index 0000000..ee23818
--- /dev/null
+++ b/docs/how-does-it-work.rst
@@ -0,0 +1,76 @@
+.. _how:
+
+How Does It Work?
+=================
+
+
+Boilerplate
+-----------
+
+``attrs`` certainly isn't the first library that aims to simplify class definition in Python.
+But its **declarative** approach combined with **no runtime overhead** lets it stand out.
+
+Once you apply the ``@attr.s`` decorator to a class, ``attrs`` searches the class object for instances of ``attr.ib``\ s.
+Internally they're a representation of the data passed into ``attr.ib`` along with a counter to preserve the order of the attributes.
+
+In order to ensure that sub-classing works as you'd expect it to work, ``attrs`` also walks the class hierarchy and collects the attributes of all super-classes.
+Please note that ``attrs`` does *not* call ``super()`` *ever*.
+It will write dunder methods to work on *all* of those attributes which also has performance benefits due to less function calls.
+
+Once ``attrs`` knows what attributes it has to work on, it writes the requested dunder methods and attaches them to your class.
+To be very clear: if you define a class with a single attribute  without a default value, the generated ``__init__`` will look *exactly* how you'd expect:
+
+.. doctest::
+
+   >>> import attr, inspect
+   >>> @attr.s
+   ... class C:
+   ...     x = attr.ib()
+   >>> print(inspect.getsource(C.__init__))
+   def __init__(self, x):
+       self.x = x
+   <BLANKLINE>
+
+No magic, no meta programming, no expensive introspection at runtime.
+
+****
+
+Everything until this point happens exactly *once* when the class is defined.
+As soon as a class is done, it's done.
+And it's just a regular Python class like any other, except for a single ``__attrs_attrs__`` attribute that can be used for introspection or for writing your own tools and decorators on top of ``attrs`` (like :func:`attr.asdict`).
+
+And once you start instantiating your classes, ``attrs`` is out of your way completely.
+
+This **static** approach was very much a design goal of ``attrs`` and what I strongly believe makes it distinct.
+
+
+.. _how-frozen:
+
+Immutability
+------------
+
+In order to give you immutability, ``attrs`` will attach a ``__setattr__`` method to your class that raises a :exc:`attr.exceptions.FrozenInstanceError` whenever anyone tries to set an attribute.
+
+In order to circumvent that ourselves in ``__init__``, ``attrs`` uses (an agressively cached) :meth:`object.__setattr__` to set your attributes.  This is (still) slower than a plain assignment:
+
+.. code-block:: none
+
+  $ pyperf timeit --rigorous \
+        -s "import attr; C = attr.make_class('C', ['x', 'y', 'z'], slots=True)" \
+        "C(1, 2, 3)"
+  ........................................
+  Median +- std dev: 378 ns +- 12 ns
+
+  $ pyperf timeit --rigorous \
+        -s "import attr; C = attr.make_class('C', ['x', 'y', 'z'], slots=True, frozen=True)" \
+        "C(1, 2, 3)"
+  ........................................
+  Median +- std dev: 676 ns +- 16 ns
+
+So on my notebook the difference is about 300 nanoseconds (1 second is 1,000,000,000 nanoseconds).
+It's certainly something you'll feel in a hot loop but shouldn't matter in normal code.
+Pick what's more important to you.
+
+****
+
+Once constructed, frozen instances differ in no way from regular ones except that you cannot change its attributes.
diff --git a/docs/index.rst b/docs/index.rst
index c1f3b6b..77b5b2a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,33 +1,44 @@
-attrs: Attributes without boilerplate.
-=============================================
+=====================================
+attrs: Attributes Without Boilerplate
+=====================================
 
 Release v\ |release| (:doc:`What's new? <changelog>`).
 
-
 .. include:: ../README.rst
    :start-after: teaser-begin
+   :end-before: -spiel-end-
+
+If you want to know how this looks like, jump right into :doc:`overview`.
+If you really want to see ``attrs`` in action, :doc:`examples` will give you a comprehensive rundown of its features.
+If you're skeptical and want to know how it works first, check out ":doc:`how-does-it-work`".
+
+.. include:: ../README.rst
+   :start-after: -testimonials-
+   :end-before: -end-
 
 
 User's Guide
-------------
+============
 
 .. toctree::
-   :maxdepth: 1
+   :maxdepth: 2
 
+   overview
    why
    examples
    api
    extending
+   how-does-it-work
 
 
-Project Information
--------------------
+.. include:: ../README.rst
+   :start-after: -project-information-
 
 .. toctree::
    :maxdepth: 1
 
-   backward-compatibility
    license
+   backward-compatibility
    contributing
    changelog
 
diff --git a/docs/overview.rst b/docs/overview.rst
new file mode 100644
index 0000000..6070b80
--- /dev/null
+++ b/docs/overview.rst
@@ -0,0 +1,79 @@
+========
+Overview
+========
+
+In order to fullfil its ambitious goal of bringing back the joy to writing classes, it gives you a class decorator and a way to declaratively define the attributes on that class:
+
+.. include:: ../README.rst
+   :start-after: -code-begin-
+   :end-before: -testimonials-
+
+
+.. _philosophy:
+
+Philosophy
+==========
+
+It's about regular classes.
+   ``attrs`` for creating well-behaved classes with a type, attributes, methods, and everything that comes with a class.
+   It can be used for data-only containers like ``namedtuple``\ s or ``types.SimpleNamespace`` but they're just a sub-genre of what ``attrs`` is good for.
+
+The class belongs to the users.
+   You define a class and ``attrs`` adds static methods to that class based on the attributes you declare.
+   The end.
+   It doesn't add meta classes.
+   It doesn't add classes you've never heard of to your inheritance tree.
+   An ``attrs`` class in runtime is indistiguishable from a regular class: because it *is* a regular class with a few boilerplate-y methods attached.
+
+Be light on API impact.
+   As convenient as it seems at first, ``attrs`` will *not* tack on any methods to your classes save the dunder ones.
+   Hence all the useful :ref:`tools <helpers>` that come with ``attrs`` live in functions that operate on top of instances.
+   Since they take an ``attrs`` instance as their first argument, you can attach them to your classes with one line of code.
+
+Performance matters.
+   ``attrs`` runtime impact is very close to zero because all the work is done when the class is defined.
+   Once you're instantiating it, ``attrs`` is out of the picture completely.
+
+No surprises.
+   ``attrs`` creates classes that arguably work the way a Python beginner would reasonably expect them to work.
+   It doesn't try to guess what you mean because explicit is better than implicit.
+   It doesn't try to be clever because software shouldn't be clever.
+
+Check out :doc:`how-does-it-work` if you'd like to know how it achieves all of the above.
+
+
+What ``attrs`` Is Not
+=====================
+
+``attrs`` does *not* invent some kind of magic system that pulls classes out of its hat using meta classes, runtime introspection, and shaky interdependencies.
+
+All ``attrs`` does is take your declaration, write dunder methods based on that information, and attach them to your class.
+It does *nothing* dynamic at runtime, hence zero runtime overhead.
+It's still *your* class.
+Do with it as you please.
+
+
+On the ``attr.s`` and ``attr.ib`` Names
+=======================================
+
+The ``attr.s`` decorator and the ``attr.ib`` function aren't any obscure abbreviations.
+They are a *concise* and highly *readable* way to write ``attrs`` and ``attrib`` with an *explicit namespace*.
+
+At first, some people have a negative gut reaction to that; resembling the reactions to Python's significant whitespace.
+And as with that, once one gets used to it, the readability and explicitness of that API prevails and delights.
+
+For those who can't swallow that API at all, ``attrs`` comes with serious business aliases: ``attr.attrs`` and ``attr.attrib``.
+
+Therefore, the following class definition is identical to the previous one:
+
+.. doctest::
+
+   >>> from attr import attrs, attrib, Factory
+   >>> @attrs
+   ... class C(object):
+   ...     x = attrib(default=42)
+   ...     y = attrib(default=Factory(list))
+   >>> C()
+   C(x=42, y=[])
+
+Use whichever variant fits your taste better.
diff --git a/docs/why.rst b/docs/why.rst
... 2495 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-attrs.git



More information about the Python-modules-commits mailing list