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

Added support for keyword-only arguments on Python 3+ [rebase] #411

Merged
merged 14 commits into from
Aug 11, 2018

Conversation

asford
Copy link
Contributor

@asford asford commented Jul 24, 2018

This is a rebase-and-extension of pull #281. @malinoff (& @hynek), I'm happy to handle this as a sub-pull of that request or merge independently.

Closes #335, closes #106, closes #38.

Pull Request Check List

This is just a reminder about the most common mistakes. Please make sure that you tick all appropriate boxes. But please read our contribution guide at least once, it will save you unnecessary review cycles!

  • Added tests for changed code.
  • New features have been added to our Hypothesis testing strategy.
  • Changes or additions to public APIs are reflected in our type stubs (files ending in .pyi).
  • Updated documentation for changed code.
  • Documentation in .rst files is written using semantic newlines.
  • Changed/added classes/methods/functions have appropriate versionadded, versionchanged, or deprecated directives.
  • Changes (and possible deprecations) have news fragments in changelog.d.

If you have any questions to any of the points above, just submit and ask! This checklist is here to help you, not to deter you from contributing!

@asford asford changed the title Issue 106 Added support for keyword-only arguments on Python 3+ [rebase] Jul 24, 2018
@asford
Copy link
Contributor Author

asford commented Jul 24, 2018

@hynek I think this extends #281 to resolve the feedback you provided in that review. Would you mind taking a look at this implementation?

@hynek
Copy link
Member

hynek commented Jul 24, 2018

Thanks for reviving this! I’ll be at EuroPython for the rest of the week but will take a look once I have the time. You’ve Got a typo in the stubs btw: kw_onlly or something like that (on phone sorry).

Other reviewers are invited to pick up my slack of course. ;)

@asford
Copy link
Contributor Author

asford commented Jul 24, 2018

Great, thanks! Before I start covering my tracks, is --force push ok for fixups in PRs in this repo?

@hynek
Copy link
Member

hynek commented Jul 24, 2018

It’s your repo, do whatever the hell pleases you. We’ll squash at the end anyway.

Add `kw_only` flag to `attr.s` decorator, indicating that all class
attributes should be keyword-only in __init__.

Minor updates to internal interface of `Attribute` to support
evolution of attributes to `kw_only` in class factory.

Expand examples with `attr.s` level kw_only.
Hear ye, hear ye. A duplicate PR is born.
@asford
Copy link
Contributor Author

asford commented Jul 24, 2018

Fixed .pyi typo and delinted; ready for review at everyone's convenience.

Copy link
Member

@hynek hynek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks pretty good! I have a bunch of minor things and one major question. :)

>>> A(a=1)
A(a=1)

`kw_only` may also be specified at via ``attr.s``, and will apply to all attributes:

This comment was marked as spam.




If you create an attribute with ``init=False``, ``kw_only`` argument is simply ignored.

This comment was marked as spam.

...
TypeError: B() missing 1 required keyword-only argument: 'b'

If you omit ``kw_only`` or specify ``kw_only=False``, then you'll get an error:

This comment was marked as spam.

This comment was marked as spam.

@@ -206,6 +212,7 @@ def attrib(
converter=converter,
metadata=metadata,
type=type,
kw_only=kw_only,

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

@@ -736,6 +760,10 @@ def attrs(
Attributes annotated as :data:`typing.ClassVar` are **ignored**.

.. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/
:param bool kw_only: Make all attributes keyword-only (Python 3+)
in the generated ``__init__`` (if ``init`` is ``False``, this
parameter is simply ignored).

This comment was marked as spam.

x = attr.ib(default=None)
y = attr.ib()

attrs, super_attrs, _ = _transform_attrs(C, None, False, True)

This comment was marked as spam.

x = attr.ib(init=False, default=0, kw_only=True)
y = attr.ib()

c = C(1)

This comment was marked as spam.

y = attr.ib()

with pytest.raises(ValueError) as e:
_transform_attrs(C, None, False, False)

This comment was marked as spam.

with pytest.raises(TypeError):
C(0, y=1)

c = C(x=0, y=1)

This comment was marked as spam.

with pytest.raises(TypeError):
C(1)

c = C(x=0, y=1)

This comment was marked as spam.

@hynek hynek added this to the 18.2 milestone Jul 28, 2018
Copy link
Member

@hynek hynek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We’re getting there!

@@ -1558,6 +1613,17 @@ def from_counting_attr(cls, name, ca, type=None):
**inst_dict
)

# Don't use attr.evolve since fields(Attribute) doesn't work
def _evolve(self, **changes):

This comment was marked as spam.

This comment was marked as spam.

if kw_only_args:
if PY2:
raise PythonTooOldError(
"Keyword-only arguments only work on Python 3 and later."

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


class PythonTooOldError(RuntimeError):
"""
An ``attrs`` feature requiring a more recent python version has been used.

This comment was marked as spam.

@attr.s(kw_only=True)
class ClassLevel(object):
a = attr.ib()

This comment was marked as spam.

@attr.s()
class AttrLevel(object):
a = attr.ib(kw_only=True)

This comment was marked as spam.

@hynek hynek merged commit 123df67 into python-attrs:master Aug 11, 2018
@hynek
Copy link
Member

hynek commented Aug 11, 2018

Thanks everyone!

@wbolster
Copy link
Member

this is awesome! thanks @asford for pushing this through!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants