3
2
from ladon.exceptions.types import *
4
3
from ladon.types.ladontype import LadonType
5
4
from ladon.types.attachment import attachment
5
from ladon.compat import PORTABLE_STRING_TYPES
7
7
def get_userdef_class_attributes(cls,exclude_methods=True):
8
8
base_attrs = dir(type('dummy', (object,), {}))
22
22
service depends on. It also keeps track of the parse order so it is possible
23
23
to create service type descriptors in the right order. This will prevent that
24
24
an array of some type is not defined before the type itself.
26
26
type_dict: holds all the parsed class-types that are derived from LadonType
27
27
type_order: holds all parsed types in the correct parse order
28
28
primitive_list: A list of all the primitive types a service depends on
30
30
Primitive types are defined as all classes that don't inherit LadonType
33
33
global_type_dict = {}
35
35
def __init__(self):
36
36
self.type_dict = {}
37
37
self.type_order = []
40
40
self.has_dicts = False
41
41
self.type_parse_order = 0
44
44
def add_primitive_type(self,prim):
45
45
if not self.primitive_list.count(prim):
46
46
self.primitive_list += [prim]
48
48
def analyze_class(self,cls):
50
50
inspect.getmro(cls).count(LadonType)
61
61
type_container = self.type_dict[type_key]
62
62
class_attrs = get_userdef_class_attributes(cls)
63
63
for attr in class_attrs:
64
if '__slots__' == attr:
66
64
attr_val = getattr(cls,attr)
68
67
if type(attr_val)==list and len(attr_val)==1:
69
68
attr_val = attr_val[0]
71
70
self.has_lists = True
72
if type(attr_val)!=type:
73
raise NeedToDefineParseTimeException("class attributes on LadonTypes must be defined as types, lists or arrays (%r %s)" % (attr_val, type(attr_val)))
71
elif type(attr_val)==dict:
72
# Dictionary type definitions for LadonTypes
73
# New feature in Ladon 0.6.6
75
temp_attr_val = attr_val['type']
76
except AttributeError:
77
raise NeedToDefineParseTimeException('Dictionary type definitions must contain the "type" key.\nclass: %s\nattr: %s' % (cls.__name__,attr))
79
if 'nullable' in attr_val:
80
if type(attr_val['nullable'])!=bool:
81
raise NeedToDefineParseTimeException('Dictionary type definition nullable must be a boolean value.\nclass: %s\nattr: %s' % (cls.__name__,attr))
82
attr_props['nullable'] = attr_val['nullable']
83
if attr_props['nullable']:
84
ok_default_types += [type(None)]
87
temp_doc = attr_val['doc']
88
if type(temp_doc) in PORTABLE_STRING_TYPES:
89
attr_props['doc'] = [temp_doc]
90
elif type(temp_doc)==list:
91
attr_props['doc'] = []
92
for doc_line in temp_doc:
93
if type(doc_line) in PORTABLE_STRING_TYPES:
94
attr_props['doc'] += [doc_line]
96
if 'default' in attr_val:
97
ok_default_types += [temp_attr_val]
98
if type(attr_val['default']) not in ok_default_types:
99
raise NeedToDefineParseTimeException('Default value does not match the attribute type.\nclass: %s\nattr: %s' % (cls.__name__,attr))
100
attr_props['default'] = attr_val['default']
103
if 'filters' in attr_val:
104
filters = attr_val['filters']
105
for filter_type in ['incoming_raw','incoming','outgoing','outgoing_raw']:
106
if filter_type in filters and hasattr(filters[filter_type],'__iter__') and len(filters[filter_type]):
107
# Add attribute filter functions
108
if 'filters' not in attr_props:
109
attr_props['filters'] = {}
110
attr_props['filters'][filter_type] = list(attr_val['filters'][filter_type])
112
attr_val = temp_attr_val
113
elif type(attr_val)!=type:
114
raise NeedToDefineParseTimeException("class attributes on LadonTypes must be defined as types, lists.\nclass: %s\nattr: %s" % (cls.__name__,attr))
74
115
if inspect.getmro(attr_val).count(LadonType):
75
116
self.analyze_class(attr_val)
82
123
if not self.type_order.count([attr_val]):
83
124
self.type_order += [[attr_val]]
84
125
attr_val = [attr_val]
85
type_container['attributes'] += [(attr,attr_val)]
126
attr_props['type'] = attr_val
127
type_container['attributes'] += [(attr,attr_val,attr_props)]
86
128
if not type_key in self.global_type_dict:
87
129
self.global_type_dict[type_key] = copy.deepcopy(type_container)
88
130
type_container['parse_order'] = self.type_parse_order