{"action":"created","issue":{"url":"https://api.github.com/repos/python-attrs/attrs/issues/238","repository_url":"https://api.github.com/repos/python-attrs/attrs","labels_url":"https://api.github.com/repos/python-attrs/attrs/issues/238/labels{/name}","comments_url":"https://api.github.com/repos/python-attrs/attrs/issues/238/comments","events_url":"https://api.github.com/repos/python-attrs/attrs/issues/238/events","html_url":"https://github.com/python-attrs/attrs/pull/238","id":253142170,"number":238,"title":"Add PEP484 stubs","user":{"login":"chadrik","id":63251,"avatar_url":"https://avatars1.githubusercontent.com/u/63251?v=4","gravatar_id":"","url":"https://api.github.com/users/chadrik","html_url":"https://github.com/chadrik","followers_url":"https://api.github.com/users/chadrik/followers","following_url":"https://api.github.com/users/chadrik/following{/other_user}","gists_url":"https://api.github.com/users/chadrik/gists{/gist_id}","starred_url":"https://api.github.com/users/chadrik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chadrik/subscriptions","organizations_url":"https://api.github.com/users/chadrik/orgs","repos_url":"https://api.github.com/users/chadrik/repos","events_url":"https://api.github.com/users/chadrik/events{/privacy}","received_events_url":"https://api.github.com/users/chadrik/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":92,"created_at":"2017-08-27T05:25:31Z","updated_at":"2018-03-12T23:53:37Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/python-attrs/attrs/pulls/238","html_url":"https://github.com/python-attrs/attrs/pull/238","diff_url":"https://github.com/python-attrs/attrs/pull/238.diff","patch_url":"https://github.com/python-attrs/attrs/pull/238.patch"},"body":"Here's a first take at PEP484-compatible pyi stubs.  The discussion in #215 has been mostly focused on runtime type checking, so I wanted to make sure that the plan discussed there will work with static analysis as well.\r\n\r\nHere's a quick test of the stubs that I put together to run against mypy:\r\n\r\n```python\r\nfrom typing import cast\r\nimport attr\r\n\r\n@attr.s\r\nclass C(object):\r\n    x : int = attr.ib(convert=int)\r\n    y: str = attr.ib()\r\n\r\nc = C('1', 'foo')  # E: Too many arguments for \"C\"\r\nc.x = 2\r\nc.y = 'bar'\r\nc > C()  # E: Unsupported left operand type for > (\"C\")\r\nstr(c)\r\n\r\n# errors below are correctly detected:\r\nc.x = 'foo'  # E: Incompatible types in assignment (expression has type \"str\", variable has type \"int\")\r\nc.y = 1  # E: Incompatible types in assignment (expression has type \"int\", variable has type \"str\")\r\n\r\nD = attr.make_class('D', {'x': cast(attr._CountingAttr, attr.ib())})\r\nd = D(2)\r\n# errors below are not correctly detected (mypy knows nothing about D other than that it's a type)\r\nd.x ='foo'\r\n```\r\n\r\n\r\nmypy knows nothing about the dunder methods added by attrs, so cmp methods and `__init__` fail.  This will have to be solved with a mypy plugin, which I'll look into next. Same goes for `attr.make_class` though that's likely to be more difficult.\r\n\r\nOne important thing to note: in order to ensure that `y: str = attr.ib()` does not trigger a mypy error, the return type of `attr.ib` is `Any` instead of `_CountingAttr`.   A side effect of this is that it complicates passing the result of `attr.ib` to functions that expect `_CountingAttr` instances.  There are a handful of strategies to solve this:\r\n\r\n1. use `typing.cast`:  ugly and verbose\r\n2. create, or choose an existing, alias for `attr.ib` that will return `_CountingAttr`, to use with functions like `make_class`. \r\n3. add another argument (`make=True`?) whose presence invokes an `@overload` of `attr.ib` that returns `_CountingAttr`\r\n4. slight variation on 2.  create a public alias for `_CountingAttr` and copy the keyword defaults from `attr.ib` to `_CountingAttr.__init__`.  In other words, if you use static type checking and are working with a function that expects `_CountingAttr` instances, use `_CountingAttr()`  directly instead of `attr.ib()`\r\n\r\n~~I favor the 3rd solution.~~  After some consideration I favor 4.\r\n\r\nIf you're interested in accepting this, the next things to figure out are:\r\n- how to make tests for this, and run them on travis\r\n- how best to install the stubs (should they be moved to [python-typeshed](https://github.com/python/typeshed)?)\r\n\r\nLet me know what you think.\r\n\r\n**edit** added option 4.\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/python-attrs/attrs/issues/comments/372500494","html_url":"https://github.com/python-attrs/attrs/pull/238#issuecomment-372500494","issue_url":"https://api.github.com/repos/python-attrs/attrs/issues/238","id":372500494,"user":{"login":"chadrik","id":63251,"avatar_url":"https://avatars1.githubusercontent.com/u/63251?v=4","gravatar_id":"","url":"https://api.github.com/users/chadrik","html_url":"https://github.com/chadrik","followers_url":"https://api.github.com/users/chadrik/followers","following_url":"https://api.github.com/users/chadrik/following{/other_user}","gists_url":"https://api.github.com/users/chadrik/gists{/gist_id}","starred_url":"https://api.github.com/users/chadrik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chadrik/subscriptions","organizations_url":"https://api.github.com/users/chadrik/orgs","repos_url":"https://api.github.com/users/chadrik/repos","events_url":"https://api.github.com/users/chadrik/events{/privacy}","received_events_url":"https://api.github.com/users/chadrik/received_events","type":"User","site_admin":false},"created_at":"2018-03-12T23:53:37Z","updated_at":"2018-03-12T23:53:37Z","author_association":"CONTRIBUTOR","body":"speaking of the advantages of having all the tests in one place:\r\n\r\n@euresti I'm getting new errors when running mypy against the doctests:\r\n\r\n```\r\nLine 1, in converters1\r\nFailed example:\r\n    import attr\r\n    @attr.s\r\n    class C(object):\r\n        x = attr.ib(converter=int)\r\n    o = C(\"1\")\r\n    o.x\r\nExpected nothing\r\nGot:\r\n    main:4: error: Unsupported converter function, only named functions are currently supported\r\n```\r\n\r\nI assume this is trying to ward off lambdas, but getting tripped up by builtins?\r\n\r\n"}}
{"actor":{"display_login":"chadrik"}}