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

Add auto_attribs #277

Merged
merged 17 commits into from
Nov 8, 2017
Merged

Add auto_attribs #277

merged 17 commits into from
Nov 8, 2017

Conversation

hynek
Copy link
Member

@hynek hynek commented Oct 27, 2017

Well, here we go. I’ve also added examples for the type argument.

Fixes #262

Final step before 17.3.0.

@hynek hynek added this to the 17.3 milestone Oct 27, 2017
@codecov
Copy link

codecov bot commented Oct 27, 2017

Codecov Report

Merging #277 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master   #277   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           9      9           
  Lines         666    688   +22     
  Branches      138    145    +7     
=====================================
+ Hits          666    688   +22
Impacted Files Coverage Δ
src/attr/exceptions.py 100% <100%> (ø) ⬆️
src/attr/_make.py 100% <100%> (ø) ⬆️
src/attr/__init__.py 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2a50c4b...5decaa6. Read the comment docs.

@hynek
Copy link
Member Author

hynek commented Oct 27, 2017

Also I wonder if we should troll a bit and add a dataclass = attr.s(auto_attribs=True) alias. ;)

@hynek
Copy link
Member Author

hynek commented Nov 3, 2017

People who might be interested to give some feedback on the API because they expressed interest in this stuff before: @agronholm @wsanchez @ambv @DRMacIver @chadrik

I’m not as afraid to ship a bug as locking us into a conceptually wrong direction.

@wsanchez
Copy link

wsanchez commented Nov 3, 2017

The auto_attrib example looks great to me.

... y: int
... foo: typing.Any = attr.ib(
... default="every attrib needs a type if auto_attribs=True"
... )

This comment was marked as spam.

@wsanchez
Copy link

wsanchez commented Nov 3, 2017

The dataclass trolling alias is kind of a great idea but it really wants to be compatible, so this example from PEP 557 should work, for example:

@attr.s(auto_attribs=True)
class InventoryItem:
    quantity_on_hand: int = 0

@agronholm
Copy link

Is my hunch correct that it does not properly handle class variable annotations (ClassVar[....])? Those must be ignored for this to work properly.

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

Is my hunch correct that it does not properly handle class variable annotations (ClassVar[....])? Those must be ignored for this to work properly.

Could you give a full example of what wouldn’t work please?

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

OMG @wsanchez thanks for reminding me! Implemented in 0ea9b00 and it looks epic!

This works now as expected:

@attr.s(auto_attribs=True)
class C:
    a: int
    x: typing.List[int] = attr.Factory(list)
    y: int = 2
    z: int = attr.ib(default=3)
    foo: typing.Any = None

@agronholm
Copy link

Could you give a full example of what wouldn’t work please?

@attr.s(auto_attribs=True)
class Foo:
    var: ClassVar[int]
    foo: str
    bar: bool

Here foo and bar should be recognized as attrib()utes but not var.

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

@agronholm hm that’s interesting in combination with #220.

Doesn’t a ClassVar have to have a value too? We could treat var: ClassVar[int] = 42 like attr.ib(init=False), or am I missing something?

@agronholm
Copy link

Doesn’t a ClassVar have to have a value too?

Why? You could always set it later.

We could treat var: ClassVar[int] = 42 like attr.ib(init=False), or am I missing something?

No, because when combining with slots=True, it would add a __slots__ entry for it, which is wrong.

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

Why? You could always set it later.

Hm yeah I guess. It’s probably not too common (except for subclassing) but it’s possible.

No, because when combining with slots=True, it would add a __slots__ entry for it, which is wrong.

Well yeah, black magic around slots is implied.


The big question now is if we can merge this without blocking ourselves from handling #220 nicely and the answer seems to be “no”.

So what would be a good way to support this?

  • allow a way to mark attributes as class variables (either x: ClassVar[int] or attr.ib(class_var=True))
  • make those always init=False
  • for slots:
    • set the attribute to the value on the new class
    • don't add them to __slots__

Missing something?


As for next steps, if we can agree on what I’ve just outlined, I’d take the discussion to #220, promote it to blocking for 17.3 and get this merged.

It’s frustrating that 17.3.0 moved into a far future again but I really don’t want to paint myself into a corner with this because I really care about #220.

