UrlSchemaNode   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 16
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
rs 10
wmc 6

1 Method

Rating   Name   Duplication   Size   Complexity  
B validator() 0 12 6
1
import colander
2
import requests
3
import rfc3987
4
5
6
class ValidationFailure(Exception):
7
    def __init__(self, msg, errors):
8
        self.msg = msg
9
        self.errors = errors
10
11
12
def sqlalchemy_validator(node, value, model, session=None, msg='%s is ongeldig'):
13
    """
14
    Validate a sqlalchemy object or identifier.
15
    Function checks if value is an instance of sqlalchemy model
16
    or an id of one.
17
    :param node: A colander SchemaNode.
18
    :param value: The value to be validated. Is the key of the
19
        SQLAlchemy model.
20
    :param model: A SQLAlchemy model.
21
    :param session: A SQLAlchemy session. Is required if value is not an
22
        instance of a SQLAlchemy model.
23
    :param msg: A msg to attach to a `colander.Invalid` exception.
24
    :raises colander.Invalid: If not a valid sqlalchemy model.
25
    """
26
27
    m = session.query(model).get(value)
28
29
    if not m:
30
        raise colander.Invalid(
31
            node,
32
            msg % value
33
        )
34
35
    return m
36
37
38
#########################################################################################
39
# BASIC DATA TYPES (ENRICHED FOR O.E.)
40
#########################################################################################
41
class OEBoolean(colander.Boolean):
42
    """
43
    The default deserialization casts every value to a Boolean. This is not what we want.
44
    courtesy of cahytinne
45
    """
46
    def deserialize(self, node, cstruct):
47
48
        if cstruct is None or cstruct is colander.null:
49
            cstruct = colander.null  # handling this depends on being required or not
50
51
        elif not type(cstruct) is bool:
52
            raise colander.Invalid(node, '{0} is not a valid Boolean.'.format(cstruct))
53
54
        result = super(OEBoolean, self).deserialize(node, cstruct)
55
        return result
56
57
58
class OEInteger(colander.Integer):
59
    """
60
    the default deserialization casts floats to ints. This is not what we want.
61
    see also: https://github.com/Pylons/colander/issues/292
62
    """
63
    def deserialize(self, node, cstruct):
64
65
        if cstruct is None or cstruct is colander.null:
66
            cstruct = colander.null  # handling this depends on being required or not
67
68
        elif not type(cstruct) is int:
69
            raise colander.Invalid(node, '{0} is not a valid Integer.'.format(cstruct))
70
71
        result = super(OEInteger, self).deserialize(node, cstruct)
72
        return result
73
74
75
#########################################################################################
76
# SCHEMA NODES (FOR O.E)
77
#########################################################################################
78
class OEIDSchemaNode(colander.SchemaNode):
79
    schema_type = OEInteger
80
81
    def validator(self, node, cstruct):
82
        if cstruct < 0:
83
            raise colander.Invalid(node, 'Geen geldig ID ({}< 0)'.format(cstruct))
84
85
86
class OEEmailSchemaNode(colander.SchemaNode):
87
    schema_type = colander.String
88
    validator = colander.All(colander.Length(max=255), colander.Email('Dit is geen geldig emailadres.'))
89
90
91
class OEStringSchemaNode(colander.SchemaNode):
92
    schema_type = colander.String
93
94
95
class OEDateTimeSchemaNode(colander.SchemaNode):
96
    schema_type = colander.DateTime
97
98
99
class OEBoolSchemaNode(colander.SchemaNode):
100
    schema_type = OEBoolean
101
102
103
class UrlSchemaNode(colander.SchemaNode):
104
    schema_type = colander.String
105
    title = 'Url'
106
107
    def validator(self, node, cstruct):
108
        if len(cstruct) > 2083:
109
            raise colander.Invalid(node, "URI is too long (max=2083).", cstruct)
110
        if not rfc3987.match(cstruct, rule='URI'):
111
            raise colander.Invalid(node, '{0} is geen geldige URL.'.format(cstruct))
112
113
        try:
114
            res = requests.get(cstruct, headers={"Accept": "application/json"})
115
        except requests.ConnectionError:
116
            raise colander.Invalid(node, "URL bestaat niet.", cstruct)
117
        if res is not None and res.status_code == 404:
118
            raise colander.Invalid(node, "URL bestaat niet.", cstruct)
119
120
121
class UriSchemaNode(colander.SchemaNode):
122
    """
123
    URL validator. rfc3987 is used to check if a URL is correct (https://pypi.python.org/pypi/rfc3987/)
124
    If ``msg`` is supplied, it will be the error message to be used when raising :exc:`colander.Invalid`;
125
    otherwise, defaults to 'Invalid URL'.
126
    """
127
128
    schema_type = colander.String
129
    title = 'Erfgoed id Uri'
130
131
    def validator(self, node, cstruct):
132
        if len(cstruct) > 100:
133
            raise colander.Invalid(node, "URI is too long (max=100).", cstruct)
134
        if not rfc3987.match(cstruct, rule='URI'):
135
            raise colander.Invalid(node, '{0} is geen geldige URI.'.format(cstruct))
136
137
138
class ExternalUriSchemaNode(UriSchemaNode):
139
    schema_type = colander.String
140
141
    def validator(self, node, cstruct):
142
        super(ExternalUriSchemaNode, self).validator(node, cstruct)
143
144
        try:
145
            res = requests.get(cstruct, headers={"Accept": "application/json"})
146
        except requests.ConnectionError:
147
            raise colander.Invalid(node, "URI bestaat niet.", cstruct)
148
        if res is not None and res.status_code == 404:
149
            raise colander.Invalid(node, "URI bestaat niet.", cstruct)