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_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
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
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
Inherited Members
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
Inherited Members
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
Inherited Members
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
Inherited Members
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
Inherited Members
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
Inherited Members
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
Inherited Members
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
Inherited Members
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
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_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 }
Inherited Members
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
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
Inherited Members
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
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
Inherited Members
def
is_unicode(x):