@agronholm
Copy link

What is the benefit of including class variables in the attrs system in the first place?

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

In non-slots you can overwrite class variables and they become instance variables, see #220 for a discussion. It kind of gives you “free” defaults.

@agronholm
Copy link

I've moved the discussion to the other thread.

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

From the docs:

ClassVar is not a class itself, and should not be used with isinstance() or issubclass(). ClassVar does not change Python runtime behavior, but it can be used by third-party type checkers.

Ehhh…so what is the clean way here? I just went for basically isinstance(a, ClassVar.__class__) which appears to work.

@agronholm
Copy link

Another question: how will you deal with foo: int = 4 and slots=True?

@agronholm
Copy link

Also, have you considered that the user might be using backports.typing?

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

For now it’s treated as a default as per documentation:

>>> i = C()

>>> i.foo
4

>>> i.foo = 5

>>> i.foo
5

Are you insinuating we should make them class variables? I feel like it’s more useful this way and if you want a class var, you use a ClassVar. (it also copies PEP 557 semantics)

@hynek
Copy link
Member Author

hynek commented Nov 4, 2017

Also, have you considered that the user might be using backports.typing?

Since we only support annotations on Python 3.6, I see no value in adding that complexity.

@hynek
Copy link
Member Author

hynek commented Nov 7, 2017

Ugh looks like we need to rethink the handling of ClassVar: ericvsmith/dataclasses#61

@hynek
Copy link
Member Author

hynek commented Nov 7, 2017

As for the factory drama: I think I’ll go with option 1 for now unless @Tinche can shed some different light on this.


That said, is there some way to make it work with a different function that works somehow differently? x: List[int] = factory(list) just looks too cute to be passed on. :|

@agronholm
Copy link

I still don't understand what the actual problem is with x: List[int] = Factory(list).

@Tinche
Copy link
Member

Tinche commented Nov 7, 2017

Ugh. I say let's go with @chadrik 's option two and allow it. "Useful now" trumps "maybe easier for mypy" later.

@hynek
Copy link
Member Author

hynek commented Nov 7, 2017

Allowing was never the question, since we just apply the default…it works by accident. :) The question is what we put into the docs. :|


But I really need to do something clever about the typing.ClassVar thingie for the reason alone, that typing imports are slow. Sigh

