<commit_before>import re
from enum import Enum


class AddressParts(Enum):
    """An enum containing all possible values for address parts"""
    name = 'N'
    organisation = 'O'
    street_address = 'A'
    dependent_locality = 'D'
    city = 'C'
    admin_area = 'S'
    postal_code = 'Z'
    sorting_code = 'X'

    # Country is special, since we made up this character ourselves.
    country = '0'

    @classmethod
    def significant(cls):
        """
        An ordered, reversed list of parts, so that the first item is the
        largest topological division. This also strips out postal and sorting
        code, since they're independent from all the others.
        """
        ordered_values = cls.__members__.values()
        reverse = reversed(list(ordered_values))
        return list(filter(lambda p: not p.name.endswith('_code'), reverse))


class InvalidAddressException(ValueError):
    pass


class FieldValue(object):
    def __init__(self, value, details, subs):
        self.value = value
        self.details = details
        self.subs = subs


class Address(object):
    """An address value.

    The Address class can save and validate a full address, from any of the
    countries specified in the specifications passed to it. These
    specifications should be generated by the generate.download module, as they
    adhere to Google's i18n imported values.

    Mostly, you'll want to use the `get_data()`, `get_field_types()` and
    `set_field()` methods. These three methods should allow you to create a
    form that dynamically responds to any data and shows only relevant form
    fields. You can then simply call `str(address)` to get a fully valid
    address string, which you could use to send emails, for example.
    """

    def __init__(self, specs, values=None):
        self.specs = specs
        self.defaults = FieldValue('', specs['details'], specs['subs'])

        self.fields = {}
        if values is not None:
            for field, value in values.items():
                self.set_field(field, value)

    def field_in_fmt(self, part):
        if part == AddressParts.country:
            return True

        data = self.get_specs()
        return '%{0}'.format(part.value) in data['fmt']

    def index_in_fmt(self, query_part):
        fmt = self.get_specs()['fmt']

        fmt_fields = []
        for substr in fmt.split('%')[1:]:
            c = substr[0]
            for part in AddressParts:
                if part.value == c:
                    fmt_fields.append(part)
                    break

        fmt_fields.append(AddressParts.country)

        return fmt_fields.index(query_part)

    def get_significant_fields(self):
        """
        Get a list of (key, value) objects of fields sorted by
        significance.
        """
        return sorted(
            filter(lambda f: not f[0].name.endswith('_code'),
                   self.fields.items()),
            key=lambda i: AddressParts.significant().index(i[0])
        )

    def get_specs(self):
        """Get an up-to-date list of specifications for the address.

        This returns a specs dict, based on the details of the filled in fields
        but falling back to the defaults from the specs. It takes the specs
        from the least significant field.
        """
        specs = self.defaults.details

        for field, value in self.get_significant_fields():
            specs.update(value.details)

        return specs

    def get_field_types(self):
        """Gets a list of currently known-about fields."""
        fields = []
        # add the country now, since it's always the first field to fill in
        fields.append({
            'key': AddressParts.country,
            'label': 'country',
            'options': {key: value.get('name', key)
                        for key, value in self.defaults.subs.items()},
        })
        data = self.get_specs()

        if 'fmt' not in data:
            return fields

        # we want only parts we have, by significance
        sig = [part for part in AddressParts.significant()
               if self.field_in_fmt(part)]

        for depth, part in enumerate(sig):
            # already have this
            if part == AddressParts.country:
                continue

            # we want to know if the "parent field" has choices for this field
            # because if it does, but no option is chosen yet, we can'ts how
            # the other fields
            options = None
            parent = depth - 1
            parent_part = sig[parent]

            if fields[parent]['options'] is not None and \
               parent_part not in self.fields:
                break

            # otherwise, if it is filled in, we only need to see if it has
            # options
            elif parent_part in self.fields:
                relevant = self.fields[parent_part]
                if len(relevant.subs) > 0:
                    options = {key: value.get('name', key)
                               for key, value in relevant.subs.items()}

            if part == AddressParts.admin_area:
                label = 'province'
            else:
                label = part.name.replace('_', ' ')
            label = relevant.details.get('state_name_type', label)

            fields.append({
                'key': part,
                'label': label,
                'options': options,
            })
        else:
            if self.field_in_fmt(AddressParts.postal_code):
                fields.append({
                    'key': AddressParts.postal_code,
                    'label': 'postal code',
                    'options': None,
                })
            if self.field_in_fmt(AddressParts.sorting_code):
                fields.append({
                    'key': AddressParts.sorting_code,
                    'label': 'sorting code',
                    'options': None,
                })<commit_msg>Get proper value for option dict<commit_after>import re
from enum import Enum


