-
Notifications
You must be signed in to change notification settings - Fork 19
Make project compatible with Python 3.7+ #37
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
Conversation
So far, it's a lot of find-and-replace work. I have replaced the types, but |
On error, the older versions of argparse call the error() method, which is already overridden in a way that we like. So, to fix the tests, we just do not provide the parameter to the constructor on older Python versions.
Alright, I have resolved almost everything that needed to be resolved. There is one last problem, though. The test @SupImDos any ideas what we can do here? I propose adding a default class SubParsersAction(argparse._SubParsersAction):
+ def __init__(self, *args, **kwargs):
+ kwargs.setdefault("metavar", "COMMAND")
+ super().__init__(*args, **kwargs) Basically, this would be analogue to this: parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(metavar="COMMAND", required=True)
test_sub = subparsers.add_parser("test")
test_sub.add_argument("--flag", type=bool, default=False) $ python3.7 parsing.py --help
usage: parsing.py [-h] COMMAND ...
positional arguments:
COMMAND
optional arguments:
-h, --help show this help message and exit
$ python3.7 parsing.py
usage: parsing.py [-h] COMMAND ...
parsing.py: error: the following arguments are required: COMMAND The same code under Python 3.7, but without metavar$ python3.7 parsing.py --help
usage: parsing.py [-h] {test} ...
positional arguments:
{test}
optional arguments:
-h, --help show this help message and exit
$ python3.7 parsing.py
Traceback (most recent call last):
File "parsing.py", line 9, in <module>
parser.parse_args()
File "/Users/nikita/.pyenv/versions/3.7.16/lib/python3.7/argparse.py", line 1755, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "/Users/nikita/.pyenv/versions/3.7.16/lib/python3.7/argparse.py", line 1787, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "/Users/nikita/.pyenv/versions/3.7.16/lib/python3.7/argparse.py", line 2022, in _parse_known_args
', '.join(required_actions))
TypeError: sequence item 0: expected str instance, NoneType found |
@kytta 1. Minor Type Checking ErrorLooks like we might need to add a - setattr(namespace, self.dest, not option_string.startswith('--no-'))
+ setattr(namespace, self.dest, not option_string.startswith('--no-')) # type: ignore[union-attr] 2. Argparse SubParser Backport BugHmm this is an interesting one. Ideally I would like to keep the same behaviour (i.e., show the different command options across the different versions. i.e., $ python examples/commands.py
usage: Example Program [-h] [-v] [--verbose] {build,serve} ...
Example Program: error: the following arguments are required: {build,serve} I can think of a few things we can do:
@kytta I think at the moment I prefer (3). What do you think? |
Yup, done!
This would be my favourite way to do this, but I understand that having every command as a metavar is more helpful than just
Too messy, such that the code becomes less readable.
I am usually not a fan of monkey patching module functions, but this is pretty clean, and we can turn it off on newer Python versions with
Yeah, let's do that. |
@SupImDos another thing I wanted to ask: How do you like
I like the (1) better, as it allows us to ship less dependencies to the most users (as I don't think that many people use Python 3.7 in production, especially for command-line-apps). It is also very easy to remove later with pyupgrade. But the code is cleaner with the second option 🤔 |
This feels like the correct way to do it. As you say, it allows us to ship less dependencies to the most users.
Less code branching is a lot cleaner and it is tempting. But I think (1) is still better in a practical sense. @kytta I agree with you that we should go with (1) 😃 I am interested to see how the code coverage is calculated with branches that only execute in certain Python versions. We will have to see 🤔 |
This is also an interesting moment. A while ago I have noticed the comment Now, I have tried to also use it here (see commit c2bcc6c), but it didn't work (at least locally). For me, I then tried to look this pragma up, but neither coverage nor pytest-cov docs mention anything other than If we can't get this to work, I propose setting |
@kytta I had a look at your I think this works?
Does this sound right? What do you think? |
Oh right, I completely forgot about this package! Yeah, this looks good, I'll add this to pyproject.toml |
@kytta
You're right, I would be happy with a I'll do my best to review this properly as soon as I can 😃 |
Alright, should be done now! All checks run fine on my machine 👌🏻 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks again for all this work!
Closes #35