The implementation is gross but importing `typing` is slow and there are
discussions to remove it from the stdlib alltogether.
"""
return str(annot).startswith("typing.ClassVar")

This comment was marked as spam.

@chadrik
Copy link
Contributor

chadrik commented Nov 7, 2017

That said, is there some way to make it work with a different function that works somehow differently?

There is a fourth option, which I did not see previously because I was blinded by my own bias. We can stub Factory so that it returns Any, which disables type checking for this object completely and would therefore allow it to be used in the short form or the long form without static type check errors. The downside is that you are no longer warned about actual errors, such as:

x: typing.List[int] = attr.Factory(str)

I prefer option 2 over this. With option 2 there is a low chance of false errors, but with option 4 there is a high chance of undetected errors.

@wsanchez
Copy link

wsanchez commented Nov 7, 2017

@chadrik: I agree.

The false errors in option 2 are rare and easily worked around with a cast.

@wsanchez
Copy link

wsanchez commented Nov 7, 2017

Actually, the more I think about it, the more Option 2 seems correct to me. x is a List[int] in the intended API for class C. That Factory is involved at all is only because I'm using attrs; that is: Factory is an artifact of attrs's API, not of C's, so C's annotations ideally shouldn't leak that out.

No?

@agronholm
Copy link

Actually, the more I think about it, the more Option 2 seems correct to me. x is a List[int] in the intended API for class C. That Factory is involved at all is only because I'm using attrs; that is: Factory is an artifact of attrs's API, not of C's, so C's annotations ideally shouldn't leak that out.

I just tried, and PyCharm does not make the type of x the union of List[int] and Factory. MyPy does. But if Factory() was marked as returning object, it would not pollute the type information, right?

@chadrik
Copy link
Contributor

chadrik commented Nov 7, 2017

I just tried, and PyCharm does not make the type of x the union of List[int] and Factory. MyPy does.

I'm not entirely sure what you mean. Without any special pyi stubs for attrs, this is an error in mypy:

x: typing.List[int] = attr.Factory(list)

Based on PEP484, when you annotate a variable with a type, the value assigned to it must be "compatible" with that type. Nothing here becomes the union of anything else. A Factory is not a list, so it's an error. I'm not sure what PyCharm does here, but it still has a lot of catching up to do wrt PEP484.

But if Factory() was marked as returning object, it would not pollute the type information, right?

Still not sure what you mean. If you want the above code to work without an error in mypy, Factory (or the stubs for Factory) must return a value that is compatible with List[int]. Any is compatible with everything (it's the union of all possibilities), so as I said earlier, that is one option, but not one that I like. object is the intersection of all possibilities: i.e. the lowest common denominator. Only operations that are possible on all types are valid with object. It's not what you want here.

@agronholm
Copy link

Still not sure what you mean. If you want the above code to work without an error in mypy, Factory must return a value that is compatible with List[int].

Could you show me a simple script with such an annotation that would result in a mypy error on inspection?

@chadrik
Copy link
Contributor

chadrik commented Nov 7, 2017

Could you show me a simple script with such an annotation that would result in a mypy error on inspection?

import typing
import attr
x: typing.List[int] = attr.Factory(list)

Make sure that you set MYPYPATH to the <attrs_repo>/src directory (do not set it to your site-packages directory).

@agronholm
Copy link

Wait, are you saying that I need to have a checked out copy of the attrs git repo whenever I run mypy against my code??

@hynek
Copy link
Member Author

hynek commented Nov 7, 2017

That or get the stubs into typeshed IIUC. It’s kind of bonkers.

@agronholm
Copy link

Alright, no wonder I didn't get any errors before then.

@chadrik
Copy link
Contributor

chadrik commented Nov 7, 2017

That or get the stubs into typeshed IIUC. It’s kind of bonkers.

Yeah, it's very annoying, but there's a pep in progress to solve it at the distutils/setuptools level.

Alright, no wonder I didn't get any errors before then.

Well, you would have gotten an error like Cannot find module named 'attr'

@agronholm
Copy link

Well, you would have gotten an error like Cannot find module named 'attr'

I routinely skip missing imports with MyPy because most libraries don't have stubs.

@hynek
Copy link
Member Author

hynek commented Nov 8, 2017

Since everyone seems to love option 2...do I have to do something a out it or am I done?

@hynek hynek merged commit 88aa1c8 into master Nov 8, 2017
@hynek hynek deleted the auto-attribs branch November 8, 2017 10:15
@chadrik
Copy link
Contributor

chadrik commented Nov 8, 2017

Since everyone seems to love option 2...do I have to do something a out it or am I done?

I handled it over on #238

1 similar comment
@chadrik
Copy link
Contributor

chadrik commented Nov 8, 2017

Since everyone seems to love option 2...do I have to do something a out it or am I done?

I handled it over on #238

bors-fusion bot referenced this pull request in fusionapp/fusion-index Nov 15, 2017
167: Scheduled weekly dependency update for week 46 r=mithrandi




## Updates
Here's a list of all the updates bundled in this pull request. I've added some links to make it easier for you to find all the information you need.
<table align="center">

<tr>
<td><b>attrs</b></td>
<td align="center">17.2.0</td>
<td align="center">&raquo;</td>
<td align="center">17.3.0</td>
<td>
     <a href="https://pypi.python.org/pypi/attrs">PyPI</a> | <a href="https://pyup.io/changelogs/attrs/">Changelog</a> | <a href="http://www.attrs.org/">Homepage</a> 

</td>

<tr>
<td><b>cryptography</b></td>
<td align="center">2.1.2</td>
<td align="center">&raquo;</td>
<td align="center">2.1.3</td>
<td>
     <a href="https://pypi.python.org/pypi/cryptography">PyPI</a> | <a href="https://pyup.io/changelogs/cryptography/">Changelog</a> | <a href="https://github.com/pyca/cryptography">Repo</a> 

</td>

<tr>
<td><b>hypothesis</b></td>
<td align="center">3.33.0</td>
<td align="center">&raquo;</td>
<td align="center">3.37.0</td>
<td>
     <a href="https://pypi.python.org/pypi/hypothesis">PyPI</a> | <a href="https://pyup.io/changelogs/hypothesis/">Changelog</a> | <a href="https://github.com/HypothesisWorks/hypothesis/issues">Repo</a> 

</td>

</tr>
</table>



## Changelogs


### attrs 17.2.0 -> 17.3.0

>### 17.3.0

>-------------------

>Backward-incompatible Changes
>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>- Attributes are not defined on the class body anymore.

>  This means that if you define a class ``C`` with an attribute ``x``, the class will *not* have an attribute ``x`` for introspection anymore.
>  Instead of ``C.x``, use ``attr.fields(C).x`` or look at ``C.__attrs_attrs__``.
>  The old behavior has been deprecated since version 16.1.
>  (`253 &lt;https://github.com/python-attrs/attrs/issues/253&gt;`_)


>Changes
>^^^^^^^

>- ``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
>  (`102 &lt;https://github.com/python-attrs/attrs/issues/102&gt;`_, `226 &lt;https://github.com/python-attrs/attrs/issues/226&gt;`_, `269 &lt;https://github.com/python-attrs/attrs/issues/269&gt;`_, `270 &lt;https://github.com/python-attrs/attrs/issues/270&gt;`_, `272 &lt;https://github.com/python-attrs/attrs/issues/272&gt;`_)
>- Added ``type`` argument to ``attr.ib()`` and corresponding ``type`` attribute to ``attr.Attribute``.

>  This change paves the way for automatic type checking and serialization (though as of this release ``attrs`` does not make use of it).
>  In Python 3.6 or higher, the value of ``attr.Attribute.type`` can alternately be set using variable type annotations
>  (see `PEP 526 &lt;https://www.python.org/dev/peps/pep-0526/&gt;`_). (`151 &lt;https://github.com/python-attrs/attrs/issues/151&gt;`_, `214 &lt;https://github.com/python-attrs/attrs/issues/214&gt;`_, `215 &lt;https://github.com/python-attrs/attrs/issues/215&gt;`_, `239 &lt;https://github.com/python-attrs/attrs/issues/239&gt;`_)
>- The combination of ``str=True`` and ``slots=True`` now works on Python 2.
>  (`198 &lt;https://github.com/python-attrs/attrs/issues/198&gt;`_)
>- ``attr.Factory`` is hashable again. (`204
>  &lt;https://github.com/python-attrs/attrs/issues/204&gt;`_)
>- Subclasses now can overwrite attribute definitions of their superclass.

>  That means that you can -- for example -- change the default value for an attribute by redefining it.
>  (`221 &lt;https://github.com/python-attrs/attrs/issues/221&gt;`_, `229 &lt;https://github.com/python-attrs/attrs/issues/229&gt;`_)
>- Added new option ``auto_attribs`` to ``attr.s`` that allows to collect annotated fields without setting them to ``attr.ib()``.

>  Setting a field to an ``attr.ib()`` is still possible to supply options like validators.
>  Setting it to any other value is treated like it was passed as ``attr.ib(default=value)`` -- passing an instance of ``attr.Factory`` also works as expected.
>  (`262 &lt;https://github.com/python-attrs/attrs/issues/262&gt;`_, `277 &lt;https://github.com/python-attrs/attrs/issues/277&gt;`_)
>- Instances of classes created using ``attr.make_class()`` can now be pickled.
>  (`282 &lt;https://github.com/python-attrs/attrs/issues/282&gt;`_)


>----








### hypothesis 3.33.0 -> 3.37.0

>### 3.37.0

>-------------------

>This is a deprecation release for some health check related features.

>The following are now deprecated:

>* Passing :attr:`~hypothesis.HealthCheck.exception_in_generation` to
>  :attr:`~hypothesis.settings.suppress_health_check`. This no longer does
>  anything even when passed -  All errors that occur during data generation
>  will now be immediately reraised rather than going through the health check
>  mechanism.
>* Passing :attr:`~hypothesis.HealthCheck.random_module` to
>  :attr:`~hypothesis.settings.suppress_health_check`. This hasn&#39;t done anything
>  for a long time, but was never explicitly deprecated. Hypothesis always seeds
>  the random module when running given tests, so this is no longer an error
>  and suppressing it doesn&#39;t do anything.
>* Passing non-:class:`~hypothesis.HealthCheck` values in
>  :attr:`~hypothesis.settings.suppress_health_check`. This was previously
>  allowed but never did anything useful.

>In addition, passing a non-iterable value as :attr:`~hypothesis.settings.suppress_health_check`
>will now raise an error immediately (it would never have worked correctly, but
>it would previously have failed later). Some validation error messages have
>also been updated.

>This work was funded by `Smarkets &lt;https://smarkets.com/&gt;`_.

>-------------------


>### 3.36.1

>-------------------

>This is a yak shaving release, mostly concerned with our own tests.

>While :func:`~python:inspect.getfullargspec` was documented as deprecated
>in Python 3.5, it never actually emitted a warning.  Our code to silence
>this (nonexistent) warning has therefore been removed.

>We now run our tests with ``DeprecationWarning`` as an error, and made some
>minor changes to our own tests as a result.  This required similar upstream
>updates to :pypi:`coverage` and :pypi:`execnet` (a test-time dependency via
>:pypi:`pytest-xdist`).

>There is no user-visible change in Hypothesis itself, but we encourage you
>to consider enabling deprecations as errors in your own tests.

>-------------------


>### 3.36.0

>-------------------

>This release adds a setting to the public API, and does some internal cleanup:

>- The :attr:`~hypothesis.settings.derandomize` setting is now documented (:issue:`890`)
>- Removed - and disallowed - all &#39;bare excepts&#39; in Hypothesis (:issue:`953`)
>- Documented the :attr:`~hypothesis.settings.strict` setting as deprecated, and
>  updated the build so our docs always match deprecations in the code.

>-------------------


>### 3.35.0

>-------------------

>This minor release supports constraining :func:`~hypothesis.strategies.uuids`
>to generate :class:`~python:uuid.UUID`s of a particular version.
>(:issue:`721`)

>Thanks to Dion Misic for this feature.

>-------------------


>### 3.34.1

>-------------------

>This patch updates the documentation to suggest
>:func:`builds(callable) &lt;hypothesis.strategies.builds&gt;` instead of
>:func:`just(callable()) &lt;hypothesis.strategies.just&gt;`.

>-------------------


>### 3.34.0

>-------------------

>Hypothesis now emits deprecation warnings if you apply
>:func:`given &lt;hypothesis.given&gt;` more than once to a target.

>Applying :func:`given &lt;hypothesis.given&gt;` repeatedly wraps the target multiple
>times. Each wrapper will search the space of of possible parameters separately.
>This is equivalent but will be much more inefficient than doing it with a
>single call to :func:`given &lt;hypothesis.given&gt;`.

>For example, instead of
>``given(booleans()) given(integers())``, you could write
>``given(booleans(), integers())``

>-------------------


>### 3.33.1

>-------------------

>This is a bugfix release:

>- :func:`~hypothesis.strategies.builds` would try to infer a strategy for
>  required positional arguments of the target from type hints, even if they
>  had been given to :func:`~hypothesis.strategies.builds` as positional
>  arguments (:issue:`946`).  Now it only infers missing required arguments.
>- An internal introspection function wrongly reported ``self`` as a required
>  argument for bound methods, which might also have affected
>  :func:`~hypothesis.strategies.builds`.  Now it knows better.

>-------------------









That's it for now!

Happy merging! 🤖
bors-fusion bot referenced this pull request in fusionapp/entropy Nov 15, 2017
161: Scheduled weekly dependency update for week 46 r=mithrandi




## Updates
Here's a list of all the updates bundled in this pull request. I've added some links to make it easier for you to find all the information you need.
<table align="center">

<tr>
<td><b>attrs</b></td>
<td align="center">17.2.0</td>
<td align="center">&raquo;</td>
<td align="center">17.3.0</td>
<td>
     <a href="https://pypi.python.org/pypi/attrs">PyPI</a> | <a href="https://pyup.io/changelogs/attrs/">Changelog</a> | <a href="http://www.attrs.org/">Homepage</a> 

</td>

<tr>
<td><b>cryptography</b></td>
<td align="center">2.1.2</td>
<td align="center">&raquo;</td>
<td align="center">2.1.3</td>
<td>
     <a href="https://pypi.python.org/pypi/cryptography">PyPI</a> | <a href="https://pyup.io/changelogs/cryptography/">Changelog</a> | <a href="https://github.com/pyca/cryptography">Repo</a> 

</td>

<tr>
<td><b>lxml</b></td>
<td align="center">4.1.0</td>
<td align="center">&raquo;</td>
<td align="center">4.1.1</td>
<td>
     <a href="https://pypi.python.org/pypi/lxml">PyPI</a> | <a href="https://pyup.io/changelogs/lxml/">Changelog</a> | <a href="http://lxml.de/">Homepage</a> | <a href="https://bugs.launchpad.net/lxml">Bugtracker</a> 

</td>

<tr>
<td><b>pytz</b></td>
<td align="center">2017.2</td>
<td align="center">&raquo;</td>
<td align="center">2017.3</td>
<td>
     <a href="https://pypi.python.org/pypi/pytz">PyPI</a> | <a href="http://pythonhosted.org/pytz">Homepage</a> | <a href="http://pythonhosted.org/pytz/">Docs</a> 

</td>

</tr>
</table>



## Changelogs


### attrs 17.2.0 -> 17.3.0

>### 17.3.0

>-------------------

>Backward-incompatible Changes
>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>- Attributes are not defined on the class body anymore.

>  This means that if you define a class ``C`` with an attribute ``x``, the class will *not* have an attribute ``x`` for introspection anymore.
>  Instead of ``C.x``, use ``attr.fields(C).x`` or look at ``C.__attrs_attrs__``.
>  The old behavior has been deprecated since version 16.1.
>  (`253 &lt;https://github.com/python-attrs/attrs/issues/253&gt;`_)


>Changes
>^^^^^^^

>- ``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
>  (`102 &lt;https://github.com/python-attrs/attrs/issues/102&gt;`_, `226 &lt;https://github.com/python-attrs/attrs/issues/226&gt;`_, `269 &lt;https://github.com/python-attrs/attrs/issues/269&gt;`_, `270 &lt;https://github.com/python-attrs/attrs/issues/270&gt;`_, `272 &lt;https://github.com/python-attrs/attrs/issues/272&gt;`_)
>- Added ``type`` argument to ``attr.ib()`` and corresponding ``type`` attribute to ``attr.Attribute``.

>  This change paves the way for automatic type checking and serialization (though as of this release ``attrs`` does not make use of it).
>  In Python 3.6 or higher, the value of ``attr.Attribute.type`` can alternately be set using variable type annotations
>  (see `PEP 526 &lt;https://www.python.org/dev/peps/pep-0526/&gt;`_). (`151 &lt;https://github.com/python-attrs/attrs/issues/151&gt;`_, `214 &lt;https://github.com/python-attrs/attrs/issues/214&gt;`_, `215 &lt;https://github.com/python-attrs/attrs/issues/215&gt;`_, `239 &lt;https://github.com/python-attrs/attrs/issues/239&gt;`_)
>- The combination of ``str=True`` and ``slots=True`` now works on Python 2.
>  (`198 &lt;https://github.com/python-attrs/attrs/issues/198&gt;`_)
>- ``attr.Factory`` is hashable again. (`204
>  &lt;https://github.com/python-attrs/attrs/issues/204&gt;`_)
>- Subclasses now can overwrite attribute definitions of their superclass.

>  That means that you can -- for example -- change the default value for an attribute by redefining it.
>  (`221 &lt;https://github.com/python-attrs/attrs/issues/221&gt;`_, `229 &lt;https://github.com/python-attrs/attrs/issues/229&gt;`_)
>- Added new option ``auto_attribs`` to ``attr.s`` that allows to collect annotated fields without setting them to ``attr.ib()``.

>  Setting a field to an ``attr.ib()`` is still possible to supply options like validators.
>  Setting it to any other value is treated like it was passed as ``attr.ib(default=value)`` -- passing an instance of ``attr.Factory`` also works as expected.
>  (`262 &lt;https://github.com/python-attrs/attrs/issues/262&gt;`_, `277 &lt;https://github.com/python-attrs/attrs/issues/277&gt;`_)
>- Instances of classes created using ``attr.make_class()`` can now be pickled.
>  (`282 &lt;https://github.com/python-attrs/attrs/issues/282&gt;`_)


>----








### lxml 4.1.0 -> 4.1.1

>### 4.1.1

>==================

>* Rebuild with Cython 0.27.3 to improve support for Py3.7.











That's it for now!

Happy merging! 🤖
bors-fusion bot referenced this pull request in fusionapp/documint Nov 17, 2017
118: Update attrs to 17.3.0 r=mithrandi


There's a new version of [attrs](https://pypi.python.org/pypi/attrs) available.
You are currently using **17.2.0**. I have updated it to **17.3.0**



These links might come in handy:  <a href="https://pypi.python.org/pypi/attrs">PyPI</a> | <a href="https://pyup.io/changelogs/attrs/">Changelog</a> | <a href="http://www.attrs.org/">Homepage</a> 



### Changelog
> 
>### 17.3.0

>-------------------

>Backward-incompatible Changes
>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>- Attributes are not defined on the class body anymore.

>  This means that if you define a class ``C`` with an attribute ``x``, the class will *not* have an attribute ``x`` for introspection anymore.
>  Instead of ``C.x``, use ``attr.fields(C).x`` or look at ``C.__attrs_attrs__``.
>  The old behavior has been deprecated since version 16.1.
>  (`253 &lt;https://github.com/python-attrs/attrs/issues/253&gt;`_)


>Changes
>^^^^^^^

>- ``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
>  (`102 &lt;https://github.com/python-attrs/attrs/issues/102&gt;`_, `226 &lt;https://github.com/python-attrs/attrs/issues/226&gt;`_, `269 &lt;https://github.com/python-attrs/attrs/issues/269&gt;`_, `270 &lt;https://github.com/python-attrs/attrs/issues/270&gt;`_, `272 &lt;https://github.com/python-attrs/attrs/issues/272&gt;`_)
>- Added ``type`` argument to ``attr.ib()`` and corresponding ``type`` attribute to ``attr.Attribute``.

>  This change paves the way for automatic type checking and serialization (though as of this release ``attrs`` does not make use of it).
>  In Python 3.6 or higher, the value of ``attr.Attribute.type`` can alternately be set using variable type annotations
>  (see `PEP 526 &lt;https://www.python.org/dev/peps/pep-0526/&gt;`_). (`151 &lt;https://github.com/python-attrs/attrs/issues/151&gt;`_, `214 &lt;https://github.com/python-attrs/attrs/issues/214&gt;`_, `215 &lt;https://github.com/python-attrs/attrs/issues/215&gt;`_, `239 &lt;https://github.com/python-attrs/attrs/issues/239&gt;`_)
>- The combination of ``str=True`` and ``slots=True`` now works on Python 2.
>  (`198 &lt;https://github.com/python-attrs/attrs/issues/198&gt;`_)
>- ``attr.Factory`` is hashable again. (`204
>  &lt;https://github.com/python-attrs/attrs/issues/204&gt;`_)
>- Subclasses now can overwrite attribute definitions of their superclass.

>  That means that you can -- for example -- change the default value for an attribute by redefining it.
>  (`221 &lt;https://github.com/python-attrs/attrs/issues/221&gt;`_, `229 &lt;https://github.com/python-attrs/attrs/issues/229&gt;`_)
>- Added new option ``auto_attribs`` to ``attr.s`` that allows to collect annotated fields without setting them to ``attr.ib()``.

>  Setting a field to an ``attr.ib()`` is still possible to supply options like validators.
>  Setting it to any other value is treated like it was passed as ``attr.ib(default=value)`` -- passing an instance of ``attr.Factory`` also works as expected.
>  (`262 &lt;https://github.com/python-attrs/attrs/issues/262&gt;`_, `277 &lt;https://github.com/python-attrs/attrs/issues/277&gt;`_)
>- Instances of classes created using ``attr.make_class()`` can now be pickled.
>  (`282 &lt;https://github.com/python-attrs/attrs/issues/282&gt;`_)


>----








*Got merge conflicts? Close this PR and delete the branch. I'll create a new PR for you.*

Happy merging! 🤖
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants