Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor class creation #272

Merged
merged 25 commits into from
Oct 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ Changes:
^^^^^^^^

- ``__slots__`` have arrived!
Classes now can automatically be `slots <https://docs.python.org/3.5/reference/datamodel.html#slots>`_-style (and save your precious memory) just by passing ``slots=True``.
Classes now can automatically be `slots <https://docs.python.org/3/reference/datamodel.html#slots>`_-style (and save your precious memory) just by passing ``slots=True``.
`#35 <https:/python-attrs/attrs/issues/35>`_
- 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.
Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ Testimonials

-- **Kenneth Reitz**, author of `requests <http://www.python-requests.org/>`_, Python Overlord at Heroku, `on paper no less <https://twitter.com/hynek/status/866817877650751488>`_

.. -end-

.. -project-information-

Getting Help
============
Expand All @@ -105,9 +108,6 @@ Please use the ``python-attrs`` tag on `StackOverflow <https://stackoverflow.com

Answering questions of your fellow developers is also great way to help the project!

.. -end-

.. -project-information-

Project Information
===================
Expand Down
1 change: 1 addition & 0 deletions changelog.d/269.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
1 change: 1 addition & 0 deletions changelog.d/270.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
1 change: 1 addition & 0 deletions changelog.d/272.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
5 changes: 4 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ class C(object):

collect_ignore = []
if sys.version_info[:2] < (3, 6):
collect_ignore.append("tests/test_annotations.py")
collect_ignore.extend([
"tests/test_annotations.py",
"tests/test_init_subclass.py",
])
6 changes: 4 additions & 2 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ By default, instances of classes have a dictionary for attribute storage.
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__``.
Normal Python classes can avoid using a separate dictionary for each instance of a class by `defining <https://docs.python.org/3/reference/datamodel.html#slots>`_ ``__slots__``.
For ``attrs`` classes it's enough to set ``slots=True``:

.. doctest::
Expand Down Expand Up @@ -505,9 +505,11 @@ Slot classes are a little different than ordinary, dictionary-backed classes:
...
AttributeError: 'Coordinates' object has no attribute 'z'

- 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.
- 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.

* One notable problem is that certain metaclass features like ``__init_subclass__`` do not work with slot classes.

- 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.
Expand Down
6 changes: 4 additions & 2 deletions docs/how-does-it-work.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ In order to ensure that sub-classing works as you'd expect it to work, ``attrs``
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 fewer function calls.

Once ``attrs`` knows what attributes it has to work on, it writes the requested dunder methods and attaches them to your class.
Once ``attrs`` knows what attributes it has to work on, it writes the requested dunder methods and -- depending on whether you wish to have ``__slots__`` -- creates a new class for you (``slots=True``) or attaches them to the original class (``slots=False``).
While creating new classes is more elegant, we've run into several edge cases surrounding metaclasses that make it impossible to go this route unconditionally.

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:
... class C(object):
... x = attr.ib()
>>> print(inspect.getsource(C.__init__))
def __init__(self, x):
Expand Down
Loading