pulsar.schema.definition

  1#
  2# Licensed to the Apache Software Foundation (ASF) under one
  3# or more contributor license agreements.  See the NOTICE file
  4# distributed with this work for additional information
  5# regarding copyright ownership.  The ASF licenses this file
  6# to you under the Apache License, Version 2.0 (the
  7# "License"); you may not use this file except in compliance
  8# with the License.  You may obtain a copy of the License at
  9#
 10#   http://www.apache.org/licenses/LICENSE-2.0
 11#
 12# Unless required by applicable law or agreed to in writing,
 13# software distributed under the License is distributed on an
 14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15# KIND, either express or implied.  See the License for the
 16# specific language governing permissions and limitations
 17# under the License.
 18#
 19
 20import copy
 21from abc import abstractmethod
 22from collections import OrderedDict
 23from enum import Enum, EnumMeta
 24from six import with_metaclass
 25
 26
 27def _check_record_or_field(x):
 28    if (type(x) is type and not issubclass(x, Record)) \
 29            and not isinstance(x, Field):
 30        raise Exception('Argument ' + x + ' is not a Record or a Field')
 31
 32
 33class RecordMeta(type):
 34    def __new__(metacls, name, parents, dct):
 35        if name != 'Record':
 36            # Do not apply this logic to the base class itself
 37            dct['_fields'] = RecordMeta._get_fields(dct)
 38            dct['_required'] = False
 39        return type.__new__(metacls, name, parents, dct)
 40
 41    @classmethod
 42    def _get_fields(cls, dct):
 43        # Build a set of valid fields for this record
 44        fields = OrderedDict()
 45        for name, value in dct.items():
 46            if issubclass(type(value), EnumMeta):
 47                value = CustomEnum(value)
 48            elif type(value) == RecordMeta:
 49                # We expect an instance of a record rather than the class itself
 50                value = value()
 51
 52            if isinstance(value, Record) or isinstance(value, Field):
 53                fields[name] = value
 54        return fields
 55
 56
 57class Record(with_metaclass(RecordMeta, object)):
 58
 59    # This field is used to set namespace for Avro Record schema.
 60    _avro_namespace = None
 61
 62    # Generate a schema where fields are sorted alphabetically
 63    _sorted_fields = False
 64
 65    def __init__(self, default=None, required_default=False, required=False, *args, **kwargs):
 66        self._required_default = required_default
 67        self._default = default
 68        self._required = required
 69
 70        for k, value in self._fields.items():
 71            if k in kwargs:
 72                if isinstance(value, Record) and isinstance(kwargs[k], dict):
 73                    # Use dict init Record object
 74                    copied = copy.copy(value)
 75                    copied.__init__(**kwargs[k])
 76                    self.__setattr__(k, copied)
 77                elif isinstance(value, Array) and isinstance(kwargs[k], list) and len(kwargs[k]) > 0 \
 78                        and isinstance(value.array_type, Record) and isinstance(kwargs[k][0], dict):
 79                    arr = []
 80                    for item in kwargs[k]:
 81                        copied = copy.copy(value.array_type)
 82                        copied.__init__(**item)
 83                        arr.append(copied)
 84                    self.__setattr__(k, arr)
 85                elif isinstance(value, Map) and isinstance(kwargs[k], dict) and len(kwargs[k]) > 0 \
 86                    and isinstance(value.value_type, Record) and isinstance(list(kwargs[k].values())[0], dict):
 87                    dic = {}
 88                    for mapKey, mapValue in kwargs[k].items():
 89                        copied = copy.copy(value.value_type)
 90                        copied.__init__(**mapValue)
 91                        dic[mapKey] = copied
 92                    self.__setattr__(k, dic)
 93                else:
 94                    # Value was overridden at constructor
 95                    self.__setattr__(k, kwargs[k])
 96            elif isinstance(value, Record):
 97                # Value is a subrecord
 98                self.__setattr__(k, value)
 99            else:
