Skip to content

Add Capturable* argparse structures to mypy.main #7804

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

Merged
merged 1 commit into from
Oct 29, 2019

Conversation

dmtucker
Copy link
Contributor

Fix #7800

Most of this code is yanked from the standard library since the same behaviors are desired, just with plumbing for stdout/stderr. One difference of note is that version is mandatory in CapturableVersionAction.__init__ to get around this error:

mypy/main.py:339: error: "ArgumentParser" has no attribute "version"  [attr-defined]
                version = parser.version
                          ^

I'm unaware of a situation where that line wouldn't raise an AttributeError 🤔
Anyways, I didn't want to patch sys.stdout/sys.stderr in order to avoid reintroducing #6125.

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks! It looks like this is the most reasonable way of doing this, even though there's quite a bit of boilerplate involved. Generally looks good, just some minor nits.

def test_capture_bad_opt(self) -> None:
"""stderr should be captured when a bad option is passed."""
_, stderr, _ = mypy.api.run(['--some-bad-option'])
assert stderr != ''
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also test that the return value is a string, as otherwise the inequality will be trivially true. This might happen if it's None, at least. Maybe like this: assert isinstance(stderr, str) and stderr != ''

def test_capture_empty(self) -> None:
"""stderr should be captured when a bad option is passed."""
_, stderr, _ = mypy.api.run([])
assert stderr != ''
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar to above.

def test_capture_help(self) -> None:
"""stdout should be captured when --help is passed."""
stdout, _, _ = mypy.api.run(['--help'])
assert stdout != ''
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar to above.

def test_capture_version(self) -> None:
"""stdout should be captured when --version is passed."""
stdout, _, _ = mypy.api.run(['--version'])
assert stdout != ''
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar to above.

self.exit(2, gettext('%(prog)s: error: %(message)s\n') % args)


class CapturableVersionAction(argparse.Action):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add docstring (maybe refer to the docstring that I requested for CapturableArgumentParser).

@@ -252,6 +257,89 @@ def infer_python_executable(options: Options,
Define MYPY_CACHE_DIR to override configuration cache_dir path.""" # type: Final


class CapturableArgumentParser(argparse.ArgumentParser):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add docstring that explains what this does and why we need to do this.

mypy/main.py Outdated

def __init__(self, *args: Any, **kwargs: Any):
try:
self.stdout = kwargs.pop('stdout')
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe you can avoid the try statements by using kwargs.pop('stdout', sys.stdout) (and similarly for stderr).

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks for the updates! Looks good now.

@JukkaL JukkaL merged commit dec5451 into python:master Oct 29, 2019
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.

stderr is not always captured by mypy.api.run
2 participants