Skip to main content

Yet another form parser.

Project description

https://travis-ci.org/bninja/pilo.png https://coveralls.io/repos/bninja/pilo/badge.png

Yet another form parser.

dev

$ git clone git@github.com:bninja/pilo.git
$ cd pilo
$ mkvirtualenv pilo
(pilo)$ pip install -e .[tests]
(pilo)$ py.test tests/ --cov=pilo --cov-report term-missing

release

All is well:

(pilo)$ py.test tests/ --cov=pilo --cov-report term-missing

so update __version__ in:

  • pilo/__init__.py

then commit and tag it (travis will publish it to pypi):

$ git commit -am "release v{version}"
$ git tag -a v{version} -m "release v{version}"
$ git push --tags

usage

Validation

Here we validate that a message has acceptable headers and body.

from pilo import Form
from pilo.fields import Dict, String


class Message(Form):
    headers = Dict(String(choices=['to', 'from', 'content-type']), String())
    body = String(max_length=20)


>>> print Message(headers={'to': 'William III'}, body='ha'*10)
{'body': 'hahahahahahahahahaha', 'headers': {'to': 'William III'}}

>>> print Message(headers={'send-to': 'William III'}, body='ha'*10)
Invalid: headers - "send-to" is not one of "to", "from", "content-type"

>>> print Message(headers={'to': 'William III'}, body='ha'*11)
Invalid: body - "hahahahahahahahahahaha" must have length <= 20

Hooks

Override-able mechanism allowing users to inject functions to customize these behaviors:

  • compute

  • resolve

  • parse

  • default

  • munge

  • filter

  • validate

e.g.:

import pilo


class ExtraCurricular(pilo.Form):

   category = pilo.fields.String(
       choices=['athletics', 'academics', 'social', 'service']
   )

   name = pilo.fields.String(max_length=40)

   description = pilo.fields.String(max_length=140)

   role = pilo.fields.String(choices=['member', 'leader'])


class CollegeApplication(pilo.Form):

    high_school_name = pilo.fields.String()

    sat_score = pilo.fields.Integer()

    gpa = pilo.fields.Float()

    extra_curriculars = pilo.fields.List(pilo.fields.SubForm(ExtraCurricular))

    score = pilo.fields.Float(default=pilo.NONE)

    accepted = pilo.fields.Bool(default=False)

    @score.compute
    def score(self):
        leadership_roles = [
            ec for ec in self.extra_curriculars if ec.role == 'leader'
        ]
        relevant_extra_curriculars =[
            ec for ec in self.extra_curriculars
            if ec.category in ['academics', 'service']
        ]
        score = (
            10 * (self.sat_score / 1600.0) +
            10 * (self.gpa / 4.0) +
             5 * len(leadership_roles) +
             5 * len(relevant_extra_curriculars)
        )
        return score

    @accepted.compute
    def accepted(self):
        if self.score > 30:
            return True
        return False

    @high_school_name.munge
    def high_school_name(self, value):
        return value.upper()


application = CollegeApplication(
    high_school_name='Bodega High',
    sat_score=1400,
    gpa=4.0,
    extra_curriculars=[
        dict(category='athletics', role='leader', name='hockey', description=''),
        dict(category='academics', role='member', name='chess club', description=''),
    ]
)


>>> print application.high_school_name
BODEGA HIGH

>>> print application.score
28.75

>>> print application.accepted
False

Form polymorphism and type downcasting

In the following example, a user has an address, but the address schema is polymorphic on the country abbreviation.

import pilo
import uuid


class Address(pilo.Form):

    guid = pilo.fields.UUID(default=uuid.uuid4)
    country = pilo.fields.Type.abstract()


class UnitedKingdomAddress(Address):

    country = pilo.fields.Type.constant('UK')
    name = pilo.fields.String()
    street = pilo.fields.String()
    locality = pilo.fields.String()
    post_town = pilo.fields.String()
    postcode = pilo.fields.String()


class UnitedStatesAddress(Address):

    country = pilo.fields.Type.constant('USA')
    name = pilo.fields.String()
    street = pilo.fields.String()
    unit = pilo.fields.String(default=None)
    city = pilo.fields.String()
    state = pilo.fields.String()
    zip = pilo.fields.String(length=5)


class User(pilo.Form):

     guid = pilo.fields.UUID(default=uuid.uuid4)
     name = pilo.fields.String()
     address = pilo.fields.PolymorphicSubForm(Address.country)


mikey_representation = dict(
    name='Michael Pikey',
    address=dict(
        country='UK',
        name='Mikey Pikey',
        street='351 Meagre Lane',
        locality='Hedge End',
        post_town='Southampton',
        postcode='SO31 4NG',
    )
)


bart_representation = dict(
    name='Bartholomew Simpson',
    address=dict(
        country='USA',
        name='Bite Me',
        street='742 Evergreen Terrace',
        city='Springfield',
        state='???',
        zip='12345',
    )
)


mikey = User(**mikey_representation)


bart = User(**bart_representation)


>>> print dict(mikey)
{
    'address': {
        'country': 'UK',
        'guid': UUID('8c73752c-69a2-4832-99f8-c5354cbeec59'),
        'locality': 'Hedge End',
        'name': 'Mikey Pikey',
        'post_town': 'Southampton',
        'postcode': 'SO31 4NG',
        'street': '351 Meagre Lane'
    },
    'guid': UUID('eee0953c-1b5a-4bd0-893d-f513b1cf24f4'),
    'name': 'Michael Pikey'
}

>>> print dict(bart)
{
    'address': {
        'city': 'Springfield',
        'country': 'USA',
        'guid': UUID('a321bedd-8b94-46b8-830e-ea137b08a608'),
        'name': 'Bite Me',
        'state': '???',
        'street': '742 Evergreen Terrace',
        'unit': None,
        'zip': '12345'
    },
    'guid': UUID('3155a3dd-4b5a-4990-aaea-439359bb36a9'),
    'name': 'Bartholomew Simpson'
}

>>> print mikey.address.postcode
SO31 4NG

>>> print bart.address.zip
12345

>>> print type(mikey.address).__name__
UnitedKingdomAddress

>>> print type(bart.address).__name__
UnitedStatesAddress

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pilo-0.6.2.tar.gz (22.5 kB view details)

Uploaded Source

File details

Details for the file pilo-0.6.2.tar.gz.

File metadata

  • Download URL: pilo-0.6.2.tar.gz
  • Upload date:
  • Size: 22.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for pilo-0.6.2.tar.gz
Algorithm Hash digest
SHA256 845878be066ea675327e569e608d45e06f51025ff2dae39e7642fbeaf53f2c12
MD5 5a5602b1319a9cff0eebbe4b61b63c08
BLAKE2b-256 8896eb3161000cc8d7b35a054291cd4d257f1b5d122316307507a8eb8c091bf3

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page