100                # Set field to default value, without revalidating the default value type
101                super(Record, self).__setattr__(k, value.default())
102
103    @classmethod
104    def schema(cls):
105        return cls.schema_info(set())
106
107    @classmethod
108    def schema_info(cls, defined_names):
109        namespace_prefix = ''
110        if cls._avro_namespace is not None:
111            namespace_prefix = cls._avro_namespace + '.'
112        namespace_name = namespace_prefix + cls.__name__
113
114        if namespace_name in defined_names:
115            return namespace_name
116
117        defined_names.add(namespace_name)
118
119        schema = {
120            'type': 'record',
121            'name': str(cls.__name__)
122        }
123        if cls._avro_namespace is not None:
124            schema['namespace'] = cls._avro_namespace
125        schema['fields'] = []
126
127        def get_filed_default_value(value):
128            if isinstance(value, Enum):
129                return value.name
130            else:
131                return value
132
133        if cls._sorted_fields:
134            fields = sorted(cls._fields.keys())
135        else:
136            fields = cls._fields.keys()
137        for name in fields:
138            field = cls._fields[name]
139            field_type = field.schema_info(defined_names) \
140                if field._required else ['null', field.schema_info(defined_names)]
141            schema['fields'].append({
142                'name': name,
143                'default': get_filed_default_value(field.default()),
144                'type': field_type
145            }) if field.required_default() else schema['fields'].append({
146                'name': name,
147                'type': field_type,
148            })
149
150        return schema
151
152    def __setattr__(self, key, value):
153        if key == '_default':
154            super(Record, self).__setattr__(key, value)
155        elif key == '_required_default':
156            super(Record, self).__setattr__(key, value)
157        elif key == '_required':
158            super(Record, self).__setattr__(key, value)
159        else:
160            if key not in self._fields:
161                raise AttributeError('Cannot set undeclared field ' + key + ' on record')
162
163            # Check that type of value matches the field type
164            field = self._fields[key]
165            value = field.validate_type(key, value)
166            super(Record, self).__setattr__(key, value)
167
168    def __eq__(self, other):
169        for field in self._fields:
170            if self.__getattribute__(field) != other.__getattribute__(field):
171                return False
172        return True
173
174    def __ne__(self, other):
175        return not self.__eq__(other)
176
177    def __str__(self):
178        return str(self.__dict__)
179
180    def type(self):
181        return str(self.__class__.__name__)
182
183    def python_type(self):
184        return self.__class__
185
186    def validate_type(self, name, val):
187        if val is None and not self._required:
188            return self.default()
189
190        if not isinstance(val, self.__class__):
191            raise TypeError("Invalid type '%s' for sub-record field '%s'. Expected: %s" % (
192                type(val), name, self.__class__))
193        return val
194
195    def default(self):
196        if self._default is not None:
197            return self._default
198        else:
199            return None
200
201    def required_default(self):
202        return self._required_default
203
204
205class Field(object):
206    def __init__(self, default=None, required=False, required_default=False):
207        if default is not None:
208            default = self.validate_type('default', default)
209        self._default = default
210        self._required_default = required_default
211        self._required = required
212
213    @abstractmethod
214    def type(self):
215        pass
216
217    @abstractmethod
218    def python_type(self):
219        pass
220
221    def validate_type(self, name, val):
222        if val is None and not self._required:
223            return self.default()
224
225        if type(val) != self.python_type():
226            raise TypeError("Invalid type '%s' for field '%s'. Expected: %s" % (type(val), name, self.python_type()))
227        return val
228
229    def schema(self):
230        # For primitive types, the schema would just be the type itself
231        return self.type()
232
233    def schema_info(self, defined_names):
234        return self.type()
235
236    def default(self):
237        return self._default
238
239    def required_default(self):
240        return self._required_default
241
242
243# All types
244
245
246class Null(Field):
247    def type(self):
248        return 'null'
249
250    def python_type(self):
251        return type(None)
252
253    def validate_type(self, name, val):
254        if val is not None:
255            raise TypeError('Field ' + name + ' is set to be None')
256        return val
257
258
259class Boolean(Field):
260    def type(self):
261        return 'boolean'
262
263    def python_type(self):
264        return bool
265
266    def default(self):
267        if self._default is not None:
268            return self._default
269        else:
270            return False
271
272
273class Integer(Field):
274    def type(self):
275        return 'int'
276
277    def python_type(self):
278        return int
279
280    def default(self):
281        if self._default is not None:
282            return self._default
283        else:
284            return None
285
286
287class Long(Field):
288    def type(self):
289        return 'long'
290
291    def python_type(self):
292        return int
293
294    def default(self):
295        if self._default is not None:
296            return self._default
297        else:
298            return None
299
300
301class Float(Field):
302    def type(self):
303        return 'float'
304
305    def python_type(self):
306        return float
307
308    def default(self):
309        if self._default is not None:
310            return self._default
311        else:
312            return None
313
314
315class Double(Field):
316    def type(self):
317        return 'double'
318
319    def python_type(self):
320        return float
321
322    def default(self):
323        if self._default is not None:
324            return self._default
325        else:
326            return None
327
328
329class Bytes(Field):
330    def type(self):
331        return 'bytes'
332
333    def python_type(self):
334        return bytes
335
336    def default(self):
337        if self._default is not None:
338            return self._default
339        else:
340            return None
341
342
343class String(Field):
344    def type(self):
345        return 'string'
346
347    def python_type(self):
348        return str
349
350    def validate_type(self, name, val):
351        t = type(val)
352
353        if val is None and not self._required:
354            return self.default()
355
356        if not (t is str or t.__name__ == 'unicode'):
357            raise TypeError("Invalid type '%s' for field '%s'. Expected a string" % (t, name))
358        return val
359
360    def default(self):
361        if self._default is not None:
362            return self._default
363        else:
364            return None
365
366# Complex types
367
368
369class CustomEnum(Field):
370    def __init__(self, enum_type, default=None, required=False, required_default=False):
371        if not issubclass(enum_type, Enum):
372            raise Exception(enum_type + " is not a valid Enum type")
373        self.enum_type = enum_type
374        self.values = {}
375        for x in enum_type.__members__.values():
376            self.values[x.value] = x
377        super(CustomEnum, self).__init__(default, required, required_default)
378
379    def type(self):
380        return 'enum'
381
382    def python_type(self):
383        return self.enum_type
384
385    def validate_type(self, name, val):
386        if val is None:
387            return None
388
389        if type(val) is str:
390            # The enum was passed as a string, we need to check it against the possible values
391            if val in self.enum_type.__members__:
392                return self.enum_type.__members__[val]
393            else:
394                raise TypeError(
395                    "Invalid enum value '%s' for field '%s'. Expected: %s" % (val, name, self.enum_type.__members__.keys()))
396        elif type(val) is int:
397            # The enum was passed as an int, we need to check it against the possible values
398            if val in self.values:
399                return self.values[val]
400            else:
401                raise TypeError(
402                    "Invalid enum value '%s' for field '%s'. Expected: %s" % (val, name, self.values.keys()))
403        elif type(val) != self.python_type():
404            raise TypeError("Invalid type '%s' for field '%s'. Expected: %s" % (type(val), name, self.python_type()))
405        else:
406            return val
407
408    def schema(self):
409        return self.schema_info(set())
410
411    def schema_info(self, defined_names):
412        if self.enum_type.__name__ in defined_names:
413            return self.enum_type.__name__
414        defined_names.add(self.enum_type.__name__)
415        return {
416            'type': self.type(),
417            'name': self.enum_type.__name__,
418            'symbols': [x.name for x in self.enum_type]
419        }
420
421    def default(self):
422        if self._default is not None:
423            return self._default
424        else:
425            return None
426
427
428class Array(Field):
429    def __init__(self, array_type, default=None, required=False, required_default=False):
430        _check_record_or_field(array_type)
431        self.array_type = array_type
432        super(Array, self).__init__(default=default, required=required, required_default=required_default)
433
434    def type(self):
435        return 'array'
436
437    def python_type(self):
438        return list
439
440    def validate_type(self, name, val):
441        if val is None:
442            return None
443
444        super(Array, self).validate_type(name, val)
445
446        for x in val:
447            if type(x) != self.array_type.python_type():
448                raise TypeError('Array field ' + name + ' items should all be of type '
449                                + self.array_type.python_type())
450        return val
451
452    def schema(self):
453        return self.schema_info(set())
454
455    def schema_info(self, defined_names):
456        return {
457            'type': self.type(),
458            'items': self.array_type.schema_info(defined_names) if isinstance(self.array_type, (Array, Map, Record))
459                else self.array_type.type()
460        }
461
462    def default(self):
463        if self._default is not None:
464            return self._default
465        else:
466            return None
467
468
469class Map(Field):
470    def __init__(self, value_type, default=None, required=False, required_default=False):
471        _check_record_or_field(value_type)
472        self.value_type = value_type
473        super(Map, self).__init__(default=default, required=required, required_default=required_default)
474
475    def type(self):
476        return 'map'
477
478    def python_type(self):
479        return dict
480
481    def validate_type(self, name, val):
482        if val is None:
483            return None
484
485        super(Map, self).validate_type(name, val)
486
487        for k, v in val.items():
488            if type(k) != str and not is_unicode(k):
489                raise TypeError('Map keys for field ' + name + '  should all be strings')
490            if type(v) != self.value_type.python_type():
491                raise TypeError('Map values for field ' + name + ' should all be of type '
492                                + self.value_type.python_type())
493
494        return val
495
496    def schema(self):
497        return self.schema_info(set())
498
499    def schema_info(self, defined_names):
500        return {
501            'type': self.type(),
502            'values': self.value_type.schema_info(defined_names) if isinstance(self.value_type, (Array, Map, Record))
503                else self.value_type.type()
504        }
505
506    def default(self):
507        if self._default is not None:
508            return self._default
509        else:
510            return None
511
512
513# Python3 has no `unicode` type, so here we use a tricky way to check if the type of `x` is `unicode` in Python2
514# and also make it work well with Python3.
515def is_unicode(x):
516    return 'encode' in dir(x) and type(x.encode()) == str
class RecordMeta(builtins.type):
34class RecordMeta(type):
35    def __new__(metacls, name, parents, dct):
36        if name != 'Record':
37            # Do not apply this logic to the base class itself
38            dct['_fields'] = RecordMeta._get_fields(dct)
39            dct['_required'] = False
40        return type.__new__(metacls, name, parents, dct)
41
42    @classmethod
43    def _get_fields(cls, dct):
44        # Build a set of valid fields for this record
45        fields = OrderedDict()
46        for name, value in dct.items():
47            if issubclass(type(value), EnumMeta):
48                value = CustomEnum(value)
49            elif type(value) == RecordMeta:
50                # We expect an instance of a record rather than the class itself
51                value = value()
52
53            if isinstance(value, Record) or isinstance(value, Field):
54                fields[name] = value
55        return fields

type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type

Inherited Members
builtins.type
type
mro
class Record:
 58class Record(with_metaclass(RecordMeta, object)):
 59
 60    # This field is used to set namespace for Avro Record schema.
 61    _avro_namespace = None
 62
 63    # Generate a schema where fields are sorted alphabetically
 64    _sorted_fields = False
 65
 66    def __init__(self, default=None, required_default=False, required=False, *args, **kwargs):
 67        self._required_default = required_default
 68        self._default = default
 69        self._required = required
 70
 71        for k, value in self._fields.items():
 72            if k in kwargs:
 73                if isinstance(value, Record) and isinstance(kwargs[k], dict):
 74                    # Use dict init Record object
 75                    copied = copy.copy(value)
 76                    copied.__init__(**kwargs[k])
 77                    self.__setattr__(k, copied)
 78                elif isinstance(value, Array) and isinstance(kwargs[k], list) and len(kwargs[k]) > 0 \
 79                        and isinstance(value.array_type, Record) and isinstance(kwargs[k][0], dict):
 80                    arr = []
 81                    for item in kwargs[k]:
 82                        copied = copy.copy(value.array_type)
 83                        copied.__init__(**item)
 84                        arr.append(copied)
 85                    self.__setattr__(k, arr)
 86                elif isinstance(value, Map) and isinstance(kwargs[k], dict) and len(kwargs[k]) > 0 \
 87                    and isinstance(value.value_type, Record) and isinstance(list(kwargs[k].values())[0], dict):
 88                    dic = {}
 89                    for mapKey, mapValue in kwargs[k].items():
 90                        copied = copy.copy(value.value_type)
 91                        copied.__init__(**mapValue)
 92                        dic[mapKey] = copied
 93                    self.__setattr__(k, dic)
 94                else:
 95                    # Value was overridden at constructor
 96                    self.__setattr__(k, kwargs[k])
 97            elif isinstance(value, Record):
 98                # Value is a subrecord
 99                self.__setattr__(k, value)
100            else:
101                # Set field to default value, without revalidating the default value type
102                super(Record, self).__setattr__(k, value.default())
103
104    @classmethod
105    def schema(cls):
106        return cls.schema_info(set())
107
108    @classmethod
109    def schema_info(cls, defined_names):
110        namespace_prefix = ''
111        if cls._avro_namespace is not None:
112            namespace_prefix = cls._avro_namespace + '.'
113        namespace_name = namespace_prefix + cls.__name__
114
115        if namespace_name in defined_names:
116            return namespace_name
117
118        defined_names.add(namespace_name)
119
120        schema = {
121            'type': 'record',
122            'name': str(cls.__name__)
123        }
124        if cls._avro_namespace is not None:
125            schema['namespace'] = cls._avro_namespace
126        schema['fields'] = []
127
128        def get_filed_default_value(value):
129            if isinstance(value, Enum):
130                return value.name
131            else:
132                return value
133
134        if cls._sorted_fields:
135            fields = sorted(cls._fields.keys())
136        else:
137            fields = cls._fields.keys()
138        for name in fields:
139            field = cls._fields[name]
140            field_type = field.schema_info(defined_names) \
141                if field._required else ['null', field.schema_info(defined_names)]
142            schema['fields'].append({
143                'name': name,
144                'default': get_filed_default_value(field.default()),
145                'type': field_type
146            }) if field.required_default() else schema['fields'].append({
147                'name': name,
148                'type': field_type,
149            })
150
151        return schema
152
153    def __setattr__(self, key, value):
154        if key == '_default':
155            super(Record, self).__setattr__(key, value)
156        elif key == '_required_default':
157            super(Record, self).__setattr__(key, value)
158        elif key == '_required':
159            super(Record, self).__setattr__(key, value)
160        else:
161            if key not in self._fields:
162                raise AttributeError('Cannot set undeclared field ' + key + ' on record')
163
164            # Check that type of value matches the field type
165            field = self._fields[key]
166            value = field.validate_type(key, value)
167            super(Record, self).__setattr__(key, value)
168
169    def __eq__(self, other):
170        for field in self._fields:
171            if self.__getattribute__(field) != other.__getattribute__(field):
172                return False
173        return True
174
175    def __ne__(self, other):
176        return not self.__eq__(other)
177
178    def __str__(self):
179        return str(self.__dict__)
180
181    def type(self):
182        return str(self.__class__.__name__)
183
184    def python_type(self):
185        return self.__class__
186
187    def validate_type(self, name, val):
188        if val is None and not self._required:
189            return self.default()
190
191        if not isinstance(val, self.__class__):
192            raise TypeError("Invalid type '%s' for sub-record field '%s'. Expected: %s" % (
193                type(val), name, self.__class__))
194        return val
195
196    def default(self):
197        if self._default is not None:
198            return self._default
199        else:
200            return None
201
202    def required_default(self):
203        return self._required_default
Record( default=None, required_default=False, required=False, *args, **kwargs)
 66    def __init__(self, default=None, required_default=False, required=False, *args, **kwargs):
 67        self._required_default = required_default
 68        self._default = default
 69        self._required = required
 70
 71        for k, value in self._fields.items():
 72            if k in kwargs:
 73                if isinstance(value, Record) and isinstance(kwargs[k], dict):
 74                    # Use dict init Record object
 75                    copied = copy.copy(value)
 76                    copied.__init__(**kwargs[k])
 77                    self.__setattr__(k, copied)
 78                elif isinstance(value, Array) and isinstance(kwargs[k], list) and len(kwargs[k]) > 0 \
 79                        and isinstance(value.array_type, Record) and isinstance(kwargs[k][0], dict):
 80                    arr = []
 81                    for item in kwargs[k]:
 82                        copied = copy.copy(value.array_type)
 83                        copied.__init__(**item)
 84                        arr.append(copied)
 85                    self.__setattr__(k, arr)
 86                elif isinstance(value, Map) and isinstance(kwargs[k], dict) and len(kwargs[k]) > 0 \
 87                    and isinstance(value.value_type, Record) and isinstance(list(kwargs[k].values())[0], dict):
 88                    dic = {}
 89                    for mapKey, mapValue in kwargs[k].items():
 90                        copied = copy.copy(value.value_type)
 91                        copied.__init__(**mapValue)
 92                        dic[mapKey] = copied
 93                    self.__setattr__(k, dic)
 94                else:
 95                    # Value was overridden at constructor
 96                    self.__setattr__(k, kwargs[k])
 97            elif isinstance(value, Record):
 98                # Value is a subrecord
 99                self.__setattr__(k, value)
