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 stubs for typing #232

Merged
merged 1 commit into from
Jun 24, 2020
Merged

Add stubs for typing #232

merged 1 commit into from
Jun 24, 2020

Conversation

blueyed
Copy link
Contributor

@blueyed blueyed commented Jan 19, 2020

This is meant to be used for pytest, which mainly uses py.path.local, and is very much work in progress.

Continuation of #231

Copy link
Member

@bluetech bluetech left a comment

Choose a reason for hiding this comment

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

Will be nice to squash to one commit.

Also, as far as I'm concerned this is pretty much done, not WIP :) Unless there is something more you want to add?

@blueyed
Copy link
Contributor Author

blueyed commented Jan 19, 2020

Will be nice to squash to one commit.

Sure. Would be nice to do it via GitHub's UI, but it's disabled here also.
I think keeping the history here is useful in general, so we should use yet another PR then for the squashed result (or merge it manually).

As for "WIP": I think it's good to use it via this/your branch for a while before merging.

@bluetech
Copy link
Member

As for "WIP": I think it's good to use it via this/your branch for a while before merging.

Do you mean use it in pytest or something else? If pytest, then there is not much using the stubs beyond running mypy on the code with the stubs installed, and we did do that.

Are there any other projects using py + mypy that you know about? I can check them as well.

@blueyed
Copy link
Contributor Author

blueyed commented Jan 19, 2020

As for "WIP": I think it's good to use it via this/your branch for a while before merging.

Do you mean use it in pytest or something else? If pytest, then there is not much using the stubs beyond running mypy on the code with the stubs installed, and we did do that.

Yes. But I do not think we need to merge it already, and certainly not until others agree that it should be e.g. shipped.
Having the branch here is good enough for us to help with typing pytest, and could even be used on our CI already via it - so there is no need to rush it.

Are there any other projects using py + mypy that you know about? I can check them as well.

I don't know of any.

@bluetech
Copy link
Member

Yes. But I do not think we need to merge it already, and certainly not until others agree that it should be e.g. shipped.

I suspect that with a WIP label it won't get attention by others. I think the stubs are complete, and there is not much to test beyond just using it once in pytest, so I just wonder what more you think is needed in order to get the WIP label down.

@blueyed blueyed changed the title [WIP] add stubs for typing Add stubs for typing Jan 19, 2020
@blueyed
Copy link
Contributor Author

blueyed commented Jan 19, 2020

@bluetech agreed. Not really WIP, but waiting for feedback and should not get merged as-is. I've removed the label.

@bluetech
Copy link
Member

@blueyed We should add this diff:

diff --git a/py/path.pyi b/py/path.pyi
index acbee979..2556a732 100644
--- a/py/path.pyi
+++ b/py/path.pyi
@@ -49,7 +49,7 @@ if sys.version_info >= (3, 6):
 else:
     class _PathLike(Generic[AnyStr]):
         def __fspath__(self) -> AnyStr: ...
-_PathType = Union[bytes, Text, _PathLike[Any]]
+_PathType = Union[bytes, Text, _PathLike[Any], local]
 
 class local:
     class ImportMismatchError(ImportError): ...

While I thought py.path.local would just be covered by the os.PathLike, it's not the case currently (python/typeshed#2808).

@blueyed
Copy link
Contributor Author

blueyed commented Jan 24, 2020

@bluetech ok, please push it here then - I cannot really tell/help in that regard.

@bluetech
Copy link
Member

Huh, didn't notice this PR is now based on my branch.

I pushed this and another fix.

@blueyed
Copy link
Contributor Author

blueyed commented Jan 27, 2020

@bluetech please git push bluetech 1.8.1 (i.e. the latest tag to your repo), so that setuptools-scm gets the correct/proper version.

@blueyed
Copy link
Contributor Author

blueyed commented Jan 27, 2020

You might also want to fix the conflict with appveyor.yml, so that CI runs.
Could/should also revert 66fc1bf then - I'll go ahead and do that.

@blueyed
Copy link
Contributor Author

blueyed commented Jan 27, 2020

@bluetech re the above: I do not have permission to push to this branch also (allow it via checkbox on the right?). But would still not allow me to push tags probably.

@bluetech
Copy link
Member

@blueyed done.

Do you think there is anything else blocking this PR? Should we ask anybody for additional review or +1s? py.path.local shows up everywhere in pytest, so it'd be really nice to have it :)

@blueyed
Copy link
Contributor Author

blueyed commented Jan 27, 2020

Do you think there is anything else blocking this PR?

Not really, apart from that we/you are still added fixes/improvements to it.

Should we ask anybody for additional review or +1s?

