<filename>app/api/util/dto.py
""" Data schemas """

from marshmallow import Schema, fields, validate, pre_load


class BaseSchema(Schema):
    """ Schema options that are universal to all schema classes """

    class Meta:
        """Schema options"""
        # maintains the field ordering on output
        ordered = True


class PartySchema(BaseSchema):
    """
    Party schema mapped onto Party() class attributes
    """
    party_id = fields.Integer(dump_only=True, attribute='id')
    party_name = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=4,
                error="Party name does not meet minimum length of 4 letters."),
            validate.Regexp(
                r'[a-zA-Z]',
                error="Party name cannot contain number(s).")])
    hq_address = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=1,
                error="Please provide party Headquarters address.")])
    logo_url = fields.URL(required=True)

    @pre_load
    def lower_cased(self, data):
        """return the input names as lower case

        Args:
            data (dict): data list to get the input field

        Returns:
            dict: input field party name in lower case
        """

        data["party_name"] = data["party_name"].lower()
        return data


class OfficeSchema(BaseSchema):
    """
    Office schema mapped onto Office() class attributes
    """
    office_id = fields.Integer(dump_only=True, attribute='id')
    office_name = fields.Str(
        required=True,
        validate=[
            validate.OneOf(
                ('president', 'governor', 'senator',
                 'house of representatives'),
                error="{input} not a valid office name. Try one of these {choices}.")
        ]
    )
    office_type = fields.Str(
        required=True,
        validate=[
            validate.OneOf(
                ('federal', 'congress', 'state'),
                error="{input} not a valid office type. Try one of these {choices}.")
        ]
    )
    is_occupied = fields.Boolean(missing=False)

    @pre_load(pass_many=True)
    def lower_cased(self, data, many):
        """return the input names as lower case

        Args:
            data (dict): data list with
            many : instructs marshmallow to expect more than one input field

        Returns:
            dict: input fields in lower case
        """

        data["office_name"] = data["office_name"].lower()
        data["office_type"] = data["office_type"].lower()
        return data


class UserSchema(BaseSchema):
    """
    User schema mapped on User class attributes
    """
    firstname = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=2,
                error="{input} is not a valid person's name."),
            validate.Regexp(
                r'^[a-zA-Z]*$',
                error="Person name cannot contain number(s).")])
    lastname = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=2,
                error="{input} is not a valid person's name."),
            validate.Regexp(
                r'^[a-zA-Z]*$',
                error="Person name cannot contain number(s).")])
    othername = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=2,
                error="{input} is not a valid person's name."),
            validate.Regexp(
                r'^[a-zA-Z]*$',
                error="Person name cannot contain number(s).")])
    email = fields.Email(required=True)
    phonenumber = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=10,
                error="{input} is not a valid phonename.")])
    password = fields.String(required=True)
    passporturl = fields.Url(required=True, data_key='passportUrl')
    isadmin = fields.Boolean(missing=False, data_key='isAdmin')
    ispolitician = fields.Boolean(missing=False, data_key='isPolitician')


class AuthSchema(BaseSchema):
    """
    User login data schema
    """
    email = fields.Email(required=True)
    password = fields.String(required=True)


class CandidateSchemaLoad(Schema):
    """
    Candidate schema mapped onto Candidate class attributes
    """
    candidate = fields.Integer(required=True)
    party = fields.Integer(required=True)


class CandidateSchemaDump(BaseSchema):
    """
    Candidate schema dump mapped onto database attributes
    """
    candidate = fields.Integer(attribute='candidate_id')
    office = fields.Integer(attribute='office_id')
    party = fields.Integer(attribute='party_id')
    registered_on = fields.LocalDateTime(attribute='created_on')


class VoteSchemaLoad(BaseSchema):
    """Vote schema for de-serializing vote data input """
    office = fields.Integer()
    candidate = fields.Integer()


class VoteSchemaDump(BaseSchema):
    """ Vote schema for serializing vote data output """
    office = fields.Integer(attribute='office_id')
    candidate = fields.Integer(attribute='candidate_id')
    created_on = fields.LocalDateTime()
    created_by = fields.Integer()


class ResultSchema(BaseSchema):
    """ Office results schema for serializing office results set """
    office = fields.Integer(attribute='office_id')
    candidate = fields.Integer(attribute='candidate_id')
    result = fields.Integer()


class PetitionLoadSchema(BaseSchema):
    """ Petition deserializer schema """
    office = fields.Integer(required=True)
    contested_by = fields.Integer(required=True)
    created_by = fields.Integer(dump_only=True)
    body = fields.String(required=True)
    evidence = fields.List(fields.Url())


class PetitionDumpSchema(BaseSchema):
    """ Petition serializer schema """
    petition_id = fields.Integer(attribute="id")
    office = fields.Integer(attribute="office_id")
    contested_by = fields.Integer()
    created_by = fields.Integer()
    created_on = fields.LocalDateTime()
    body = fields.String()
    evidence = fields.List(fields.Url())


class ApplicationLoadSchema(BaseSchema):
    """ Application deserializer schema """
    party = fields.String(required=True)
    office = fields.String(required=True)

    @pre_load(pass_many=True)
    def lower_cased(self, data, many):
        """return the input names as lower case prevents a party or
        office from not been been found because of mismatch in case

        Args:
            data (dict): data list with
            many : instructs marshmallow to expect more than one input field

        Returns:
            dict: input fields in lower case
        """

        data["party"] = data["party"].lower()
        data["office"] = data["office"].lower()
        return data


class ApplicationDumpSchema(BaseSchema):
    """ Application serializer schema """
    party = fields.Integer(attribute="party_id")
    office = fields.Integer(attribute="office_id")
    createdBy = fields.Integer(attribute="applicant_id")
    approved = fields.Boolean()
    requested_on = fields.LocalDateTime()


party_schema = PartySchema()
parties_schema = PartySchema(many=True)
office_schema = OfficeSchema()
offices_schema = OfficeSchema(many=True)
user_schema = UserSchema()
auth_schema = AuthSchema()
candidate_load_schema = CandidateSchemaLoad()
candidate_dump_schema = CandidateSchemaDump()
vote_load_schema = VoteSchemaLoad()
vote_dump_schema = VoteSchemaDump()
results_schema = ResultSchema(many=True)
petition_load_schema = PetitionLoadSchema()
petitions_dump_schema = PetitionDumpSchema()
application_load_schema = ApplicationLoadSchema()
application_dump_schema = ApplicationDumpSchema()

<filename>app/api/util/dto.py
""" Data schemas """

from marshmallow import Schema, fields, validate, pre_load


class BaseSchema(Schema):
    """ Schema options that are universal to all schema classes """

    class Meta:
        """Schema options"""
        # maintains the field ordering on output
        ordered = True


class PartySchema(BaseSchema):
    """
    Party schema mapped onto Party() class attributes
    """
    party_id = fields.Integer(dump_only=True, attribute='id')
    party_name = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=4,
                error="Party name does not meet minimum length of 4 letters."),
            validate.Regexp(
                r'[a-zA-Z]',
                error="Party name cannot contain number(s).")])
    hq_address = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=1,
                error="Please provide party Headquarters address.")])
    logo_url = fields.URL(required=True)

    @pre_load
    def lower_cased(self, data):
        """return the input names as lower case

        Args:
            data (dict): data list to get the input field

        Returns:
            dict: input field party name in lower case
        """

        data["party_name"] = data["party_name"].lower()
        return data


class OfficeSchema(BaseSchema):
    """
    Office schema mapped onto Office() class attributes
    """
    office_id = fields.Integer(dump_only=True, attribute='id')
    office_name = fields.Str(
        required=True,
        validate=[
            validate.OneOf(
                ('president', 'governor', 'senator',
                 'house of representatives'),
                error="{input} not a valid office name. Try one of these {choices}.")
        ]
    )
    office_type = fields.Str(
        required=True,
        validate=[
            validate.OneOf(
                ('federal', 'congress', 'state'),
                error="{input} not a valid office type. Try one of these {choices}.")
        ]
    )
    is_occupied = fields.Boolean(missing=False)

    @pre_load(pass_many=True)
    def lower_cased(self, data, many):
        """return the input names as lower case

        Args:
            data (dict): data list with
            many : instructs marshmallow to expect more than one input field

        Returns:
            dict: input fields in lower case
        """

        data["office_name"] = data["office_name"].lower()
        data["office_type"] = data["office_type"].lower()
        return data


class UserSchema(BaseSchema):
    """
    User schema mapped on User class attributes
    """
    firstname = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=2,
                error="{input} is not a valid person's name."),
            validate.Regexp(
                r'^[a-zA-Z]*$',
                error="Person name cannot contain number(s).")])
    lastname = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=2,
                error="{input} is not a valid person's name."),
            validate.Regexp(
                r'^[a-zA-Z]*$',
                error="Person name cannot contain number(s).")])
    othername = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=2,
                error="{input} is not a valid person's name."),
            validate.Regexp(
                r'^[a-zA-Z]*$',
                error="Person name cannot contain number(s).")])
    email = fields.Email(required=True)
    phonenumber = fields.String(
        required=True,
        validate=[
            validate.Length(
                min=10,
                error="{input} is not a valid phonename.")])
    password = fields.String(required=True)
    passporturl = fields.Url(required=True, data_key='passportUrl')
    isadmin = fields.Boolean(missing=False, data_key='isAdmin')
    ispolitician = fields.Boolean(missing=False, data_key='isPolitician')