100            else:
101                # Set field to default value, without revalidating the default value type
102                super(Record, self).__setattr__(k, value.default())
@classmethod
def schema(cls):
104    @classmethod
105    def schema(cls):
106        return cls.schema_info(set())
@classmethod
def schema_info(cls, defined_names):
108    @classmethod
109    def schema_info(cls, defined_names):
110        namespace_prefix = ''
111        if cls._avro_namespace is not None:
112            namespace_prefix = cls._avro_namespace + '.'
113        namespace_name = namespace_prefix + cls.__name__
114
115        if namespace_name in defined_names:
116            return namespace_name
117
118        defined_names.add(namespace_name)
119
120        schema = {
121            'type': 'record',
122            'name': str(cls.__name__)
123        }
124        if cls._avro_namespace is not None:
125            schema['namespace'] = cls._avro_namespace
126        schema['fields'] = []
127
128        def get_filed_default_value(value):
129            if isinstance(value, Enum):
130                return value.name
131            else:
132                return value
133
134        if cls._sorted_fields:
135            fields = sorted(cls._fields.keys())
136        else:
137            fields = cls._fields.keys()
138        for name in fields:
139            field = cls._fields[name]
140            field_type = field.schema_info(defined_names) \
141                if field._required else ['null', field.schema_info(defined_names)]
142            schema['fields'].append({
143                'name': name,
144                'default': get_filed_default_value(field.default()),
145                'type': field_type
146            }) if field.required_default() else schema['fields'].append({
147                'name': name,
148                'type': field_type,
149            })
150
151        return schema
def type(self):
181    def type(self):
182        return str(self.__class__.__name__)
def python_type(self):
184    def python_type(self):
185        return self.__class__
def validate_type(self, name, val):
187    def validate_type(self, name, val):
188        if val is None and not self._required:
189            return self.default()
190
191        if not isinstance(val, self.__class__):
192            raise TypeError("Invalid type '%s' for sub-record field '%s'. Expected: %s" % (
193                type(val), name, self.__class__))
194        return val
def default(self):
196    def default(self):
197        if self._default is not None:
198            return self._default
199        else:
200            return None
def required_default(self):
202    def required_default(self):
203        return self._required_default
class Field:
206class Field(object):
207    def __init__(self, default=None, required=False, required_default=False):
208        if default is not None:
209            default = self.validate_type('default', default)
210        self._default = default
211        self._required_default = required_default
212        self._required = required
213
214    @abstractmethod
215    def type(self):
216        pass
217
218    @abstractmethod
219    def python_type(self):
220        pass
221
222    def validate_type(self, name, val):
223        if val is None and not self._required:
224            return self.default()
225
226        if type(val) != self.python_type():
227            raise TypeError("Invalid type '%s' for field '%s'. Expected: %s" % (type(val), name, self.python_type()))
228        return val
229
230    def schema(self):
231        # For primitive types, the schema would just be the type itself
232        return self.type()
233
234    def schema_info(self, defined_names):
235        return self.type()
236
237    def default(self):
238        return self._default
239
240    def required_default(self):
241        return self._required_default
Field(default=None, required=False, required_default=False)
207    def __init__(self, default=None, required=False, required_default=False):
208        if default is not None:
209            default = self.validate_type('default', default)
210        self._default = default
211        self._required_default = required_default
212        self._required = required
@abstractmethod
def type(self):
214    @abstractmethod
215    def type(self):
216        pass
@abstractmethod
def python_type(self):
218    @abstractmethod
219    def python_type(self):
220        pass
def validate_type(self, name, val):
222    def validate_type(self, name, val):
223        if val is None and not self._required:
224            return self.default()
225
226        if type(val) != self.python_type():
227            raise TypeError("Invalid type '%s' for field '%s'. Expected: %s" % (type(val), name, self.python_type()))
228        return val
def schema(self):
230    def schema(self):
231        # For primitive types, the schema would just be the type itself
232        return self.type()
def schema_info(self, defined_names):
234    def schema_info(self, defined_names):
235        return self.type()
def default(self):
237    def default(self):
238        return self._default
def required_default(self):
240    def required_default(self):
241        return self._required_default
class Null(Field):
247class Null(Field):
248    def type(self):
249        return 'null'
250
251    def python_type(self):
252        return type(None)
253
254    def validate_type(self, name, val):
255        if val is not None:
256            raise TypeError('Field ' + name + ' is set to be None')
257        return val
def type(self):
248    def type(self):
249        return 'null'
def python_type(self):
251    def python_type(self):
252        return type(None)
def validate_type(self, name, val):
254    def validate_type(self, name, val):
255        if val is not None:
256            raise TypeError('Field ' + name + ' is set to be None')
257        return val
class Boolean(Field):
260class Boolean(Field):
261    def type(self):
262        return 'boolean'
263
264    def python_type(self):
265        return bool
266
267    def default(self):
268        if self._default is not None:
269            return self._default
270        else:
271            return False
def type(self):
261    def type(self):
262        return 'boolean'
def python_type(self):
264    def python_type(self):
265        return bool
def default(self):
267    def default(self):
268        if self._default is not None:
269            return self._default
270        else:
271            return False
class Integer(Field):
274class Integer(Field):
275    def type(self):
276        return 'int'
277
278    def python_type(self):
279        return int
280
281    def default(self):
282        if self._default is not None:
283            return self._default
284        else:
285            return None
def type(self):
275    def type(self):
276        return 'int'
def python_type(self):
278    def python_type(self):
279        return int
def default(self):
281    def default(self):
282        if self._default is not None:
283            return self._default
284        else:
285            return None
class Long(Field):
288class Long(Field):
289    def type(self):
290        return 'long'
291
292    def python_type(self):
293        return int
294
295    def default(self):
296        if self._default is not None:
297            return self._default
298        else:
299            return None
def type(self):
289    def type(self):
290        return 'long'
def python_type(self):
292    def python_type(self):
293        return int
def default(self):
295    def default(self):
296        if self._default is not None:
297            return self._default
298        else:
299            return None
class Float(Field):
302class Float(Field):
303    def type(self):
304        return 'float'
305
306    def python_type(self):
307        return float
308
309    def default(self):
310        if self._default is not None:
311            return self._default
312        else:
313            return None
def type(self):
303    def type(self):
304        return 'float'
def python_type(self):
306    def python_type(self):
307        return float
def default(self):
309    def default(self):
310        if self._default is not None:
311            return self._default
312        else:
313            return None
class Double(Field):
316class Double(Field):
317    def type(self):
318        return 'double'
319
320    def python_type(self):
321        return float
322
323    def default(self):
324        if self._default is not None:
325            return self._default
326        else:
327            return None
def type(self):
317    def type(self):
318        return 'double'
def python_type(self):
320    def python_type(self):
321        return float
def default(self):
323    def default(self):
324        if self._default is not None:
325            return self._default
326        else:
327            return None
class Bytes(Field):
330class Bytes(Field):
331    def type(self):
332        return 'bytes'
333
334    def python_type(self):
335        return bytes
336
337    def default(self):
338        if self._default is not None:
339            return self._default
340        else:
341            return None
def type(self):
331    def type(self):
332        return 'bytes'
def python_type(self):
334    def python_type(self):
335        return bytes
def default(self):
337    def default(self):
338        if self._default is not None:
339            return self._default
340        else:
341            return None
class String(Field):
344class String(Field):
345    def type(self):
346        return 'string'
347
348    def python_type(self):
349        return str
350
351    def validate_type(self, name, val):
352        t = type(val)
353
354        if val is None and not self._required:
355            return self.default()
356
357        if not (t is str or t.__name__ == 'unicode'):
358            raise TypeError("Invalid type '%s' for field '%s'. Expected a string" % (t, name))
359        return val
360
361    def default(self):
362        if self._default is not None:
363            return self._default
364        else:
365            return None
def type(self):
345    def type(self):
346        return 'string'
def python_type(self):
348    def python_type(self):
349        return str
def validate_type(self, name, val):
351    def validate_type(self, name, val):
352        t = type(val)
353
354        if val is None and not self._required:
355            return self.default()
356
357        if not (t is str or t.__name__ == 'unicode'):
358            raise TypeError("Invalid type '%s' for field '%s'. Expected a string" % (t, name))
359        return val
def default(self):
361    def default(self):
362        if self._default is not None:
363            return self._default
364        else:
365            return None
class CustomEnum(Field):
370class CustomEnum(Field):
371    def __init__(self, enum_type, default=None, required=False, required_default=False):
372        if not issubclass(enum_type, Enum):
373            raise Exception(enum_type + " is not a valid Enum type")
374        self.enum_type = enum_type
375        self.values = {}
376        for x in enum_type.__members__.values():
377            self.values[x.value] = x
378        super(CustomEnum, self).__init__(default, required, required_default)
379
380    def type(self):
381        return 'enum'
382
383    def python_type(self):
384        return self.enum_type
385
386    def validate_type(self, name, val):
387        if val is None:
388            return None
389
390        if type(val) is str:
391            # The enum was passed as a string, we need to check it against the possible values
392            if val in self.enum_type.__members__:
393                return self.enum_type.__members__[val]
394            else:
395                raise TypeError(
396                    "Invalid enum value '%s' for field '%s'. Expected: %s" % (val, name, self.enum_type.__members__.keys()))
397        elif type(val) is int:
398            # The enum was passed as an int, we need to check it against the possible values
399            if val in self.values:
400                return self.values[val]
401            else:
402                raise TypeError(
403                    "Invalid enum value '%s' for field '%s'. Expected: %s" % (val, name, self.values.keys()))
404        elif type(val) != self.python_type():
405            raise TypeError("Invalid type '%s' for field '%s'. Expected: %s" % (type(val), name, self.python_type()))
406        else:
407            return val
408
409    def schema(self):
410        return self.schema_info(set())
411
412    def schema_info(self, defined_names):
413        if self.enum_type.__name__ in defined_names:
414            return self.enum_type.__name__
415        defined_names.add(self.enum_type.__name__)
416        return {
417            'type': self.type(),
418            'name': self.enum_type.__name__,
419            'symbols': [x.name for x in self.enum_type]
420        }
421
422    def default(self):
423        if self._default is not None:
424            return self._default
425        else:
426            return None
CustomEnum(enum_type, default=None, required=False, required_default=False)
371    def __init__(self, enum_type, default=None, required=False, required_default=False):
372        if not issubclass(enum_type, Enum):
373            raise Exception(enum_type + " is not a valid Enum type")
374        self.enum_type = enum_type
375        self.values = {}
376        for x in enum_type.__members__.values():
377            self.values[x.value] = x
378        super(CustomEnum, self).__init__(default, required, required_default)
def type(self):
380    def type(self):
381        return 'enum'
def python_type(self):
383    def python_type(self):
384        return self.enum_type
def validate_type(self, name, val):
386    def validate_type(self, name, val):
387        if val is None:
388            return None
389
390        if type(val) is str:
391            # The enum was passed as a string, we need to check it against the possible values
392            if val in self.enum_type.__members__:
393                return self.enum_type.__members__[val]
394            else:
395                raise TypeError(
396                    "Invalid enum value '%s' for field '%s'. Expected: %s" % (val, name, self.enum_type.__members__.keys()))
397        elif type(val) is int:
398            # The enum was passed as an int, we need to check it against the possible values
399            if val in self.values:
400                return self.values[val]
401            else:
402                raise TypeError(
403                    "Invalid enum value '%s' for field '%s'. Expected: %s" % (val, name, self.values.keys()))
404        elif type(val) != self.python_type():
405            raise TypeError("Invalid type '%s' for field '%s'. Expected: %s" % (type(val), name, self.python_type()))
406        else:
407            return val
def schema(self):
409    def schema(self):
410        return self.schema_info(set())
def schema_info(self, defined_names):
412    def schema_info(self, defined_names):
413        if self.enum_type.__name__ in defined_names:
414            return self.enum_type.__name__
415        defined_names.add(self.enum_type.__name__)
416        return {
417            'type': self.type(),
418            'name': self.enum_type.__name__,
419            'symbols': [x.name for x in self.enum_type]
420        }
def default(self):
422    def default(self):
423        if self._default is not None:
424            return self._default
425        else:
426            return None
Inherited Members
Field
required_default
class Array(Field):
429class Array(Field):
430    def __init__(self, array_type, default=None, required=False, required_default=False):
431        _check_record_or_field(array_type)
432        self.array_type = array_type
433        super(Array, self).__init__(default=default, required=required, required_default=required_default)
434
435    def type(self):
436        return 'array'
437
438    def python_type(self):
439        return list
440
441    def validate_type(self, name, val):
442        if val is None:
443            return None
444
445        super(Array, self).validate_type(name, val)
446
447        for x in val:
448            if type(x) != self.array_type.python_type():
449                raise TypeError('Array field ' + name + ' items should all be of type '
450                                + self.array_type.python_type())
451        return val
452
453    def schema(self):
454        return self.schema_info(set())
455
456    def schema_info(self, defined_names):
457        return {
458            'type': self.type(),
459            'items': self.array_type.schema_info(defined_names) if isinstance(self.array_type, (Array, Map, Record))
460                else self.array_type.type()
461        }
462
463    def default(self):
464        if self._default is not None:
465            return self._default
466        else:
467            return None
Array(array_type, default=None, required=False, required_default=False)
430    def __init__(self, array_type, default=None, required=False, required_default=False):
431        _check_record_or_field(array_type)
432        self.array_type = array_type
433        super(Array, self).__init__(default=default, required=required, required_default=required_default)
def type(self):
435    def type(self):
436        return 'array'
def python_type(self):
438    def python_type(self):
439        return list
def validate_type(self, name, val):
441    def validate_type(self, name, val):
442        if val is None:
443            return None
444
445        super(Array, self).validate_type(name, val)
446
447        for x in val:
448            if type(x) != self.array_type.python_type():
449                raise TypeError('Array field ' + name + ' items should all be of type '
450                                + self.array_type.python_type())
451        return val
def schema(self):
453    def schema(self):
454        return self.schema_info(set())
def schema_info(self, defined_names):
456    def schema_info(self, defined_names):
457        return {
458            'type': self.type(),
459            'items': self.array_type.schema_info(defined_names) if isinstance(self.array_type, (Array, Map, Record))
460                else self.array_type.type()
461        }
def default(self):
463    def default(self):
464        if self._default is not None:
465            return self._default
466        else:
467            return None
Inherited Members
Field
required_default
class Map(Field):
470class Map(Field):
471    def __init__(self, value_type, default=None, required=False, required_default=False):
472        _check_record_or_field(value_type)
473        self.value_type = value_type
474        super(Map, self).__init__(default=default, required=required, required_default=required_default)
475
476    def type(self):
477        return 'map'
478
479    def python_type(self):
480        return dict
481
482    def validate_type(self, name, val):
483        if val is None:
484            return None
485
486        super(Map, self).validate_type(name, val)
487
488        for k, v in val.items():
489            if type(k) != str and not is_unicode(k):
490                raise TypeError('Map keys for field ' + name + '  should all be strings')
491            if type(v) != self.value_type.python_type():
492                raise TypeError('Map values for field ' + name + ' should all be of type '
493                                + self.value_type.python_type())
494
495        return val
496
497    def schema(self):
498        return self.schema_info(set())
499
500    def schema_info(self, defined_names):
501        return {
502            'type': self.type(),
503            'values': self.value_type.schema_info(defined_names) if isinstance(self.value_type, (Array, Map, Record))
504                else self.value_type.type()
505        }
506
507    def default(self):
508        if self._default is not None:
509            return self._default
510        else:
511            return None
Map(value_type, default=None, required=False, required_default=False)
471    def __init__(self, value_type, default=None, required=False, required_default=False):
472        _check_record_or_field(value_type)
473        self.value_type = value_type
474        super(Map, self).__init__(default=default, required=required, required_default=required_default)
def type(self):
476    def type(self):
477        return 'map'
def python_type(self):
479    def python_type(self):
480        return dict
def validate_type(self, name, val):
482    def validate_type(self, name, val):
483        if val is None:
484            return None
485
486        super(Map, self).validate_type(name, val)
487
488        for k, v in val.items():
489            if type(k) != str and not is_unicode(k):
490                raise TypeError('Map keys for field ' + name + '  should all be strings')
491            if type(v) != self.value_type.python_type():
492                raise TypeError('Map values for field ' + name + ' should all be of type '
493                                + self.value_type.python_type())
494
495        return val
def schema(self):
497    def schema(self):
498        return self.schema_info(set())
def schema_info(self, defined_names):
500    def schema_info(self, defined_names):
501        return {
502            'type': self.type(),
503            'values': self.value_type.schema_info(defined_names) if isinstance(self.value_type, (Array, Map, Record))
504                else self.value_type.type()
505        }
def default(self):
507    def default(self):
508        if self._default is not None:
509            return self._default
510        else:
511            return None
Inherited Members
Field
required_default
def is_unicode(x):
516def is_unicode(x):
517    return 'encode' in dir(x) and type(x.encode()) == str