Sure.

py.path.local shows up everywhere in pytest, so it'd be really nice to have it :)

I'm going to add this branch to the "mypy" tox env, which then can be run on CI already. Having the version (tag) for it was a requirement.

@bluetech
Copy link
Member

Okay, pinging some names I recognize from the contributor's list.

@nicoddemus @RonnyPfannschmidt @asottile

This PR adds type stubs to py. The stubs only cover the modules that pytest uses, but are comprehensive and strict, otherwise. We tested pytest's typing with typed py installed and it works well. The py.typed file indicates the stubs are "partial", so projects which use modules which we didn't cover shouldn't be badly affected.

Would be great to have your +1's, unless you think this is not a good idea.

@asottile
Copy link
Member

the stubs seem fine, though for a library which is "maintenance only" I think this extends a bit beyond that -- that said it does improve pytest's ability to typecheck itself so I'm a little torn 🤔

@blueyed

This comment has been minimized.

@bluetech

This comment has been minimized.

@blueyed

This comment has been minimized.

py/path.pyi Outdated
def __fspath__(self) -> AnyStr: ...
_PathType = Union[bytes, Text, _PathLike[Any], local]

class local:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
class local:
class local(_PathLike[str]):

This would allow for pathlib.Path(py.path.local("foo")) then, where mypy currently complains:

Argument 1 to "Path" has incompatible type "local"; expected "Union[str, _PathLike[str]]" [arg-type]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that it should only accept Text in general (#238).

Copy link
Member

Choose a reason for hiding this comment

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

This would allow for pathlib.Path(py.path.local("foo")) then, where mypy currently complains:

The situation is odd. If we also do it for the real local (in the .py, not just in the .pyi) then that would remove any doubt from my mind.

For now a workaround for pathlib.Path(py.path.local("foo")) is pathlib.Path(str(py.path.local("foo"))). This is also be portable to Python<=3.5.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, the workaround is known, but currently mypy complains about something that works (with py36+).
We can leave it out for now if unclear, but should probably make it more strict to not accepts bytes?

Copy link
Member

Choose a reason for hiding this comment

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

We can leave it out for now if unclear

If we make the real local derive from os.PathLike, then it would be good to add it in the stubs too. But if not, then the stub would be sort-of lying. Although os.PathLike has a hack where isinstance(foo, os.PathLike) returns true even if foo just implements __fspath__, without deriving. So I'm not really sure.

but should probably make it more strict to not accepts bytes?

While it seems bytes support is broken, I'm sure there's someone someplace that uses it. For example #187 (comment). So again, not sure :)

Copy link
Member

Choose a reason for hiding this comment

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

An article on how pathlib (does not) handle this: https://jodal.no/2019/12/10/pathlib-and-paths-with-arbitrary-bytes/

@blueyed
Copy link
Contributor Author

blueyed commented Jan 28, 2020

commit cae97e28 (HEAD -> pyi)
Author: Daniel Hahler <git@thequod.de>
Date:   Tue Jan 28 22:14:25 2020 +0100

    path: __truediv__, __div__, join: returns local

diff --git a/py/path.pyi b/py/path.pyi
index b7879c3e..e803ada2 100644
--- a/py/path.pyi
+++ b/py/path.pyi
@@ -65,8 +65,8 @@ class local:
     def __gt__(self, other: object) -> bool: ...
     def __add__(self, other: object) -> local: ...
     def __cmp__(self, other: object) -> int: ...
-    def __div__(self, other: _PathType): ...
-    def __truediv__(self, other: _PathType): ...
+    def __div__(self, other: _PathType) -> local: ...
+    def __truediv__(self, other: _PathType) -> local: ...
     def __fspath__(self) -> str: ...

     @classmethod
@@ -132,7 +132,7 @@ class local:
     def isdir(self) -> bool: ...
     def isfile(self) -> bool: ...
     def islink(self) -> bool: ...
-    def join(self, *args: _PathType, abs: int = ...) -> Any: ...
+    def join(self, *args: _PathType, abs: int = ...) -> local: ...
     def listdir(
         self,
         fil: Optional[Union[str, Text, Callable[[local], bool]]] = ...,

@pytest-dev pytest-dev deleted a comment from codecov-io Jan 28, 2020
@codecov-io
Copy link

codecov-io commented Jan 28, 2020

Codecov Report

Merging #232 into master will not change coverage by %.
The diff coverage is 66.66%.

@@           Coverage Diff           @@
##           master     #232   +/-   ##
=======================================
  Coverage   82.06%   82.06%           
=======================================
  Files          55       55           
  Lines       10161    10161           
  Branches     1141     1141           
=======================================
  Hits         8339     8339           
  Misses       1558     1558           
  Partials      264      264           

@blueyed
Copy link
Contributor Author

blueyed commented Feb 1, 2020

@bluetech seems you've not really applied the patch? (2cf11b7 is empty)
You can cherry-pick it via cae97e2.

I guess you could also invite me as collaborator to your fork.

@bluetech
Copy link
Member

@blueyed Oops. Applied now. I also went and squashed it. I know you asked not to, but it was pretty terrible! I put the old history here: https://github.com/bluetech/py/tree/pyi-old

blueyed added a commit to blueyed/pytest that referenced this pull request Feb 20, 2020
Fixes:

> Argument 1 to "Path" has incompatible type "Union[local, Any]";
> expected "Union[str, _PathLike[str]]"  [arg-type]

Ref: pytest-dev/py#232 (review)
blueyed added a commit to pytest-dev/pytest that referenced this pull request Feb 20, 2020
Fixes:

> Argument 1 to "Path" has incompatible type "Union[local, Any]";
> expected "Union[str, _PathLike[str]]"  [arg-type]

Ref: pytest-dev/py#232 (review)
@bluetech
Copy link
Member

@asottile

the stubs seem fine, though for a library which is "maintenance only" I think this extends a bit beyond that -- that said it does improve pytest's ability to typecheck itself so I'm a little torn

Since this doesn't make any code changes, I think the risk is quite low. But I understand the hesitation.

To move this forward, maybe we can submit it to typeshed instead. @blueyed, WDYT?

@blueyed
Copy link
Contributor Author

blueyed commented Mar 1, 2020

@bluetech
From my point of view it works for me by using this branch locally and for CI.
I do not think it is "worth" adding to typeshed, given that only pytest uses it probably.
I'm not opposed to merging and properly releasing it though, of course - but cannot really tell if that implies going through extra things when updating/fixing them.

@bluetech
Copy link
Member

bluetech commented Mar 5, 2020

I see 3 options to proceed:

  1. Use py from a branch. This doesn't work for users, or official pytest CI. I think it's better to avoid this, to allow everyone to benefit.
  2. Merge this PR and release py. This is the best outcome IMO, but seems to have maintenance concerns and py is officially frozen. So probably not going to happen?
  3. Add to typeshed. I can manage and maintain it myself. Doesn't incur a maintenance burden on py itself. Typeshed is open to 3rd party stubs.

That's why going through typeshed seems like the best course to me for now. But of course I wouldn't submit it without consensus.

@RonnyPfannschmidt
Copy link
Member

im ok with option 2 in a feature release - this is clearly a help for any downstream that wants to adopt typing

@bluetech
Copy link
Member

Added a few improvements to py.xml while adding annotations to _pytest.junitxml.

@bluetech
Copy link
Member

... and squashed again.

@RonnyPfannschmidt said:

im ok with option 2 in a feature release - this is clearly a help for any downstream that wants to adopt typing

Thanks! So I guess we have +1 from @blueyed, @RonnyPfannschmidt (and me), and a -0 (?) from @asottile.

If anyone with permissions feels like merging this (and maybe releasing), that would be great.

If there will be any issues reported after releasing this, I'll make sure to handle them (I subscribed to issues on this repo).

@bluetech
Copy link
Member

bluetech commented Jun 22, 2020

There were a couple of omissions in the py.xml types, I fixed them:

  • Didn't accept py.xml.raw where it's allowed
  • Didn't accept Iterable of Tags where it's allowed

Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

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

LGTM, should we update the CHANGELOG?

Add complete type stubs to the public interface of some of `py`s
modules.

The modules are those used by `pytest`. The types are marked as partial,
so uncovered modules should be unaffected.

Co-authored-by: Ran Benita <ran@unusedvar.com>.
@bluetech
Copy link
Member

OK, I made a few updates:

  • Added CHANGELOG entry (marked for a 1.9.0)

  • Somewhat belatedly I understood that partial in py.typed doesn't do what I thought it does, so I removed it and added explicit Anys for all of the types & modules we didn't cover.

  • Made py.path.local explicitly inherit from os.PathLike because it is actually not defined as a Protocol in typeshed. This fixes pathlib.Path(py.path.local()) (at least on Python>=3.6).

Finally, pytest master is currently completely clean with this PR.

So I think this is ready.

@nicoddemus
Copy link
Member

Awesome! Let's merge and release this then!

@nicoddemus nicoddemus merged commit c869d32 into pytest-dev:master Jun 24, 2020
@bluetech bluetech deleted the pyi branch December 12, 2020 11:54
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.

None yet

6 participants