Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

Commit

Permalink
dded validation_rules property to Node class for automatic input
Browse files Browse the repository at this point in the history
validation. #5
added tests for validation rules.
updated version: 0.2.1
  • Loading branch information
mostafa committed Apr 27, 2017
1 parent 020f963 commit 4e30800
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 42 deletions.
2 changes: 1 addition & 1 deletion grest/__init__.py
@@ -1,3 +1,3 @@
from .grest import GRest

__version__ = '0.2'
__version__ = '0.2.1'
4 changes: 2 additions & 2 deletions grest/grest.py
Expand Up @@ -62,15 +62,15 @@ def index(self):
"""
try:
primary_model = self.__model__.get("primary")
validation_rules = {
__validation_rules__ = {
"skip": fields.Int(required=False, validate=lambda s: s >= 0),
"limit": fields.Int(required=False, validate=lambda l: l >= 1 and l <= 100)
}

# parse input data (validate or not!)
# noinspection PyBroadException
try:
query_data = parser.parse(validation_rules, request)
query_data = parser.parse(__validation_rules__, request)
except:
self.__log.debug("Validation failed!")
return jsonify(errors=["One or more of the required fields is missing or incorrect."]), 422
Expand Down
109 changes: 70 additions & 39 deletions grest/utils.py
@@ -1,23 +1,33 @@
from flask import request, g, jsonify, current_app as app
import markupsafe
import requests
from datetime import datetime
from functools import wraps
import json
from itertools import chain
import copy
from neomodel import relationship_manager

from flask import request, g, jsonify, current_app as app
import markupsafe
import requests
from webargs import fields
from neomodel import (relationship_manager, Property, StringProperty,
DateTimeProperty, DateProperty, EmailProperty,
BooleanProperty, ArrayProperty, IntegerProperty,
UniqueIdProperty, JSONProperty)
# import logging
# import os
import global_config


class Node(object):
__validation_rules__ = None
__validation_rules__ = {}

def __init__(self):
super(self.__class__, self)
self.__validation_rules__ = self.validation_rules

def serialize(self):
properties = copy.deepcopy(self.__dict__)
blocked_properties = ["id", "password", "current_otp"]
blocked_properties = ["id", "password",
"current_otp", "validation_rules"]

removable_keys = set()
for prop in properties.keys():
Expand All @@ -42,39 +52,60 @@ def serialize(self):

return properties

# @property
# def __validation_rules__(self):
# # if a class already has validation rules, return that!
# if (len(self.__validation_rules__) > 0):
# return self.__validation_rules__

# model_types = [
# # JSONProperty
# StringProperty, DateTimeProperty, DateProperty,
# EmailProperty, BooleanProperty,
# ArrayProperty, IntegerProperty
# ]

# model_mapping = {
# IntegerProperty: fields.Int,
# StringProperty: fields.Str,
# BooleanProperty: fields.Bool,
# DateTimeProperty: fields.DateTime,
# DateProperty: fields.Date,
# EmailProperty: fields.Str,
# ArrayProperty: fields.Raw,
# # JSONProperty: fields.Raw,
# }

# self.__validation_rules__ = {}
# all_fields = dir(self)
# for field in all_fields:
# if type(getattr(self, field)) in model_types:
# if not (field.startswith("_") and field.endswith("_")):
# self.__validation_rules__[field] = model_mapping[
# getattr(self, field)]()

# return self.__validation_rules__
@property
def validation_rules(self):
"""
if the user has defined validation rules,
return that, otherwise construct a set of
predefined rules and return it.
All internal GRest methods should use this property.
"""

if len(self.__validation_rules__) > 0:
# there is a set of user-defined validation rules
return self.__validation_rules__

model_types = [
StringProperty, DateTimeProperty, DateProperty,
EmailProperty, BooleanProperty, UniqueIdProperty,
ArrayProperty, IntegerProperty, JSONProperty
]

model_mapping = {
IntegerProperty: fields.Int,
StringProperty: fields.Str,
BooleanProperty: fields.Bool,
DateTimeProperty: fields.DateTime,
DateProperty: fields.Date,
EmailProperty: fields.Email,
ArrayProperty: fields.List,
JSONProperty: fields.Dict,
UniqueIdProperty: fields.UUID
}

name = 0
value = 1

for field in self.__all_properties__:
if type(field[value]) in model_types:
if isinstance(field[value], ArrayProperty):
if field[value].unique_index:
# what it contains: Array of *String*
container = model_mapping[
type(field[value].unique_index)]
else:
# defaults to Raw for untyped ArrayProperty
container = fields.Raw

self.__validation_rules__[field[name]] = model_mapping[
type(field[value])](container,
required=field[value].required)
else:
self.__validation_rules__[field[name]] = model_mapping[
type(field[value])](required=field[value].required)

return self.__validation_rules__


def authenticate(func):
Expand Down
32 changes: 32 additions & 0 deletions tests/test_validation_rules_property.py
@@ -0,0 +1,32 @@
from neomodel import *
from webargs import fields
import grest


class model(StructuredNode, grest.utils.Node):
GREEK = (
("A", "Alpha"),
("B", "Beta"),
("G", "Gamma")
)

uuid = UniqueIdProperty()
string = StringProperty(required=True)
choices = StringProperty(choices=GREEK)
integer = IntegerProperty()
json = JSONProperty()
array_of_string = ArrayProperty(StringProperty())
raw_data = ArrayProperty()
date = DateProperty()
datetime = DateTimeProperty()
boolean = BooleanProperty()
email = EmailProperty()


def test_validation_rules_property():
instance = model()

for rule in instance.__validation_rules__.items():
assert isinstance(rule[1], fields.Field)
if isinstance(rule[1], fields.List):
assert isinstance(rule[1].container, fields.Field)

0 comments on commit 4e30800

Please sign in to comment.