Skip to content

Change scandir() to type as both iterator and context-manager #1583

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

Closed
wants to merge 3 commits into from
Closed

Change scandir() to type as both iterator and context-manager #1583

wants to merge 3 commits into from

Conversation

cricalix
Copy link

@cricalix cricalix commented Aug 30, 2017

Summary:
The existing typing for scandir() assumes it can only be an iterator. It can also be used as a context manager per the documentation, and typing fails when used as part of mypy-0.530.

Hat-tip to a colleague, M. Pieters, for the guidance on how to do this.

Filed as issue #1573

Test Plan:
Wrote a small snippet of code that implements the context manager usage.
Ran stock mypy against that code, got warnings about exit and enter.
Ran amended mypy (ie, with this typing included) against that code, got no warnings.

Snippet:

    def _find_files(base: str, directory: str) -> List[str]:
        with os.scandir(os.path.join(base, directory)) as it:
            for dirent in it:
                pass

Summary:
The existing typing for scandir() assumes it can only be an iterator. It can also be used as a context manager per the documentation, and typing fails when used as part of mypy-0.530.

Hat-tip to a colleague, M. Pieters, for the guidance on how to do this.

Test Plan:
Wrote a small snippet of code that implements the context manager usage.
Ran stock mypy against that code, got warnings about exit and enter.
Ran amended mypy (ie, with this typing included) against that code, got no warnings.
def __next__(self) -> DirEntry[str]: ...
def __enter__(self: _T) -> _T: ...
def __exit__(self, exc_type: Optional[type], exc_val: Optional[Exception],
exc_tb: Optional[TracebackType]) -> bool: ...
@overload
def scandir() -> Iterator[DirEntry[str]]: ...
Copy link
Member

Choose a reason for hiding this comment

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

Why is this overload unaffected?

@@ -343,10 +344,16 @@ if sys.version_info >= (3, 3):
def replace(src: _PathType, dst: _PathType) -> None: ...
def rmdir(path: _PathType) -> None: ...
if sys.version_info >= (3, 6):
class ScandirIterator(Iterable):
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be generic in AnyStr (so inherit from Iterable[AnyStr], and then change all the str below to AnyStr.

Copy link
Member

Choose a reason for hiding this comment

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

Also, the name should be prefixed with _ because this name is not publicly exported in the os module.

class ScandirIterator(Iterable):
def __iter__(self) -> Iterator[DirEntry[str]]: ...
def __next__(self) -> DirEntry[str]: ...
def __enter__(self: _T) -> _T: ...
Copy link
Member

Choose a reason for hiding this comment

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

Instead of _T, use a special type variable with bound=ScandirIterator[AnyStr].

def __iter__(self) -> Iterator[DirEntry[str]]: ...
def __next__(self) -> DirEntry[str]: ...
def __enter__(self: _T) -> _T: ...
def __exit__(self, exc_type: Optional[type], exc_val: Optional[Exception],
Copy link
Member

Choose a reason for hiding this comment

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

exc_type should be Optional[Type[BaseException]] and exc_val should be Optional[BaseException].

@cricalix
Copy link
Author

cricalix commented Sep 2, 2017

Ack requested changes. I'm going off-grid for a week, will come back to this when I'm back from holiday.

@JelleZijlstra JelleZijlstra self-assigned this Sep 23, 2017
@JelleZijlstra
Copy link
Member

Any updates?

JelleZijlstra added a commit to JelleZijlstra/typeshed that referenced this pull request Dec 15, 2017
@JelleZijlstra
Copy link
Member

JelleZijlstra commented Dec 15, 2017

I reimplemented the change in #1787 since the author of this PR is AWOL.

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.

3 participants