<s> import copy <EOL> import inspect <EOL> from collections import OrderedDict <EOL> from functools import partial <EOL> import six <EOL> from . options import Options <EOL> class ClassTypeMeta ( type ) : <EOL> options_class = Options <EOL> def __new__ ( mcs , name , bases , attrs ) : <EOL> super_new = super ( ClassTypeMeta , mcs ) . __new__ <EOL> module = attrs . pop ( '<STR_LIT>' , None ) <EOL> doc = attrs . pop ( '<STR_LIT>' , None ) <EOL> new_class = super_new ( mcs , name , bases , { <EOL> '<STR_LIT>' : module , <EOL> '<STR_LIT>' : doc <EOL> } ) <EOL> attr_meta = attrs . pop ( '<STR_LIT:Meta>' , None ) <EOL> if not attr_meta : <EOL> meta = getattr ( new_class , '<STR_LIT:Meta>' , None ) <EOL> else : <EOL> meta = attr_meta <EOL> new_class . add_to_class ( '<STR_LIT>' , new_class . get_options ( meta ) ) <EOL> return mcs . construct ( new_class , bases , attrs ) <EOL> def get_options ( cls , meta ) : <EOL> return cls . options_class ( meta ) <EOL> def add_to_class ( cls , name , value ) : <EOL> if not inspect . isclass ( value ) and hasattr ( <EOL> value , '<STR_LIT>' ) : <EOL> value . contribute_to_class ( cls , name ) <EOL> else : <EOL> setattr ( cls , name , value ) <EOL> def construct ( cls , bases , attrs ) : <EOL> for obj_name , obj in attrs . items ( ) : <EOL> cls . add_to_class ( obj_name , obj ) <EOL> if not cls . _meta . abstract : <EOL> from . . types import List , NonNull <EOL> setattr ( cls , '<STR_LIT>' , partial ( NonNull , cls ) ) <EOL> setattr ( cls , '<STR_LIT>' , partial ( List , cls ) ) <EOL> return cls <EOL> class ClassType ( six . with_metaclass ( ClassTypeMeta ) ) : <EOL> class Meta : <EOL> abstract = True <EOL> @ classmethod <EOL> def internal_type ( cls , schema ) : <EOL> raise NotImplementedError ( "<STR_LIT>" . format ( cls ) ) <EOL> class FieldsOptions ( Options ) : <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( FieldsOptions , self ) . __init__ ( * args , ** kwargs ) <EOL> self . local_fields = [ ] <EOL> def add_field ( self , field ) : <EOL> self . local_fields . append ( field ) <EOL> @ property <EOL> def fields ( self ) : <EOL> return sorted ( self . local_fields ) <EOL> @ property <EOL> def fields_map ( self ) : <EOL> return OrderedDict ( [ ( f . attname , f ) for f in self . fields ] ) <EOL> @ property <EOL> def fields_group_type ( self ) : <EOL> from . . types . field import FieldsGroupType <EOL> return FieldsGroupType ( * self . local_fields ) <EOL> class FieldsClassTypeMeta ( ClassTypeMeta ) : <EOL> options_class = FieldsOptions <EOL> def extend_fields ( cls , bases ) : <EOL> new_fields = cls . _meta . local_fields <EOL> field_names = { f . attname : f for f in new_fields } <EOL> for base in bases : <EOL> if not isinstance ( base , FieldsClassTypeMeta ) : <EOL> continue <EOL> parent_fields = base . _meta . local_fields <EOL> for field in parent_fields : <EOL> if field . attname in field_names and field . type . __class__ != field_names [ <EOL> field . attname ] . type . __class__ : <EOL> raise Exception ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % ( <EOL> field . attname , <EOL> cls . __name__ , <EOL> field . __class__ , <EOL> base . __name__ , <EOL> field_names [ field . attname ] . __class__ ) <EOL> ) <EOL> new_field = copy . copy ( field ) <EOL> cls . add_to_class ( field . attname , new_field ) <EOL> def construct ( cls , bases , attrs ) : <EOL> cls = super ( FieldsClassTypeMeta , cls ) . construct ( bases , attrs ) <EOL> cls . extend_fields ( bases ) <EOL> return cls <EOL> class FieldsClassType ( six . with_metaclass ( FieldsClassTypeMeta , ClassType ) ) : <EOL> class Meta : <EOL> abstract = True <EOL> @ classmethod <EOL> def fields_internal_types ( cls , schema ) : <EOL> return schema . T ( cls . _meta . fields_group_type ) </s>
