pythonponyorm

AttributeError: Can't set attribute - How can I fix it?


I am working on developing tests with pytest, but I am encountering the AttributeError: can't set attribute.

This is the model:

class User(UserMixin, db.Entity):
   _table_ = 'users'
   email = Required(str, unique=True)
   username = Required(str, unique=True)
   password_hash = Optional(str)
   pretax_income = Optional(Decimal, default=110000)
   tax_rate = Optional(Decimal, default=0.1)

   @property
   @db_session
   def monthly_income(self):
      return round(self.pretax_income/12, 2)

   @property
   @db_session
   def post_tax_income(self):
      return round(self.pretax_income - (self.pretax_income * self.tax_rate), 2)

  @property
  @db_session
  def post_tax_income_monthly(self):
      return round(self.post_tax_income / 12, 2)

And this is where I am doing the tests, from which the first 2 work fine. The last one testing the monthly post tax income gets the error about setting the attribute.

class TestCalculator:

@db_session
def test_calc_monthly_income(self):
    user = User.get(email='test@test.com')
    user.pretax_income = 12000
    assert user.monthly_income == Decimal('1000')
    user.pretax_income = 48000
    assert user.monthly_income== Decimal('4000')

@db_session
def test_calc_post_tax_income(self):
    user = User.get(email='test@test.com')
    user.pretax_income = 120000
    user.tax_rate = 0.1
    assert user.post_tax_income == 108000
    user.pretax_income = 90000
    user.tax_rate = 0.2
    assert user.post_tax_income == 72000

@db_session
def test_calc_post_tax_income_monthly(self):
    user = User.get(email='test@test.com')
    user.post_tax_income = 36000
    assert user.post_tax_income_monthly == Decimal('3000')
    user.post_tax_income = 60000
    assert user.post_tax_income_monthly == Decimal('5000')

Update: I tried to add a setter in this way. Clearly, I am doing it wrong.

   @post_tax_income.setter
@db_session
def set_post_tax_income(self):
    self.post_tax_income = post_tax_income

Solution

  • @property
    @db_session
    def post_tax_income(self):
      return round(self.pretax_income - (self.pretax_income * self.tax_rate), 2)
    

    this defines only a getter. It allows you fetch the value but you can't do this:

    user.post_tax_income = 36000
    

    This requires a setter to also be defined:

    @post_tax_income.setter
    def set_post_tax_income(self):
      ...