Skip to content

Add attrs library - #1838

Merged
JelleZijlstra merged 5 commits into
python:masterfrom
chadrik:attrs
Feb 3, 2018
Merged

Add attrs library#1838
JelleZijlstra merged 5 commits into
python:masterfrom
chadrik:attrs

Conversation

@chadrik

Copy link
Copy Markdown
Contributor

Hi, here are stubs for attrs. I've already received permission from @hynekhere.

After this is merged, @euresti will follow up with his PR on mypy to add plugin support.

@ilevkivskyiilevkivskyi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just two style comments.

Comment threadthird_party/2and3/attr/__init__.pyi Outdated

# _make --

NOTHING : object

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

PEP 8 requires no space before colon.

Comment threadthird_party/2and3/attr/__init__.pyi Outdated

# 1st form catches _T set.
@overload
def attrib(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can split this definition one parameter per line:

deffun(x: type_x,
y: type_y,
z: type_z) ->ret_type: ...

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

You can split this definition one parameter per line:

I'm happy to oblige, but I'm having a little trouble reconciling that advice with the guidelines in CONTRIBUTING.md:

  • there is no line length limit;
  • prefer long lines over elaborate indentation;

If there is no line length limit, how do I decide which definitions should be split per line? This also seems to go against the latter, preferring long lines to indentation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There are no strict rules, you should just apply your reason, as an example there is builtins.open in Python 3.
My rule of thumb is if it doesn't fit in one line on my Mac, then it is definitely too long :-)

@chadrik

Copy link
Copy Markdown
ContributorAuthor

@ilevkivskyi What's next?

@ilevkivskyi

Copy link
Copy Markdown
Member

The mypy PR you mentioned is higher priority for me than this (and Python 3.7 beta 1 in four days is even higher priority).

@chadrik

Copy link
Copy Markdown
ContributorAuthor

@euresti, who is doing the mypy PR, has indicated that he needs this merged to get his PR passing tests and mergeable.

@euresti

Copy link
Copy Markdown
Contributor

Technically, without the stubs the plugin would never be called. (I haven't looked into why I just tested it and it doesn't get called.)

@ilevkivskyi

Copy link
Copy Markdown
Member

Technically, without the stubs the plugin would never be called.

This is because mypy currently only uses only typeshed. After PEP 561 is implemented it will also accept inline annotations and side-by-side stubs in third party packages.

@JelleZijlstraJelleZijlstra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Don't have time to review all this against the attrs implementation right now, but left a few comments.

Comment threadthird_party/2and3/attr/__init__.pyi Outdated
_ValidatorType = Callable[[Any, Attribute, _T], Any]
_ConverterType = Callable[[Any], _T]
_FilterType = Callable[[Attribute, Any], bool]
_ValidatorArgType = Union[_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T], ...]]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Don't have time to read through the attrs code right now, but why isn't this just Iterable or Sequence? Does it really accept only lists and tuples?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

yes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The code literally does isinstance(validator, (list, tuple)):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's unfortunate because list and tuple are invariant, so subtypes of _ValidatorType may end up not getting accepted.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Good point. Confirmed that I'm getting errors with lists of validators. I'm going to use Sequence for now and I'll open a separate ticket against attrs to see if this can be addressed in the code.

Comment threadthird_party/2and3/attr/__init__.pyi Outdated
cmp: bool = ...,
hash: Optional[bool] = ...,
init: bool = ...,
metadata: Mapping = ...,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Missing type arguments to Mapping.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

attrs doesn't have any opinion or requirement about the types within the mapping.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It should probably be Optional[Mapping[Any, Any]] since None is acceptable

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In general, even if the type arguments are Any I prefer being explicit, so that we can detect cases where we skip type arguments by accident.

def get_run_validators() -> bool: ...

# aliases --
# s = attributes = attrs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why can't you just write these lines instead of duplicating the definitions? Does that interact poorly with overloads?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Just below those commented lines:

# FIXME: there is a bug in PyCharm with creating aliases to overloads.
# Remove these when the bug is fixed:
# https://youtrack.jetbrains.com/issue/PY-27788

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would take out the commented out assignments entirely. Just to avoid confusion.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I find it's nice when testing to be able to uncomment them. I'll move the FIXME to a more co-located place.

@JelleZijlstraJelleZijlstra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A few more minor comments, then this should be good to go.

Comment threadthird_party/2and3/attr/__init__.pyi Outdated
_ValidatorType = Callable[[Any, Attribute, _T], Any]
_ConverterType = Callable[[Any], _T]
_FilterType = Callable[[Attribute, Any], bool]
_ValidatorArgType = Union[_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T], ...]]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's unfortunate because list and tuple are invariant, so subtypes of _ValidatorType may end up not getting accepted.

Comment threadthird_party/2and3/attr/__init__.pyi Outdated
cmp: bool = ...,
hash: Optional[bool] = ...,
init: bool = ...,
metadata: Mapping = ...,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In general, even if the type arguments are Any I prefer being explicit, so that we can detect cases where we skip type arguments by accident.

init: bool = ...,
metadata: Mapping = ...,
type: Optional[Type[_T]] = ...,
converter: Optional[_ConverterType[_T]] = ...) -> _T: ...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The convert argument is missing. It is apparently deprecated, but we should still include it because otherwise the positional arguments are out of sync. We could perhaps mark some or all of the arguments as keyword-only here (it will work even in Python 2).

Comment threadthird_party/2and3/attr/__init__.pyi Outdated

# TODO: add support for returning a proper attrs class from the mypy plugin
# we use Any instead of _CountingAttr so that e.g. `make_class('Foo', [attr.ib()])` is valid
def make_class(name, attrs: Union[List[str], Dict[str, Any]], bases: Tuple[type, ...] = ..., **attributes_arguments) -> type: ...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

missing type (presumably Any) on attributes_arguments

- add attrib(convert)
- replace Mapping with Optional[Mapping[Any, Any]]
- add make_class arg types
- deal properly with sequences of validator types
- fix a bug with forward references
@chadrik

Copy link
Copy Markdown
ContributorAuthor

review notes addressed.

Btw, I've added pretty thorough tests to my attrs PR for pyi stubs which cover both the attrs stubs and mypy plugin.

@JelleZijlstra

Copy link
Copy Markdown
Member

Thanks for addressing the comments! There's a minor lint error now.

@JelleZijlstra
JelleZijlstra merged commit b111a45 into python:masterFeb 3, 2018
@gvanrossum

gvanrossum commented Feb 3, 2018 via email

Copy link
Copy Markdown
Member

rhysparry added a commit to rhysparry/typeshed that referenced this pull request Feb 8, 2018
* python/master: (269 commits)
allow Optional[float] for asyncio.wait() timeout arg (python#1860)
Clean up the pytype blacklist. (python#1851)
filter function: make the callable of the first overload non-optional so that mypy is able to select the second overload for the case. (python#1855)
Accept Text in distutils *Version classes (python#1854)
Add attrs library (python#1838)
Add type stub for the lzma module (python#1844)
Add ImportError attributes name, path for Python 3.3+ (python#1849)
Add 'message' to click.decorators.version_option (python#1845)
PEP 553 and PEP 564 (python#1846)
Adding py36 additions to datetime module (python#1848)
Remove incomplete thrift stubs that cause false positives. (python#1827)
adding curses.ascii, curses.panel and curses.textpad modules (python#1792)
Fix requests session hooks type (python#1794)
Add StringIO.name and BytesIO.name (python#1802)
Fix werkzeug environ type (python#1831)
Change the return type of unittest.TestCase.fail() to NoReturn (python#1843)
_curses.tparm works on bytes, not str (python#1828)
Refine types for distutils.version (python#1835)
Add stub for stat.filemode (python#1837)
modify pytype_test to run from within pytype too, and support python3 (python#1817)
...
Sign up for freeto 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.

5 participants

@chadrik@ilevkivskyi@euresti@JelleZijlstra@gvanrossum