<s> """<STR_LIT>""" <EOL> import copy <EOL> import inflection <EOL> from django . db import models <EOL> from django . utils import six <EOL> from django . utils . functional import cached_property <EOL> from rest_framework import exceptions , fields , serializers <EOL> from rest_framework . fields import SkipField <EOL> from rest_framework . utils . serializer_helpers import ReturnDict , ReturnList <EOL> from dynamic_rest . bases import DynamicSerializerBase <EOL> from dynamic_rest . conf import settings <EOL> from dynamic_rest . fields import DynamicRelationField <EOL> from dynamic_rest . links import merge_link_object <EOL> from dynamic_rest . meta import get_model_table <EOL> from dynamic_rest . processors import SideloadingProcessor <EOL> from dynamic_rest . tagged import tag_dict <EOL> class WithResourceKeyMixin ( object ) : <EOL> def get_resource_key ( self ) : <EOL> """<STR_LIT>""" <EOL> model = self . get_model ( ) <EOL> if model : <EOL> return get_model_table ( model ) <EOL> else : <EOL> return self . get_name ( ) <EOL> class DynamicListSerializer ( WithResourceKeyMixin , serializers . ListSerializer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( DynamicListSerializer , self ) . __init__ ( * args , ** kwargs ) <EOL> self . child . parent = self <EOL> def to_representation ( self , data ) : <EOL> iterable = data . all ( ) if isinstance ( data , models . Manager ) else data <EOL> return [ self . child . to_representation ( item ) for item in iterable ] <EOL> def get_model ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . child . get_model ( ) <EOL> def get_name ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . child . get_name ( ) <EOL> def get_plural_name ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . child . get_plural_name ( ) <EOL> def id_only ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . child . id_only ( ) <EOL> @ property <EOL> def data ( self ) : <EOL> """<STR_LIT>""" <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> data = super ( DynamicListSerializer , self ) . data <EOL> if self . child . sideload : <EOL> self . _sideloaded_data = ReturnDict ( <EOL> SideloadingProcessor ( <EOL> self , <EOL> data <EOL> ) . data , <EOL> serializer = self <EOL> ) <EOL> else : <EOL> self . _sideloaded_data = ReturnList ( data , serializer = self ) <EOL> return self . _sideloaded_data <EOL> class WithDynamicSerializerMixin ( WithResourceKeyMixin , DynamicSerializerBase ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> meta = getattr ( cls , '<STR_LIT:Meta>' , None ) <EOL> if not meta : <EOL> meta = type ( '<STR_LIT:Meta>' , ( ) , { } ) <EOL> cls . Meta = meta <EOL> meta . list_serializer_class = DynamicListSerializer <EOL> return super ( <EOL> WithDynamicSerializerMixin , cls <EOL> ) . __new__ ( <EOL> cls , * args , ** kwargs <EOL> ) <EOL> def __init__ ( <EOL> self , <EOL> instance = None , <EOL> data = fields . empty , <EOL> only_fields = None , <EOL> include_fields = None , <EOL> exclude_fields = None , <EOL> request_fields = None , <EOL> sideload = False , <EOL> dynamic = True , <EOL> embed = False , <EOL> ** kwargs <EOL> ) : <EOL> """<STR_LIT>""" <EOL> name = self . get_name ( ) <EOL> if data is not fields . empty and name in data and len ( data ) == <NUM_LIT:1> : <EOL> data = data [ name ] <EOL> if data is not fields . empty : <EOL> for field_name , field in six . iteritems ( self . get_all_fields ( ) ) : <EOL> if ( <EOL> field . allow_null is False and field . required is False and <EOL> field_name in data and data [ field_name ] is None <EOL> ) : <EOL> data . pop ( field_name ) <EOL> kwargs [ '<STR_LIT>' ] = instance <EOL> kwargs [ '<STR_LIT:data>' ] = data <EOL> super ( WithDynamicSerializerMixin , self ) . __init__ ( ** kwargs ) <EOL> self . sideload = sideload <EOL> self . dynamic = dynamic <EOL> self . request_fields = request_fields or { } <EOL> self . embed = embed <EOL> self . _dynamic_init ( only_fields , include_fields , exclude_fields ) <EOL> self . enable_optimization = settings . ENABLE_SERIALIZER_OPTIMIZATIONS <EOL> def _dynamic_init ( self , only_fields , include_fields , exclude_fields ) : <EOL> """<STR_LIT>""" <EOL> if not self . dynamic : <EOL> return <EOL> if ( <EOL> isinstance ( self . request_fields , dict ) <EOL> and self . request_fields . pop ( '<STR_LIT:*>' , None ) is False <EOL> ) : <EOL> exclude_fields = '<STR_LIT:*>' <EOL> only_fields = set ( only_fields or [ ] ) <EOL> include_fields = include_fields or [ ] <EOL> exclude_fields = exclude_fields or [ ] <EOL> all_fields = set ( self . get_all_fields ( ) . keys ( ) ) <EOL> if only_fields : <EOL> exclude_fields = '<STR_LIT:*>' <EOL> include_fields = only_fields <EOL> if exclude_fields == '<STR_LIT:*>' : <EOL> include_fields = set ( <EOL> list ( include_fields ) + [ <EOL> field for field , val in six . iteritems ( self . request_fields ) <EOL> if val or val == { } <EOL> ] <EOL> ) <EOL> exclude_fields = all_fields - include_fields <EOL> elif include_fields == '<STR_LIT:*>' : <EOL> include_fields = all_fields <EOL> for name in exclude_fields : <EOL> self . request_fields [ name ] = False <EOL> for name in include_fields : <EOL> if not isinstance ( self . request_fields . get ( name ) , dict ) : <EOL> self . request_fields [ name ] = True <EOL> @ classmethod <EOL> def get_model ( cls ) : <EOL> """<STR_LIT>""" <EOL> return None <EOL> @ classmethod <EOL> def get_name ( cls ) : <EOL> """<STR_LIT>""" <EOL> if not hasattr ( cls . Meta , '<STR_LIT:name>' ) : <EOL> class_name = getattr ( cls . get_model ( ) , '<STR_LIT>' , None ) <EOL> setattr ( <EOL> cls . Meta , <EOL> '<STR_LIT:name>' , <EOL> inflection . underscore ( class_name ) if class_name else None <EOL> ) <EOL> return cls . Meta . name <EOL> @ classmethod <EOL> def get_plural_name ( cls ) : <EOL> """<STR_LIT>""" <EOL> if not hasattr ( cls . Meta , '<STR_LIT>' ) : <EOL> setattr ( <EOL> cls . Meta , <EOL> '<STR_LIT>' , <EOL> inflection . pluralize ( cls . get_name ( ) ) <EOL> ) <EOL> return cls . Meta . plural_name <EOL> def get_all_fields ( self ) : <EOL> """<STR_LIT>""" <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _all_fields = super ( <EOL> WithDynamicSerializerMixin , <EOL> self <EOL> ) . get_fields ( ) <EOL> for k , field in six . iteritems ( self . _all_fields ) : <EOL> field . field_name = k <EOL> field . parent = self <EOL> return self . _all_fields <EOL> def _get_deferred_field_names ( self , serializer_fields ) : <EOL> """<STR_LIT>""" <EOL> meta_deferred = set ( getattr ( self . Meta , '<STR_LIT>' , [ ] ) ) <EOL> return { <EOL> name for name , field in six . iteritems ( serializer_fields ) <EOL> if getattr ( field , '<STR_LIT>' , None ) is True or name in <EOL> meta_deferred <EOL> } <EOL> def get_fields ( self ) : <EOL> """<STR_LIT>""" <EOL> all_fields = self . get_all_fields ( ) <EOL> if self . dynamic is False : <EOL> return all_fields <EOL> if self . id_only ( ) : <EOL> return { } <EOL> serializer_fields = copy . deepcopy ( all_fields ) <EOL> request_fields = self . request_fields <EOL> deferred = self . _get_deferred_field_names ( serializer_fields ) <EOL> if request_fields : <EOL> for name , include in six . iteritems ( request_fields ) : <EOL> if name not in serializer_fields : <EOL> raise exceptions . ParseError ( <EOL> "<STR_LIT>" % <EOL> ( name , self . get_name ( ) ) ) <EOL> if include is not False and name in deferred : <EOL> deferred . remove ( name ) <EOL> elif include is False : <EOL> deferred . add ( name ) <EOL> for name in deferred : <EOL> serializer_fields . pop ( name ) <EOL> return serializer_fields <EOL> def get_link_fields ( self ) : <EOL> """<STR_LIT>""" <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> all_fields = self . get_all_fields ( ) <EOL> self . _link_fields = { <EOL> name : field for name , field in six . iteritems ( all_fields ) <EOL> if isinstance ( field , DynamicRelationField ) <EOL> and getattr ( field , '<STR_LIT>' , True ) <EOL> and not ( <EOL> name in self . fields <EOL> and not field . serializer . id_only ( ) <EOL> ) and not ( <EOL> name in self . fields <EOL> and not getattr ( field . serializer , '<STR_LIT>' , False ) <EOL> ) <EOL> } <EOL> return self . _link_fields <EOL> @ cached_property <EOL> def _readable_fields ( self ) : <EOL> return [ <EOL> field for field in self . fields . values ( ) <EOL> if not field . write_only <EOL> ] <EOL> def _faster_to_representation ( self , instance ) : <EOL> """<STR_LIT>""" <EOL> ret = { } <EOL> fields = self . _readable_fields <EOL> for field in fields : <EOL> try : <EOL> attribute = field . get_attribute ( instance ) <EOL> except SkipField : <EOL> continue <EOL> if attribute is None : <EOL> ret [ field . field_name ] = None <EOL> else : <EOL> ret [ field . field_name ] = field . to_representation ( attribute ) <EOL> return ret <EOL> def to_representation ( self , instance ) : <EOL> """<STR_LIT>""" <EOL> if self . id_only ( ) : <EOL> return instance . pk <EOL> else : <EOL> if self . enable_optimization : <EOL> representation = self . _faster_to_representation ( instance ) <EOL> else : <EOL> representation = super ( <EOL> WithDynamicSerializerMixin , <EOL> self <EOL> ) . to_representation ( instance ) <EOL> if settings . ENABLE_LINKS : <EOL> representation = merge_link_object ( <EOL> self , representation , instance <EOL> ) <EOL> return tag_dict ( <EOL> representation , <EOL> serializer = self , <EOL> instance = instance , <EOL> embed = self . embed <EOL> ) <EOL> def save ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> update = getattr ( self , '<STR_LIT>' , None ) is not None <EOL> instance = super ( <EOL> WithDynamicSerializerMixin , <EOL> self <EOL> ) . save ( <EOL> * args , <EOL> ** kwargs <EOL> ) <EOL> view = self . _context . get ( '<STR_LIT>' ) <EOL> if update and view : <EOL> instance = self . instance = view . get_object ( ) <EOL> return instance <EOL> def id_only ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . dynamic and self . request_fields is True <EOL> @ property <EOL> def data ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> data = super ( WithDynamicSerializerMixin , self ) . data <EOL> self . _sideloaded_data = ReturnDict ( <EOL> SideloadingProcessor ( <EOL> self , <EOL> data <EOL> ) . data if self . sideload else data , <EOL> serializer = self <EOL> ) <EOL> return self . _sideloaded_data <EOL> class WithDynamicModelSerializerMixin ( WithDynamicSerializerMixin ) : <EOL> """<STR_LIT>""" <EOL> @ classmethod <EOL> def get_model ( cls ) : <EOL> return cls . Meta . model <EOL> def get_id_fields ( self ) : <EOL> """<STR_LIT>""" <EOL> model = self . get_model ( ) <EOL> out = [ model . _meta . pk . name ] <EOL> for field in model . _meta . fields : <EOL> if isinstance ( field , models . ForeignKey ) : <EOL> out . append ( field . name + '<STR_LIT>' ) <EOL> return out <EOL> class DynamicModelSerializer ( <EOL> WithDynamicModelSerializerMixin , <EOL> serializers . ModelSerializer <EOL> ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> class EphemeralObject ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , values_dict ) : <EOL> if '<STR_LIT>' not in values_dict : <EOL> raise Exception ( "<STR_LIT>" ) <EOL> self . __dict__ . update ( values_dict ) <EOL> class DynamicEphemeralSerializer ( <EOL> WithDynamicSerializerMixin , <EOL> serializers . Serializer <EOL> ) : <EOL> """<STR_LIT>""" <EOL> def to_representation ( self , instance ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( instance , dict ) : <EOL> data = super ( <EOL> DynamicEphemeralSerializer , <EOL> self <EOL> ) . to_representation ( instance ) <EOL> else : <EOL> data = instance <EOL> instance = EphemeralObject ( data ) <EOL> if self . id_only ( ) : <EOL> return data <EOL> else : <EOL> return tag_dict ( data , serializer = self , instance = instance ) </s>
