Keywords Must Be Strings When Passing Variable As Parameter

I’m trying to pass a variable as a keyword argument like this:

@receiver(post_save, sender=BudgetTransaction)
def create_forecasted(sender, instance, created, **kwargs):
    if instance.transaction_type == "EC":
        return True

    if created:
        today = instance.next_date
        last_day = date(today.year, 12, 31)
        this_month = today.month
        weeks_left = int((last_day - today).days / 7)
        fortnights_left = int(weeks_left / 2)
        months_left = 12 - this_month

        if instance.frequency == 'weeks':
            create_range = weeks_left
        elif instance.frequency == 'fort':
            create_range = fortnights_left
        else:
            create_range = months_left

        loop = 1
        for i in range(create_range):
            if instance.frequency == 'fort':
                true_frequency = 'weeks'
                true_loop = loop * 2
            elif instance.frequency == '4week':
                true_frequency = 'weeks'
                true_loop = loop * 4
            else:
                true_frequency = instance.frequency
                true_loop = loop


            ### PASSING VARIABLE HERE ###
            next_month = today + relativedelta(**{true_frequency: true_loop})
            date_string = next_month.strftime("%Y-%m-%d")

            BudgetTransaction.objects.bulk_create([BudgetTransaction(
                owner=instance.owner,
                transaction_amount=instance.transaction_amount,
                transaction_name=instance.transaction_name,
                transaction_type=instance.transaction_type,
                next_date=date_string,
                frequency=instance.frequency,
            )])

            loop += 1

This is for a django site and it doesn’t error when I run this through the site. However, when I run a test I’m getting this error:

Error
Traceback (most recent call last):
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\bf_app\tests\test_models.py", line 26, in test_transaction_has_owner
    transaction = TransactionFactory(owner=user)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\base.py", line 40, in __call__
    return cls.create(**kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\base.py", line 528, in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\django.py", line 117, in _generate
    return super()._generate(strategy, params)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\base.py", line 465, in _generate
    return step.build()
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\builder.py", line 262, in build
    instance = self.factory_meta.instantiate(
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\base.py", line 317, in instantiate
    return self.factory._create(model, *args, **kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\django.py", line 166, in _create
    return manager.create(*args, **kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\query.py", line 514, in create
    obj.save(force_insert=True, using=self.db)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\base.py", line 806, in save
    self.save_base(
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\base.py", line 872, in save_base
    post_save.send(
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\dispatch\dispatcher.py", line 176, in send
    return [
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\dispatch\dispatcher.py", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\bf_app\models.py", line 82, in create_forecasted
    next_month = next_date + relativedelta(**{true_frequency: true_loop})
TypeError: keywords must be strings

I’m not entirely sure how to solve this as I’ve never passed a keyword as a variable before so I’m not overly familiar with the process. This is happening on a receiver object.

Thanks

I’d throw a couple print statements in there before that line to print true_frequency and type(true_frequency) to ensure you’ve got valid data at that location for that specific test.
(My first inclination is to think that you may have a case where instance.frequency may be None.)

That was exactly the issue! Thanks!