Skip to content

Instantly share code, notes, and snippets.

@mkorkmaz
Last active March 15, 2016 06:09
Show Gist options
  • Save mkorkmaz/f50c4f5d083b456c5bd7 to your computer and use it in GitHub Desktop.
Save mkorkmaz/f50c4f5d083b456c5bd7 to your computer and use it in GitHub Desktop.
A simple python class for validating, variable type fixing and setting defaults for a model definition encoded as a dict. It may be useful when you use schemaless databases.
#!/usr/bin/env python3.5
# -*- coding: utf-8 -*-
# author: [email protected]
# created: 2016-03-11
# A simple class for validating, variable type fixing and setting defaults
# for a model definition encoded as a dict
class ModelUtils:
def __init__(self):
self.__ver = "0.0.1"
# Validate a dict whether if it has a wrong variable type or not.
# If there is at least one variable with a wrong type, raise an exception.
def validate_dict(self, my_model, my_dict, my_key=False):
my_keys = list(my_dict.keys())
for key in my_keys:
# Does dict has a key that does not exist in model definition.
if key not in my_model:
if my_key is not False:
my_key = str(my_key)+"."+str(key)
else:
my_key = key
raise Exception("Error for key '" + my_key + "' that does not exist in the model")
# Is the value of the dict[key] again another dict?.
elif my_dict[key].__class__ is dict:
if my_key is not False:
my_key = str(my_key) + "." + str(key)
else:
my_key = key
# Validate this dict too.
my_dict[key] = self.validate_dict(my_model[key], my_dict[key], my_key)
if my_dict[key].__class__ is not dict:
return my_dict[key]
# Does the value of the dict[key] have same variable type that stated in the definition of the model dict.
elif my_dict[key].__class__ is not my_model[key]['_type'].__class__:
if my_key is not False:
my_key = my_key+"."+key
else:
my_key = key
raise Exception("Error for key '" + my_key + "'" + ", " + str(my_dict[key].__class__) +
" given but it must be " + str(my_model[key]['_type'].__class__))
return my_dict
# Fix the values of the dict according to model definition.
# If the value of the dict has wrong variable types, fix it.
# If dict has a key that is not presented in the model definition unset it.
def fit_dict_to_model(self, my_model, my_dict):
my_keys = list(my_dict.keys())
for key in my_keys:
# If dict has a key that is not presented in the model definition, unset it.
if key not in my_model:
my_dict.pop(key, None)
# If dict[key] is again a dict, recursively fit this dict too.
elif my_dict[key].__class__ is dict:
my_dict[key] = self.fit_dict_to_model(my_model[key], my_dict[key])
# If returned value is not a dict, return it.
if my_dict[key].__class__ is not dict:
return my_dict[key]
# If dict[key] is not a dict and not has same variable type that stated in the model definition.
elif my_dict[key].__class__ is not my_model[key]['_type'].__class__:
if my_model[key]['_type'].__class__ is int:
my_dict[key] = int(my_dict[key])
elif my_model[key]['_type'].__class__ is float:
my_dict[key] = float(my_dict[key])
elif my_model[key]['_type'].__class__ is complex:
my_dict[key] = complex(my_dict[key])
elif my_model[key]['_type'].__class__ is str:
my_dict[key] = str(my_dict[key])
return my_dict
# Fix if dict has a wrong variable type according to model definition.
# If dict does not have keys that model definition has, set them as default values.
# If dict has a key that model definition does not have, unset it.
def defaults_with_model(self, my_model, my_dict):
my_keys = list(my_model.keys())
new_dict = {}
for key in my_keys:
item_keys = list(my_model[key].keys())
# If one of the keys of my_model[key] is _type this is a definition, not a defined key
if "_type" in item_keys:
# If dict does not have this key, set the default value.
if key not in my_dict:
new_dict[key] = my_model[key]['_default']
# If dict has this key
else:
# If model definition stated this key's default value is not None
# and has a wrong variable type, fix it.
if my_model[key]['_default'] is not None:
if my_model[key]['_type'].__class__ is int:
new_dict[key] = int(my_dict[key])
elif my_model[key]['_type'].__class__ is float:
new_dict[key] = float(my_dict[key])
elif my_model[key]['_type'].__class__ is complex:
my_dict[key] = complex(my_dict[key])
elif my_model[key]['_type'].__class__ is str:
new_dict[key] = str(my_dict[key])
# If one of the keys is not _type, this is a defined key, recursively get sub keys.
else:
if key not in my_dict:
my_dict[key] = ""
new_dict[key] = self.defaults_with_model(my_model[key], my_dict[key])
return new_dict
@mkorkmaz
Copy link
Author

#!/usr/bin/env python3.5
# -*- coding: utf-8 -*-

from model_utils import ModelUtils

ModelUtilities = ModelUtils()

mdl = {
    "name": {"_type": str(), "_required": True, "_index": True, "_default": "", '_ref': None, '_has_many': 0},
    "last_name": {"_type": str(), "_required": True, "_index": True, "_default": "", '_ref': None, '_has_many': 0},
    "experience": {"_type": int(), "_required": True, "_index": True, "_default": 0, '_ref': None, '_has_many': 0},
    "gender": {"_type": float(), "_required": False, "_index": False, "_default": None, '_ref': None, '_has_many': 0},
    "profile": {
        "age": {"_type": int(), "_required": False, "_index": False, "_default": 0, '_ref': None, '_has_many': 0},
        "weight": {"_type": float(), "_required": False, "_index": False, "_default": 0.0, '_ref': None, '_has_many': 0},
        "pets": {
            "cat": {"_type": int(), "_required": False, "_index": False, "_default": 0, '_ref': None, '_has_many': 0},
            "dogs": {"_type": int(), "_required": False, "_index": False, "_default": 0, '_ref': None, '_has_many': 0}
        }
    }
}

dct = {"name": "Mehmet",  "experience": "4", "profile": {"age": "26", "not_related_data": "23","pets": {"cat": 2}}}

print(ModelUtilities.validate_dict(mdl, dct))
# **Raises an exception:** Exception: Error for key 'profile.age', <class 'str'> given but it must be <class 'int'>

print(ModelUtilities.fit_dict_to_model(mdl, dct))
# **Prints:** {'profile': {'pets': {'cat': 2}, 'age': 26}, 'experience': 4, 'name': 'Mehmet'}

print(ModelUtilities.defaults_with_model(mdl, dct))
# **Prints:** {'profile': {'pets': {'cat': 2, 'dogs': 0}, 'weight': 0.0, 'age': 26}, 'gender': None, 'last_name': '', 'name': 'Mehmet', 'experience': 4}



Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment