# Path: select_multiple_field/codecs.py
# def decode_csv_to_list(encoded):
#     """
#     Decodes a delimiter separated string to a Python list
#     """
#     delimiter = getattr(
#         settings, 'SELECTMULTIPLEFIELD_DELIMITER', DEFAULT_DELIMITER)
#     if encoded == '':
#         return []
# 
#     decoded = sorted(set(encoded.split(delimiter)))
#     return decoded
# 
# Path: select_multiple_field/widgets.py
# class SelectMultipleField(widgets.SelectMultiple):
#     """Multiple select widget ready for jQuery multiselect.js"""
# 
#     allow_multiple_selected = True
# 
#     def render(self, name, value, attrs={}, choices=()):
#         rendered_attrs = {'class': HTML_ATTR_CLASS}
#         rendered_attrs.update(attrs)
#         if value is None:
#             value = []
# 
#         final_attrs = self.build_attrs(rendered_attrs, name=name)
#         # output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)]
#         output = [format_html('<select multiple="multiple"{0}>',
#                               flatatt(final_attrs))]
#         options = self.render_options(choices, value)
#         if options:
#             output.append(options)
# 
#         output.append('</select>')
#         return mark_safe('\n'.join(output))
# 
#     def value_from_datadict(self, data, files, name):
#         """
#         SelectMultipleField widget delegates processing of raw user data to
#         Django's SelectMultiple widget
# 
#         Returns list or None
#         """
#         return super(SelectMultipleField, self).value_from_datadict(
#             data, files, name)


from django.conf import settings
from django.core import validators
from django.forms import fields
from django.utils import six
from .codecs import decode_csv_to_list
from .widgets import SelectMultipleField
        coerce is bound to ModelField.to_python method when using
        ModelViewMixin, otherwise it returns what is passed (the identity
        function)

        empty_value is the value used to represent an empty field
        """
        self.max_length, self.max_choices = max_length, max_choices
        self.size, self.max_choices_attr = size, max_choices_attr
        self.coerce = kwargs.pop('coerce', lambda val: val)
        self.empty_value = kwargs.pop('empty_value', [])
        if not hasattr(self, 'empty_values'):
            self.empty_values = list(validators.EMPTY_VALUES)
        super(SelectMultipleFormField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        """
        Takes processed widget data as value, possibly a char string, and
        makes it into a Python list

        Returns a Python list

        Method also handles lists and strings
        """
        if (value == self.empty_value) or (value in self.empty_values):
            return self.empty_value

        if isinstance(value, six.string_types):
            if len(value) == 0:
                return []


# Path: select_multiple_field/codecs.py
# def decode_csv_to_list(encoded):
#     """
#     Decodes a delimiter separated string to a Python list
#     """
#     delimiter = getattr(
#         settings, 'SELECTMULTIPLEFIELD_DELIMITER', DEFAULT_DELIMITER)
#     if encoded == '':
#         return []
# 
#     decoded = sorted(set(encoded.split(delimiter)))
#     return decoded
# 
# Path: select_multiple_field/widgets.py
# class SelectMultipleField(widgets.SelectMultiple):
#     """Multiple select widget ready for jQuery multiselect.js"""
# 
#     allow_multiple_selected = True
# 
#     def render(self, name, value, attrs={}, choices=()):
#         rendered_attrs = {'class': HTML_ATTR_CLASS}
#         rendered_attrs.update(attrs)
#         if value is None:
#             value = []
# 
#         final_attrs = self.build_attrs(rendered_attrs, name=name)
#         # output = [u'<select multiple="multiple"%s>' % flatatt(final_attrs)]
#         output = [format_html('<select multiple="multiple"{0}>',
#                               flatatt(final_attrs))]
#         options = self.render_options(choices, value)
#         if options:
#             output.append(options)
# 
#         output.append('</select>')
#         return mark_safe('\n'.join(output))
# 
#     def value_from_datadict(self, data, files, name):
#         """
#         SelectMultipleField widget delegates processing of raw user data to
#         Django's SelectMultiple widget
# 
#         Returns list or None
#         """
#         return super(SelectMultipleField, self).value_from_datadict(
#             data, files, name)


# Path: select_multiple_field/forms.py
from django.conf import settings
from django.core import validators
from django.forms import fields
from django.utils import six
from .codecs import decode_csv_to_list
from .widgets import SelectMultipleField

        coerce is bound to ModelField.to_python method when using
        ModelViewMixin, otherwise it returns what is passed (the identity
        function)

        empty_value is the value used to represent an empty field
        """
        self.max_length, self.max_choices = max_length, max_choices
        self.size, self.max_choices_attr = size, max_choices_attr
        self.coerce = kwargs.pop('coerce', lambda val: val)
        self.empty_value = kwargs.pop('empty_value', [])
        if not hasattr(self, 'empty_values'):
            self.empty_values = list(validators.EMPTY_VALUES)
        super(SelectMultipleFormField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        """
        Takes processed widget data as value, possibly a char string, and
        makes it into a Python list

        Returns a Python list

        Method also handles lists and strings
        """
        if (value == self.empty_value) or (value in self.empty_values):
            return self.empty_value

        if isinstance(value, six.string_types):
            if len(value) == 0:
                return []


            native = decode_csv_to_list(value)