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
            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
                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")


            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:

Traceback (most recent call last):
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\bf_app\tests\", line 26, in test_transaction_has_owner
    transaction = TransactionFactory(owner=user)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 40, in __call__
    return cls.create(**kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 528, in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 117, in _generate
    return super()._generate(strategy, params)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 465, in _generate
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 262, in build
    instance = self.factory_meta.instantiate(
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 317, in instantiate
    return self.factory._create(model, *args, **kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\factory\", line 166, in _create
    return manager.create(*args, **kwargs)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\", 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\", line 514, in create, using=self.db)
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\", line 806, in save
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\db\models\", line 872, in save_base
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\dispatch\", line 176, in send
    return [
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\venv\lib\site-packages\django\dispatch\", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "C:\Users\Mitchell\PycharmProjects\BudgieFinance_TW\bf_app\", 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.


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!