class AddressParts(Enum):
    """An enum containing all possible values for address parts"""
    name = 'N'
    organisation = 'O'
    street_address = 'A'
    dependent_locality = 'D'
    city = 'C'
    admin_area = 'S'
    postal_code = 'Z'
    sorting_code = 'X'

    # Country is special, since we made up this character ourselves.
    country = '0'

    @classmethod
    def significant(cls):
        """
        An ordered, reversed list of parts, so that the first item is the
        largest topological division. This also strips out postal and sorting
        code, since they're independent from all the others.
        """
        ordered_values = cls.__members__.values()
        reverse = reversed(list(ordered_values))
        return list(filter(lambda p: not p.name.endswith('_code'), reverse))


class InvalidAddressException(ValueError):
    pass


class FieldValue(object):
    def __init__(self, value, details, subs):
        self.value = value
        self.details = details
        self.subs = subs


class Address(object):
    """An address value.

    The Address class can save and validate a full address, from any of the
    countries specified in the specifications passed to it. These
    specifications should be generated by the generate.download module, as they
    adhere to Google's i18n imported values.

    Mostly, you'll want to use the `get_data()`, `get_field_types()` and
    `set_field()` methods. These three methods should allow you to create a
    form that dynamically responds to any data and shows only relevant form
    fields. You can then simply call `str(address)` to get a fully valid
    address string, which you could use to send emails, for example.
    """

    def __init__(self, specs, values=None):
        self.specs = specs
        self.defaults = FieldValue('', specs['details'], specs['subs'])

        self.fields = {}
        if values is not None:
            for field, value in values.items():
                self.set_field(field, value)

    def field_in_fmt(self, part):
        if part == AddressParts.country:
            return True

        data = self.get_specs()
        return '%{0}'.format(part.value) in data['fmt']

    def index_in_fmt(self, query_part):
        fmt = self.get_specs()['fmt']

        fmt_fields = []
        for substr in fmt.split('%')[1:]:
            c = substr[0]
            for part in AddressParts:
                if part.value == c:
                    fmt_fields.append(part)
                    break

        fmt_fields.append(AddressParts.country)

        return fmt_fields.index(query_part)

    def get_significant_fields(self):
        """
        Get a list of (key, value) objects of fields sorted by
        significance.
        """
        return sorted(
            filter(lambda f: not f[0].name.endswith('_code'),
                   self.fields.items()),
            key=lambda i: AddressParts.significant().index(i[0])
        )

    def get_specs(self):
        """Get an up-to-date list of specifications for the address.

        This returns a specs dict, based on the details of the filled in fields
        but falling back to the defaults from the specs. It takes the specs
        from the least significant field.
        """
        specs = self.defaults.details

        for field, value in self.get_significant_fields():
            specs.update(value.details)

        return specs

    def get_field_types(self):
        """Gets a list of currently known-about fields."""
        fields = []
        # add the country now, since it's always the first field to fill in
        fields.append({
            'key': AddressParts.country,
            'label': 'country',
            'options': {key: value.get('name', key)
                        for key, value in self.defaults.subs.items()},
        })
        data = self.get_specs()

        if 'fmt' not in data:
            return fields

        # we want only parts we have, by significance
        sig = [part for part in AddressParts.significant()
               if self.field_in_fmt(part)]

        for depth, part in enumerate(sig):
            # already have this
            if part == AddressParts.country:
                continue

            # we want to know if the "parent field" has choices for this field
            # because if it does, but no option is chosen yet, we can'ts how
            # the other fields
            options = None
            parent = depth - 1
            parent_part = sig[parent]

            if fields[parent]['options'] is not None and \
               parent_part not in self.fields:
                break

            # otherwise, if it is filled in, we only need to see if it has
            # options
            elif parent_part in self.fields:
                relevant = self.fields[parent_part]
                if len(relevant.subs) > 0:
                    options = {key: value['details'].get('name', key)
                               for key, value in relevant.subs.items()}

            if part == AddressParts.admin_area:
                label = 'province'
            else:
                label = part.name.replace('_', ' ')
            label = relevant.details.get('state_name_type', label)

            fields.append({
                'key': part,
                'label': label,
                'options': options,
            })
        else:
            if self.field_in_fmt(AddressParts.postal_code):
                fields.append({
                    'key': AddressParts.postal_code,
                    'label': 'postal code',
                    'options': None,
                })
            if self.field_in_fmt(AddressParts.sorting_code):
                fields.append({
                    'key': AddressParts.sorting_code,
                    'label': 'sorting code',
                    'options': None,
                })
{'fraction_non_alphanumeric': 0.09077181208053692, 'fraction_numerical': 0.0016778523489932886, 'mean_word_length': 1.8155408597071327, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5853427', 'n_tokens_mistral': 3206, 'n_tokens_neox': 3023, 'n_words': 1075}