Reputation: 41
I am trying to use property decorator to validate python object.
Following is my class
'''Contains all model classes. Each class corresponds to a database table'''
from validation import company_legal_type, max_len
class Company():
'''A class to represent a company and its basic information'''
def __init__(self, ref, name, currency, legal_type, business):
self._ref = int(ref)
self._name = name
self._currency = str(currency) # i.e. The functional currency
self._legal_type = str(legal_type)
self._business = str(business)
def __str__(self):
return f"Company object for '{self._name}'"
# Validate object attributes
@property # Prevents change to ref after company object has been created
def ref(self):
return self._ref
@property # The following two functions permit changes but set validation checks for name
def name(self):
return self._name
@name.setter
def name(self, value):
if type(value) != str:
raise TypeError("Company name must be a string.")
if len(value) > max_len['company_name']:
raise ValueError(f"Company name must not be longer than {str(max_len['company_name'])} characters.")
Following is validation.py
# data length validation
max_len = {
'company_name': 200,
'company_business': 200,
}
And finally here is how I am using the class:
# Import custom modules
from models import Company, Currency
company = Company(23, 'ABC Limited', 'PKR', 'pvt_ltd', 'manufacturing')
company.name = 'ABCD Limited'
print(company.name)
This prints 'ABC Limited' instead of 'ABCD Limited'.
If I break a validation condition like use an integer instead of a string when updating company.name, it correctly results in an error. But if I break it when creating the object, no error is raised.
What am I doing wrong?
Upvotes: 0
Views: 428
Reputation: 95873
The problem is your setter doesn't set anything. It merely raises errors on bad input. So you have to actually set something, or else how do you expect it to modify self._name
? So:
@name.setter
def name(self, value):
if type(value) != str:
raise TypeError("Company name must be a string.")
if len(value) > max_len['company_name']:
raise ValueError(f"Company name must not be longer than {str(max_len['company_name'])} characters.")
self._name = value
If I break a validation condition like use an integer instead of a string when updating company.name, it correctly results in an error. But if I break it when creating the object, no error is raised.
Because you don't use the property in __init__
. Generally if you have validation property setters, you want to use those in __init__
. So your __init__
should be something like:
def __init__(self, ref, name, currency, legal_type, business):
self._ref = int(ref)
self.name = name
self._currency = str(currency) # i.e. The functional currency
self._legal_type = str(legal_type)
self._business = str(business)
Upvotes: 2