How to prevent inserting a record different from the model in python
Question: I have a data model that have some primitive and array type properties as
shown below:

    
    
    class WordCollection:
        """First model"""
        def __init__(self, **properties):
            self.name = ""
            self.status = CommonStatus.active
            self.expire_time = time.time() + 1000 * 60 * 24  # after 1 day
            self.created_date = time.time()
            self.words = []
            self.__dict__.update(properties)
    

That comes some hack. For example when i construct the class with a property
which is not part of the class it could be easily hacked.

    
    
    collection = WordCollection(**{..., "hack_property":"large text or irrelative data"})
    

So i've played on class initialize method:

    
    
    class WordCollection:
            """Second model"""
            def __init__(self, **properties):
                self.name = properties["name"] if "name" in properties else ""
                self.status = properties["active"] if "active" in properties else CommonStatus.active
                self.expire_time = properties["expire_time"] if "expire_time" in properties else time.time() + 1000 * 60 * 24  # after 1 day
                self.created_date = properties["created_date"] if "created_date" in properties else time.time()
                self.words = properties["words"] if "words" in properties else []
    

But above code does not solve the problem in full:

    
    
    collection = WordCollection(**{..., "name":{"hack_property":"large text or irrelative data"}})
    

This is the last rebuilt code:

    
    
        class WordCollection:
            """Third Model"""
            def __init__(self, **properties):
                self.name = properties["name"] if "name" in properties and isinstance(properties["name"], str) else ""
                self.status = properties["active"] if "active" in properties \
                                                      and isinstance(properties["status"], int) else CommonStatus.active
                ....
    

Above revision solves my problem but it brings conditional complexity and i
believe that would be better solution than aboves.


Answer: A more standard formulation:

    
    
    valid_properties =  {'prop1', 'prop2', 'prop3'}
    class WordCollection(object):
        def __init__(self, name="", status=None; **properties):
            # This one is explicit, with a default that is specified in the call signature
            # Defaults in the call signature are resolved when the class is imported
            self.name = name
            # This one is more dynamic - CommonStatus.active could change
            # after the user imports the class, so we don't want it fixed.
            # Instead, use a sentinel.
            # I usually use None. If None is a valid value, best bet
            # is to do something like this:
            # sentinel = object()
            # then use that instead of None.
            self.status = CommonStatus.active if status is None else status
            # This one we just assign - 
            self.words = []
            # You don't _have_ to include a **kwargs if you don't want to.
            # If you don't want _any_ surprise properties, just leave
            # **properties out of the __init__, and only ones you explicit
            # declare will be allowed.
            # Explicit is better - they show up in tab completion/help
            # But if you want to filter out input to a set of valid props...
            filtered_props = {k:v for k,v in properties.items() if k in valid_properties}
            self.__dict__.update(filtered_props)
    

