Skip to content

Conversation

voidus
Copy link

@voidus voidus commented Feb 20, 2025

Running procrastinate subcommands when configurations is installed gives the following error:

> ./manage.py procrastinate healthchecks
Adding tasks from blueprint
Adding tasks from blueprint
healthchecks() got an unexpected keyword argument 'configuration'

The monkey-patching in create_parser caused this in an interesting way:

Procrastinate uses the add_arguments hook to check the previously defined arguments like this:

class Command(BaseCommand):
    def add_arguments(self, parser):
      self._django_options = {a.dest for a in parser._actions}
      ...

in order to later filter them out like this:

  def handle(self, *args, **kwargs):
    ...
    kwargs = {k: v for k, v in kwargs.items() if k not in self._django_options}
    ...

This is a problem because the CONFIGURATION_ARGUMENT arg is added after procrastinate's add_arguments is called. Here's the call graph:

  create_parser (django-configurations)
  -> create_parser (django) (a.k.a. orig_create_parser)
    -> add_arguments (procrastinate)
    -> (CONFIGURATION_ARGUMENT added here)

This commit esesentially swaps the inner two actions so it looks like this:

  create_parser (django-configurations)
  -> create_parser (django) (a.k.a. orig_create_parser)
    -> (CONFIGURATION_ARGUMENT added here)
    -> add_arguments (procrastinate)

It does this by temporarily overriding add_arguments with a no-op and then later restoring and calling it.

This is a hack on top of two hacks, but I can't really see any other ways to make it work.

This monkey-patching broke procrastinate in an interesting way:

Procrastinate uses the add_arguments hook to check the previously
defined arguments like this:

```python
class Command(BaseCommand):
    def add_arguments(self, parser):
      self._django_options = {a.dest for a in parser._actions}
      ...
```

in order to later filter them out like this:

```python
  def handle(self, *args, **kwargs):
    ...
    kwargs = {k: v for k, v in kwargs.items() if k not in self._django_options}
    ...
```

This is a problem because the CONFIGURATION_ARGUMENT arg is added
*after* procrastinate's `add_arguments` is called. Here's the call
graph:

```
  create_parser (django-configurations)
  -> create_parser (django) (a.k.a. orig_create_parser)
    -> add_arguments (procrastinate)
    -> (CONFIGURATION_ARGUMENT added here)
```

This commit esesentially swaps the inner two actions so it looks like
this:

```
  create_parser (django-configurations)
  -> create_parser (django) (a.k.a. orig_create_parser)
    -> (CONFIGURATION_ARGUMENT added here)
    -> add_arguments (procrastinate)
```

It does this by temporarily overriding `add_arguments` with a no-op and
then later restoring and calling it.

This is a hack on top of two hacks, but I can't really see any other
ways to make it work.
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.

1 participant