コード例 #1
0
    def drf_meta_fields(meta_node):
        def resolve_fields(fields_node, read_only=False):
            fields = []
            known_types = [ast.Tuple, ast.List, ast.Set]

            if isinstance(fields_node, ast.BinOp):
                assert isinstance(fields_node.op, ast.Add)
                # if either is Attribute, resolve_fields returns [] which is fine
                # since it will be handled by the logic in bases
                return resolve_fields(fields_node.left) + resolve_fields(
                    fields_node.right)

            if any(isinstance(fields_node, t) for t in known_types):
                for field_node in fields_node.elts:
                    field = Field(field_name=Resolver.resolve(field_node),
                                  read_only=read_only)

                    fields.append(field)

            return fields

        fields = Fields()

        for node in meta_node.body:
            if not isinstance(node, ast.Assign):
                continue

            lhs, rhs = Resolver.resolve(node)

            if lhs == 'fields':
                fields.extend(resolve_fields(rhs))
            elif lhs == 'read_only_fields':
                fields.extend(resolve_fields(rhs, read_only=True))

        return fields
コード例 #2
0
    def find_serializer_fields(self, serializer_name):
        nodes = self.serializer_registry.nodes

        if serializer_name in self.memo_dict:
            return self.memo_dict[serializer_name]

        class_node = nodes[serializer_name]
        fields = Fields()
        init_node = None

        # Look at own class variables first, this trumps everything else
        for node in class_node.body:
            if self.is_class_var(node):
                # explicit class var trumps Meta
                fields.add(Resolver.drf_field_assignment(node), overwrite=True)
            elif self.is_meta(node):
                fields.extend(Resolver.drf_meta_fields(node))
            elif self.is_init_method(node):
                init_node = node

        # add fields from bases, in left to right order. The bases of the base
        # trumps the neighbour of the base if there's overlap.
        for base in class_node.bases:
            base = Resolver.resolve(base)

            if base == 'object':
                continue

            if base not in nodes:
                # TODO: ???
                continue

            base_class_vars = self.find_serializer_fields(base)
            fields.extend(base_class_vars)

        # Check for dynamic fields that were inherited from direct ancestors.
        # TODO: Find a better way to support inheritance
        parent_in_dynamic_fields = any(
            getattr(parent_class, 'attr', None) in self.dynamic_fields
            or getattr(parent_class, 'id', None) in self.dynamic_fields
            for parent_class in class_node.bases)

        # dynamic fields trump or augment existing fields
        if serializer_name in self.dynamic_fields or parent_in_dynamic_fields:
            if init_node:
                dynamic_fields = Resolver.init_method(init_node)
                for field_name, field in dynamic_fields.iteritems():
                    if field_name not in fields:
                        fields.add(field)
                        continue

                    previous_field = fields[field_name]
                    augmented_field = self.augment_field(previous_field, field)
                    fields.add(augmented_field, overwrite=True)

        self.memo_dict[serializer_name] = fields

        return fields
コード例 #3
0
    def find_serializer_fields(self, serializer_name):
        nodes = self.serializer_registry.nodes

        if serializer_name in self.memo_dict:
            return self.memo_dict[serializer_name]

        class_node = nodes[serializer_name]
        fields = Fields()
        init_node = None

        # Look at own class variables first, this trumps everything else
        for node in class_node.body:
            if self.is_class_var(node):
                # explicit class var trumps Meta
                fields.add(Resolver.class_var_drf_field(node), overwrite=True)
            elif self.is_meta(node):
                fields.extend(Resolver.drf_meta_fields(node))
            elif self.is_init_method(node):
                init_node = node

        # add fields from bases, in left to right order. The bases of the base
        # trumps the neighbour of the base if there's overlap.
        for base in class_node.bases:
            base = Resolver.resolve(base)

            if base == 'object':
                continue

            if base not in nodes:
                # TODO: ???
                continue

            base_class_vars = self.find_serializer_fields(base)
            fields.extend(base_class_vars)

        # dynamic fields trump or augment existing fields
        if serializer_name in self.dynamic_fields:
            if not init_node:
                msg = ('Did not find __init__ in {} but view specifies dynamic'
                       ' fields.').format(serializer_name)
                raise Exception(msg)

            dynamic_fields = Resolver.init_method(node)
            for field in dynamic_fields:
                if field not in fields:
                    fields.add(field)
                    continue

                previous_field = fields[field['field_name']]
                augmented_field = self.augment_field(previous_field, field)
                fields.add(augmented_field, overwrite=True)

        self.memo_dict[serializer_name] = fields

        return fields