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
mgr_module.py: make keyword style argument passing explicit #36910
Conversation
jenkins render docs |
Doc render available at http://docs.ceph.com/ceph-prs/36910/ |
interesting. those calls are missing from https://docs.ceph.com/ceph-prs/36910/api/mon_command_api/ |
what I still don't quite understand is:
already works. But I mean, I can still say:
|
Looks like commands that are setup via the CLICommand decorator (or its variants) are just not extracted. E.g all |
Unfortunaltey things can't look quite like this. The command would be
Right, that will still work. I'd be up for adding a |
Hmm seems like ceph_argparse.py needs a change as well. Looking into it. |
Instead of assuming a kwarg when a '=' is encountered, this commit changes the CLICommand decorator to require an explicit 'kw=true' specification in a command definition to add the option to parse it as a kwarg. Arguments marked with kw=true can either be passed kwarg style (arg_name=value) or as a positional argument. Once a kwarg style argument was seen, the following ones must not be passed as positionals. Signed-off-by: Jan Fajerski <jfajerski@suse.com>
When setting up the module commands we can warn if the developer defined a positional after a keyword argument. Signed-off-by: Jan Fajerski <jfajerski@suse.com>
Signed-off-by: Jan Fajerski <jfajerski@suse.com>
5331811
to
225e6ce
Compare
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.
I think the idea makes sense, especially given that the support already exists but the current implementation seems broken due to assuming any =
will be handled as the separator for a key/value pair.
I do have a few comments on the approach though.
@@ -299,6 +300,12 @@ def _parse_args(self): | |||
arg_d[k] = v | |||
else: | |||
self.args_dict[v] = arg_d | |||
if k == 'kw' and v == 'true': |
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.
I find the kw
keyword a bit too weird, especially since we're then dropping "kwarg" terms bellow. I find going with something a bit more descriptive (especially since we're using this on the CLI descriptor) would be ideal. Something like "requires_args" or "with_map_args". More to type, but I'm sure with a bit of creativity we can find a better keyword ;)
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.
maybe k/v
argument? kv_arg?
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.
kw
stands for keyword, borrowed from pythons keywords arguments. kwarg
might be better and should be familiar to python developers.
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.
but if we are exposing kw
as a thing to the user (like we do on returning EINVAL later in the patch), this is no longer just for developer consumption and, I'd say, a more relatable term might be better.
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.
Yeah fair point.
else: | ||
if kwargs_switch: | ||
# we saw a kwarg earlier and now a positional | ||
logging.warn('Found positional argument after kwarg') |
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.
is there a reason why we'd warn about positional arguments after a k/v pair was found? I don't see a particular technical difficulty in handling them, especially since we know which arguments are expected to be k/v pairs.
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.
Here (while setting up the command and argument structures) I only warn since the kw=true
currently enables optional passing as a kwarg. The user can also pass the arguments as positional arguments.
if not kwargs_switch and isinstance(cmd_dict[a], str) and '=' in cmd_dict[a]: | ||
# We consider this a kwarg. Set the switch so that all | ||
# future args are parsed as kwargs too. | ||
mgr.log.debug('Seen a kwarg, assuming all following args are kw style') |
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.
I asked this above, but is there a technical reason why we can't handle positional arguments after k/v pairs?
We're not even allowing spaces between the key portion, the equal sign, and the value portion, so we're not actually dealing with 3 arguments in the CLI, just the one. Why not allowing other arguments to come after?
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.
The reasoning is that once we have seen a kwarg and it is followed by a positional, we don't know what that positional argument is (since it is identified by its position in the arg list). This is consistent with python behaviour.
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.
I see the point, but aren't these being pre-handled by argparse so that they arrive as a dictionary as is? IIRC, and I may be conflating argparse and command parsing in the mgr module, arguments are identified by their dictionary k/v pairs rather than list positional arguments; no?
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.
Once we're in mgr module land, yes, we have the dict. But the dict is filled by position on the command line iiuc. But I need to look closer into ceph_argparse, the kwargs parsing should probably happen there.
Okay, crazy idea: why not implementing this as a new type for argparse, such that you can have a map type? |
The argparse types are value types. We want to use those for positionals as well as kwarg style. I realise that in order to use the kwarg style they argument currently has to be a |
This pull request has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs for another 30 days. |
This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved |
relates to https://tracker.ceph.com/issues/50954 |
Doc render available at https://ceph--36910.org.readthedocs.build/en/36910/ |
superseded by #41509? |
This PR changes the recent addition to CLICommand to support kwargs style passing. With this a module author has to explicitly mark arguments that can be passed with a keyword.
Checklist
Show available Jenkins commands
jenkins retest this please
jenkins test classic perf
jenkins test crimson perf
jenkins test signed
jenkins test make check
jenkins test make check arm64
jenkins test submodules
jenkins test dashboard
jenkins test api
jenkins test docs
jenkins render docs
jenkins test ceph-volume all
jenkins test ceph-volume tox