def __new__(mcls, name, bases, attrs): model_parents = [ base for base in bases if isinstance(base, MongoModelMetaclass) ] # Only perform Model initialization steps if the class has inherited # from a Model base class (i.e. MongoModel/EmbeddedMongoModel). if not model_parents: return type.__new__(mcls, name, bases, attrs) new_attrs = {'__module__': attrs['__module__']} if '__classcell__' in attrs: new_attrs['__classcell__'] = attrs['__classcell__'] new_class = type.__new__(mcls, name, bases, new_attrs) # User-defined or inherited metadata meta = attrs.get('Meta', getattr(new_class, 'Meta', None)) # Allow the options class to be pluggable. # Pop it from attrs, since it's not useful in the final class. options_class = attrs.pop('_options_class', MongoOptions) options = options_class(meta) # Let the Options object take care of merging relevant options. new_class.add_to_class('_mongometa', options) # Add all attributes to class. for attr in attrs: new_class.add_to_class(attr, attrs[attr]) def should_inherit_field(parent_class, field): # Never shadow fields defined on the new class. if field.attname in new_class._mongometa.fields_attname_dict: return False # Never inherit an implicit primary key. if field.primary_key and parent_class._mongometa.implicit_id: return False return True # Also add fields from parents into the metadata. for base in model_parents: if hasattr(base, '_mongometa'): parent_fields = base._mongometa.get_fields() for field in parent_fields: if should_inherit_field(base, field): new_class.add_to_class(field.attname, field) # Discover and store class hierarchy for later. class_name = new_class._mongometa.object_name new_class._subclasses = set([class_name]) flattened_bases = new_class._get_bases(bases) for base in flattened_bases: if base._mongometa.final: raise InvalidModel('Cannot extend class %s, ' 'because it has been declared final.' % base._mongometa.object_name) base._subclasses.add(class_name) # Set the default collection name. if new_class._mongometa.collection_name is None: # If this class extends another custom MongoModel, use the same # collection. if flattened_bases: parent_cls = next(iter(flattened_bases)) parent_collection_name = parent_cls._mongometa.collection_name new_class._mongometa.collection_name = parent_collection_name else: new_class._mongometa.collection_name = snake_case(name) # Create model-specific Exception types. for exc_type in (errors.DoesNotExist, errors.MultipleObjectsReturned): exc_name = exc_type.__name__ parent_types = tuple( getattr(base, exc_name) for base in bases if hasattr(base, exc_name)) model_exc = type(exc_name, parent_types or (exc_type, ), {'__module__': attrs['__module__']}) new_class.add_to_class(exc_name, model_exc) # Add class to the registry. register_document(new_class) return new_class
def __new__(mcls, name, bases, attrs): model_parents = [ base for base in bases if isinstance(base, MongoModelMetaclass)] # Only perform Model initialization steps if the class has inherited # from a Model base class (i.e. MongoModel/EmbeddedMongoModel). if not model_parents: return type.__new__(mcls, name, bases, attrs) new_class = type.__new__( mcls, name, bases, {'__module__': attrs['__module__']}) # User-defined or inherited metadata meta = attrs.get('Meta', getattr(new_class, 'Meta', None)) options = MongoOptions(meta) # Let the Options object take care of merging relevant options. new_class.add_to_class('_mongometa', options) # Add all attributes to class. for attr in attrs: new_class.add_to_class(attr, attrs[attr]) def should_inherit_field(parent_class, field): # Never shadow fields defined on the new class. if field.attname in new_class._mongometa.fields_dict: return False # Never inherit an implicit primary key. if field.primary_key and parent_class._mongometa.implicit_id: return False return True # Also add fields from parents into the metadata. for base in model_parents: if hasattr(base, '_mongometa'): parent_fields = base._mongometa.get_fields() for field in parent_fields: if should_inherit_field(base, field): new_class.add_to_class(field.attname, field) # Discover and store class hierarchy for later. class_name = new_class._mongometa.object_name new_class._subclasses = set([class_name]) flattened_bases = new_class._get_bases(bases) for base in flattened_bases: if base._mongometa.final: raise InvalidModel( 'Cannot extend class %s, ' 'because it has been declared final.' % base._mongometa.object_name) base._subclasses.add(class_name) # Set the default collection name. if new_class._mongometa.collection_name is None: # If this class extends another custom MongoModel, use the same # collection. if flattened_bases: parent_cls = next(iter(flattened_bases)) parent_collection_name = parent_cls._mongometa.collection_name new_class._mongometa.collection_name = parent_collection_name else: new_class._mongometa.collection_name = snake_case(name) # Create model-specific Exception types. for exc_type in (errors.DoesNotExist, errors.MultipleObjectsReturned): exc_name = exc_type.__name__ parent_types = tuple( getattr(base, exc_name) for base in bases if hasattr(base, exc_name)) model_exc = type( exc_name, parent_types or (exc_type,), {'__module__': attrs['__module__']}) new_class.add_to_class(exc_name, model_exc) # Add class to the registry. register_document(new_class) return new_class