class AuthSchema(BaseSchema):
    """
    User login data schema
    """
    email = fields.Email(required=True)
    password = fields.String(required=True)


class CandidateSchemaLoad(Schema):
    """
    Candidate schema mapped onto Candidate class attributes
    """
    candidate = fields.Integer(required=True)
    party = fields.Integer(required=True)


class CandidateSchemaDump(BaseSchema):
    """
    Candidate schema dump mapped onto database attributes
    """
    candidate = fields.Integer(attribute='candidate_id')
    office = fields.Integer(attribute='office_id')
    party = fields.Integer(attribute='party_id')
    registered_on = fields.LocalDateTime(attribute='created_on')


class VoteSchemaLoad(BaseSchema):
    """Vote schema for de-serializing vote data input """
    office = fields.Integer()
    candidate = fields.Integer()


class VoteSchemaDump(BaseSchema):
    """ Vote schema for serializing vote data output """
    office = fields.Integer(attribute='office_id')
    candidate = fields.Integer(attribute='candidate_id')
    created_on = fields.LocalDateTime()
    created_by = fields.Integer()


class ResultSchema(BaseSchema):
    """ Office results schema for serializing office results set """
    office = fields.Integer(attribute='office_id')
    candidate = fields.Integer(attribute='candidate_id')
    result = fields.Integer()


class PetitionLoadSchema(BaseSchema):
    """ Petition deserializer schema """
    office = fields.Integer(required=True)
    contested_by = fields.Integer(required=True)
    created_by = fields.Integer(dump_only=True)
    body = fields.String(required=True)
    evidence = fields.List(fields.Url())


class PetitionDumpSchema(BaseSchema):
    """ Petition serializer schema """
    petition_id = fields.Integer(attribute="id")
    office = fields.Integer(attribute="office_id")
    contested_by = fields.Integer()
    created_by = fields.Integer()
    created_on = fields.LocalDateTime()
    body = fields.String()
    evidence = fields.List(fields.Url())


class ApplicationLoadSchema(BaseSchema):
    """ Application deserializer schema """
    party = fields.String(required=True)
    office = fields.String(required=True)

    @pre_load(pass_many=True)
    def lower_cased(self, data, many):
        """return the input names as lower case prevents a party or
        office from not been been found because of mismatch in case

        Args:
            data (dict): data list with
            many : instructs marshmallow to expect more than one input field

        Returns:
            dict: input fields in lower case
        """

        data["party"] = data["party"].lower()
        data["office"] = data["office"].lower()
        return data


class ApplicationDumpSchema(BaseSchema):
    """ Application serializer schema """
    party = fields.Integer(attribute="party_id")
    office = fields.Integer(attribute="office_id")
    createdBy = fields.Integer(attribute="applicant_id")
    approved = fields.Boolean()
    requested_on = fields.LocalDateTime()


party_schema = PartySchema()
parties_schema = PartySchema(many=True)
office_schema = OfficeSchema()
offices_schema = OfficeSchema(many=True)
user_schema = UserSchema()
auth_schema = AuthSchema()
candidate_load_schema = CandidateSchemaLoad()
candidate_dump_schema = CandidateSchemaDump()
vote_load_schema = VoteSchemaLoad()
vote_dump_schema = VoteSchemaDump()
results_schema = ResultSchema(many=True)
petition_load_schema = PetitionLoadSchema()
petitions_dump_schema = PetitionDumpSchema()
application_load_schema = ApplicationLoadSchema()
application_dump_schema = ApplicationDumpSchema()

Data schemas Schema options that are universal to all schema classes Schema options # maintains the field ordering on output Party schema mapped onto Party() class attributes return the input names as lower case          Args:             data (dict): data list to get the input field          Returns:             dict: input field party name in lower case Office schema mapped onto Office() class attributes return the input names as lower case          Args:             data (dict): data list with             many : instructs marshmallow to expect more than one input field          Returns:             dict: input fields in lower case User schema mapped on User class attributes User login data schema Candidate schema mapped onto Candidate class attributes Candidate schema dump mapped onto database attributes Vote schema for de-serializing vote data input Vote schema for serializing vote data output Office results schema for serializing office results set Petition deserializer schema Petition serializer schema Application deserializer schema return the input names as lower case prevents a party or         office from not been been found because of mismatch in case          Args:             data (dict): data list with             many : instructs marshmallow to expect more than one input field          Returns:             dict: input fields in lower case Application serializer schema