def _generate_union_class_custom_annotations(self, ns, data_type):
        """
        The _process_custom_annotations function allows client code to access
        custom annotations defined in the spec.
        """
        self.emit('def _process_custom_annotations(self, annotation_type, field_path, processor):')
        with self.indent(), emit_pass_if_nothing_emitted(self):
            self.emit(
                (
                    'super({}, self)._process_custom_annotations(annotation_type, field_path, '
                    'processor)'
                ).format(class_name_for_data_type(data_type))
            )
            self.emit()

            for field in data_type.fields:
                recursive_processors = list(self._generate_custom_annotation_processors(
                    ns, field.data_type, field.custom_annotations))

                # check if we have any annotations that apply to this field at all
                if len(recursive_processors) == 0:
                    continue

                field_name = fmt_func(field.name)
                self.emit('if self.is_{}():'.format(field_name))

                with self.indent():
                    for annotation_type, processor in recursive_processors:
                        annotation_class = class_name_for_annotation_type(annotation_type, ns)
                        self.emit('if annotation_type is {}:'.format(annotation_class))
                        with self.indent():
                            self.emit('self._value = {}'.format(
                                generate_func_call(
                                    processor,
                                    args=[
                                        "'{{}}.{}'.format(field_path)".format(field_name),
                                        'self._value',
                                    ])
                            ))
                        self.emit()
The _process_custom_annotations function allows client code to access
        custom annotations defined in the spec.