{{{#!python
class Command(BaseCommand):
def add_arguments(self, parser) -> None:
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--for', dest='until', action='store',
type=parse_duration_to_time)
group.add_argument('--until', action='store', type=parse_time)
def handle(self, until: datetime, **_):
pass
}}}
This works fine on the command line, however there doesn't seem to be a
way to make this work through `call_command`. Specifically there are two
sides to the failure:
- while I can provide an `until` value (as a string, which is processed by
`parse_time`) there is no mechanism to pass a `for` value if that's how I
want to spell the input
- the `for` value is always required and attempts to parse the (string)
`until` value passed, which then errors since the input formats are very
different
--
Ticket URL: <https://code.djangoproject.com/ticket/33205>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: Hasan Ramezani (added)
* type: Uncategorized => Bug
* component: Uncategorized => Core (Management commands)
* stage: Unreviewed => Accepted
Comment:
Thanks for the report. The following calls work as expected for me :
{{{#!python
management.call_command('pause', '--until=1')
management.call_command('pause', '--until', '1')
management.call_command('pause', '--for=1')
management.call_command('pause', '--for', '1')
}}}
however I confirmed an issue when passing arguments in keyword arguments:
{{{
management.call_command('pause', until='1')
management.call_command('pause', **{'for': '1'}) # Using
"call_command('pause', for='1')" raises SyntaxError
}}}
This is caused by using `dest` for mapping `**options` to arguments, see
[https://github.com/django/django/blob/e2f778d57947d168a875159e6df075255eea4bbc/django/core/management/__init__.py#L117-L121
call_command()].
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:1>
Comment (by Hasan Ramezani):
I can create a patch to fix the two above-mentioned issues but using the
command with both options together:
`management.call_command('pause', **{'for': '1', 'util': '1'})`
won't raise an error because both options use the same `dest`.
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:2>
Comment (by Peter Law):
Ah, interesting, I wasn't aware that those other spellings worked! I'd be
happy to switch to using those spellings instead (I've confirmed they work
for my original case).
Perhaps just documenting this limitation (and the fact that those
spellings work as alternatives) and/or improving the related error
messages could be a way to go here?
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:3>
Comment (by Mariusz Felisiak):
Replying to [comment:2 Hasan Ramezani]:
> I don't know do we have to support passing both dest and arg name as
keyword arguments? in the example of this ticket, if we call
`management.call_command('pause', until='1')`, it should be considered as
`until` arg or `for` (because `dest` of `for` is `until` as well)
We should support option names as
[https://docs.djangoproject.com/en/3.2/ref/django-
admin/#django.core.management.call_command documented]:
> `** options`
> named options accepted on the command-line.
so
* `management.call_command('pause', until='1')` should work the same as
calling `pause --until 1`
* `management.call_command('pause', **{'for': '1'})` should work the same
as calling `pause --for 1`
* `management.call_command('pause', **{'for': '1', 'until': '1'})` should
work the same as calling `pause --for 1 --until 1` and raise an exception
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:4>
Comment (by Hasan Ramezani):
Replying to [comment:4 Mariusz Felisiak]:
I am not sure about your second example:
> * `management.call_command('pause', **{'for': '1'})` should work the
same as calling `pause --for 1`
Based on the documentation, it seems we have to pass `dest` as keyword
argument name when we define `dest` for arguments.
>Some command options have different names when using call_command()
instead of django-admin or manage.py. For example, django-admin
createsuperuser --no-input translates to call_command('createsuperuser',
interactive=False). To find what keyword argument name to use for
call_command(), check the command’s source code for the dest argument
passed to parser.add_argument().
Also, when Django
[https://github.com/django/django/blob/e2f778d57947d168a875159e6df075255eea4bbc/django/core/management/__init__.py#L149
adds required arguments in call command], it search for `dest` in options.
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:5>
Comment (by Mariusz Felisiak):
You're right, sorry, I missed ''"... check the command’s source code for
the **dest** argument passed to parser.add_argument()."''. In that case I
would raise an error that passing `dest` with multiple arguments via
`**options` is not supported.
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:6>
* owner: nobody => Hasan Ramezani
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:7>
* has_patch: 0 => 1
Comment:
[https://github.com/django/django/pull/15018 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:8>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:9>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"c1e4111c74ee9d9f48cbee5a5b7c40289203c93d" c1e4111c]:
{{{
#!CommitTicketReference repository=""
revision="c1e4111c74ee9d9f48cbee5a5b7c40289203c93d"
Fixed #33205 -- Made call_command() raise TypeError when dest with
multiple arguments is passed.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:10>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"c9ebe4ca4e3f5d5d76bfbdae489e3f44e32416e5" c9ebe4ca]:
{{{
#!CommitTicketReference repository=""
revision="c9ebe4ca4e3f5d5d76bfbdae489e3f44e32416e5"
[4.0.x] Fixed #33205 -- Made call_command() raise TypeError when dest with
multiple arguments is passed.
Backport of c1e4111c74ee9d9f48cbee5a5b7c40289203c93d from main
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33205#comment:11>