This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (pypi.python.org).
Help us improve Python packaging - Donate today!

Yet another form parser.

Project Description

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
Release History

Release History

This version
History Node

0.6.2

History Node

0.6.1

History Node

0.6.0

History Node

0.5.2

History Node

0.5.1

History Node

0.5.0

History Node

0.4.0

History Node

0.3.8

History Node

0.3.7

History Node

0.3.6

History Node

0.3.5

History Node

0.3.4

History Node

0.3.3

History Node

0.3.2

History Node

0.3.1

History Node

0.2.5

History Node

0.2.4

History Node

0.2.3

History Node

0.2.2

History Node

0.2.1

History Node

0.2.0

Download Files

Download Files

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

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
pilo-0.6.2.tar.gz (22.5 kB) Copy SHA256 Checksum SHA256 Source Dec 1, 2015

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting