Permalink
Browse files

initial import

  • Loading branch information...
0 parents commit ab8e6f7a1ba102556bcde876fd1c54a97bdb2b54 @fafhrd91 committed Nov 7, 2012
Showing with 5,580 additions and 0 deletions.
  1. +7 −0 .gitignore
  2. +10 −0 .travis.yml
  3. +8 −0 CHANGES.txt
  4. +20 −0 README.rst
  5. +111 −0 pform/__init__.py
  6. +205 −0 pform/button.py
  7. +117 −0 pform/directives.py
  8. +117 −0 pform/directives.py.bak
  9. +214 −0 pform/field.py
  10. +503 −0 pform/fields.py
  11. +156 −0 pform/fieldset.py
  12. +309 −0 pform/form.py
  13. +309 −0 pform/interfaces.py
  14. +108 −0 pform/iso8601.py
  15. +19 −0 pform/templates/fields/bool.pt
  16. +8 −0 pform/templates/fields/choice-display.pt
  17. +9 −0 pform/templates/fields/date-display.pt
  18. +9 −0 pform/templates/fields/datetime-display.pt
  19. +14 −0 pform/templates/fields/file.pt
  20. +10 −0 pform/templates/fields/multichoice-display.pt
  21. +34 −0 pform/templates/fields/multichoice.pt
  22. +8 −0 pform/templates/fields/password-display.pt
  23. +13 −0 pform/templates/fields/password.pt
  24. +22 −0 pform/templates/fields/radio.pt
  25. +21 −0 pform/templates/fields/select.pt
  26. +6 −0 pform/templates/fields/text-display.pt
  27. +14 −0 pform/templates/fields/text.pt
  28. +12 −0 pform/templates/fields/textarea.pt
  29. +13 −0 pform/templates/fields/widget-display.jinja2
  30. +17 −0 pform/templates/fields/widget.jinja2
  31. +7 −0 pform/templates/form/actions.jinja2
  32. +12 −0 pform/templates/form/display.jinja2
  33. +16 −0 pform/templates/form/error.jinja2
  34. +1 −0 pform/templates/form/submit.jinja2
  35. +28 −0 pform/templates/form/view.jinja2
  36. +54 −0 pform/tests/base.py
  37. +54 −0 pform/tests/base.py.bak
  38. +3 −0 pform/tests/test-form.pt
  39. +259 −0 pform/tests/test_button.py
  40. +71 −0 pform/tests/test_directives.py
  41. +212 −0 pform/tests/test_field.py
  42. +682 −0 pform/tests/test_fields.py
  43. +252 −0 pform/tests/test_fieldset.py
  44. +253 −0 pform/tests/test_fieldset.py.bak
  45. +329 −0 pform/tests/test_form.py
  46. +127 −0 pform/tests/test_iso8601.py
  47. +37 −0 pform/tests/test_timezone.py
  48. +206 −0 pform/tests/test_validator.py
  49. +120 −0 pform/tests/test_vocabulary.py
  50. +198 −0 pform/validator.py
  51. +102 −0 pform/vocabulary.py
  52. +30 −0 setup.cfg
  53. +69 −0 setup.py
  54. +35 −0 tox.ini
@@ -0,0 +1,7 @@
+*~
+*.egg-info
+*.pyc
+*.pyo
+.DS_Store
+.coverage
+.noseids
@@ -0,0 +1,10 @@
+language: python
+python:
+ - 2.6
+ - 2.7
+ - 3.2
+install:
+ - python setup.py develop
+script: python setup.py test
+notifications:
+ irc: "irc.freenode.org#ptahproject"
@@ -0,0 +1,8 @@
+=======
+CHANGES
+=======
+
+0.1 (Unreleased)
+================
+
+- Initial release
@@ -0,0 +1,20 @@
+pform
+=====
+
+.. image :: https://secure.travis-ci.org/fafhrd91/pform.png
+ :target: https://secure.travis-ci.org/fafhrd91/pform
+
+
+Requirements
+------------
+
+- Python 2.6+ or Python 3.2+
+
+- virtualenv
+
+
+
+License
+-------
+
+pform is offered under the BSD license.
@@ -0,0 +1,111 @@
+# pform public api
+
+__all__ = [
+ 'null','required','Invalid','Field','FieldFactory',
+ 'Fieldset','FieldsetErrors','field','fieldpreview','get_field_factory',
+ 'get_field_preview','SimpleTerm','SimpleVocabulary',
+ 'FORM_INPUT','FORM_DISPLAY','All','Function','Regex','Email','Range',
+ 'Length','OneOf','InputField','TextField','IntegerField','FloatField',
+ 'DecimalField','TextAreaField','FileField','LinesField','PasswordField',
+ 'DateField','DateTimeField','RadioField','BoolField','ChoiceField',
+ 'MultiChoiceField','MultiSelectField','TimezoneField','VocabularyField',
+ 'BaseChoiceField','BaseMultiChoiceField','Form','DisplayForm','FormWidgets',
+ 'button','Button','Buttons','AC_DEFAULT','AC_PRIMARY','AC_DANGER',
+ 'AC_SUCCESS','AC_INFO','AC_WARNING','parse_date','includeme'
+]
+
+from pform.interfaces import null
+from pform.interfaces import required
+from pform.interfaces import Invalid
+
+# field
+from pform.field import Field
+from pform.field import FieldFactory
+
+from pform.fieldset import Fieldset
+from pform.fieldset import FieldsetErrors
+
+# field registration
+from pform.directives import field
+from pform.directives import fieldpreview
+from pform.directives import get_field_factory
+from pform.directives import get_field_preview
+
+# vocabulary
+from pform.vocabulary import SimpleTerm
+from pform.vocabulary import SimpleVocabulary
+
+# widget mode
+from pform.interfaces import FORM_INPUT
+from pform.interfaces import FORM_DISPLAY
+
+# validators
+from pform.validator import All
+from pform.validator import Function
+from pform.validator import Regex
+from pform.validator import Email
+from pform.validator import Range
+from pform.validator import Length
+from pform.validator import OneOf
+
+# helper class
+from pform.fields import InputField
+
+# fields
+from pform.fields import TextField
+from pform.fields import IntegerField
+from pform.fields import FloatField
+from pform.fields import DecimalField
+from pform.fields import TextAreaField
+from pform.fields import FileField
+from pform.fields import LinesField
+from pform.fields import PasswordField
+from pform.fields import DateField
+from pform.fields import DateTimeField
+from pform.fields import RadioField
+from pform.fields import BoolField
+from pform.fields import ChoiceField
+from pform.fields import MultiChoiceField
+from pform.fields import MultiSelectField
+from pform.fields import TimezoneField
+
+# helper field classes
+from pform.fields import VocabularyField
+from pform.fields import BaseChoiceField
+from pform.fields import BaseMultiChoiceField
+
+# forms
+from pform.form import Form
+from pform.form import DisplayForm
+from pform.form import FormWidgets
+
+# button
+from pform.button import button
+from pform.button import Button
+from pform.button import Buttons
+from pform.button import AC_DEFAULT
+from pform.button import AC_PRIMARY
+from pform.button import AC_DANGER
+from pform.button import AC_SUCCESS
+from pform.button import AC_INFO
+from pform.button import AC_WARNING
+
+# iso date
+from pform.iso8601 import parse_date
+
+
+def includeme(cfg):
+ cfg.include('player')
+ cfg.include('pyramid_jinja2')
+
+ # field
+ from pform.directives import add_field
+ cfg.add_directive('add_form_field', add_field)
+
+ # layers
+ cfg.add_layer('form', path='pform:templates/form/')
+ cfg.add_layer('fields', path='pform:templates/fields/')
+ cfg.add_layer('message', path='pform:templates/messages/')
+
+ # scan
+ cfg.scan()
@@ -0,0 +1,205 @@
+""" Form buttons """
+import re
+import sys
+import binascii
+from player import render
+from collections import OrderedDict
+
+AC_DEFAULT = 0
+AC_PRIMARY = 1
+AC_DANGER = 2
+AC_SUCCESS = 3
+AC_INFO = 4
+AC_WARNING = 4
+
+css = {
+ AC_PRIMARY: 'btn-primary',
+ AC_DANGER: 'btn-danger',
+ AC_SUCCESS: 'btn-success',
+ AC_INFO: 'btn-info',
+ AC_WARNING: 'brn-warning'}
+
+
+class Button(object):
+ """A simple button in a form."""
+
+ lang = None
+ readonly = False
+ alt = None
+ accesskey = None
+ disabled = False
+ tabindex = None
+ klass = 'btn'
+ actype = ''
+
+ template = 'form:submit'
+
+ def __init__(self, name='submit', title=None, action=None, actionName=None,
+ actype=AC_DEFAULT, condition=None, **kw):
+ self.__dict__.update(kw)
+
+ if title is None:
+ title = name.capitalize()
+
+ if isinstance(name, bytes):
+ name = name.decode('utf-8')
+ name = re.sub('\s', '_', name)
+
+ self.name = name
+ self.title = title
+ self.action = action
+ self.actionName = actionName
+ self.actype = actype
+ self.condition = condition
+
+ def __repr__(self):
+ return '<{0} "{1}" : "{2}">'.format(
+ self.__class__.__name__, self.name, self.title)
+
+ def __call__(self, context):
+ if self.actionName is not None:
+ return getattr(context, self.actionName)()
+ elif self.action is not None:
+ return self.action(context)
+ else:
+ raise TypeError("Action is not specified")
+
+ def bind(self, prefix, params, context, request):
+ widget = self.__class__.__new__(self.__class__)
+ widget.__dict__.update(self.__dict__)
+
+ widget.id = str(prefix + widget.name).replace('.', '-')
+ widget.name = str(prefix + widget.name)
+ widget.params = params
+ widget.context = context
+ widget.request = request
+ widget.klass = '{0} {1}'.format(widget.klass, css.get(widget.actype,''))
+ return widget
+
+ def activated(self):
+ return self.params.get(self.name, None) is not None
+
+ def render(self):
+ return render(self.request, self.template, self)
+
+
+class Buttons(OrderedDict):
+ """Form buttons manager."""
+
+ def __init__(self, *args):
+ super(Buttons, self).__init__()
+
+ buttons = []
+ for arg in args:
+ if isinstance(arg, Buttons):
+ buttons += arg.values()
+ else:
+ buttons.append(arg)
+
+ self.add(*buttons)
+
+ def add(self, *btns):
+ """Add buttons to this manager."""
+ for btn in btns:
+ if btn.name in self:
+ raise ValueError("Duplicate name", btn.name)
+
+ self[btn.name] = btn
+
+ def add_action(self, title, **kwargs):
+ """Add action to this manager."""
+ # Add the title to button constructor keyword arguments
+ kwargs['title'] = title
+ if 'name' not in kwargs:
+ kwargs['name'] = create_btn_id(title)
+
+ button = Button(**kwargs)
+
+ self.add(button)
+
+ return button
+
+ def __add__(self, other):
+ return self.__class__(self, other)
+
+
+class Actions(OrderedDict):
+ """Form actions manager."""
+
+ prefix = 'buttons.'
+
+ def __init__(self, form, request):
+ self.form = form
+ self.request = request
+
+ super(Actions, self).__init__()
+
+ def update(self):
+ form = self.form
+ params = form.form_params()
+
+ # Create a unique prefix.
+ prefix = '%s%s' % (form.prefix, self.prefix)
+
+ # Walk through each node, making a widget out of it.
+ for field in self.form.buttons.values():
+ if field.condition and not field.condition(form):
+ continue
+
+ self[field.name] = field.bind(prefix, params, form, self.request)
+
+ def execute(self):
+ result = None
+ executed = False
+ for action in self.values():
+ if action.activated():
+ executed = True
+ result = action(self.form)
+
+ if executed:
+ self.clear()
+ self.update()
+
+ return result
+
+
+_identifier = re.compile('[A-Za-z][a-zA-Z0-9_]*$')
+
+
+def create_btn_id(name):
+ if _identifier.match(name):
+ return str(name).lower()
+ return binascii.hexlify(name.encode('utf-8'))
+
+
+def button(title, **kwargs):
+ """ Register new form button.
+
+ :param title: Button title. it is beeing used for html form generations.
+ :param kwargs: Keyword arguments
+
+ .. code-block:: python
+
+ class CustomForm(form.Form):
+
+ field = form.Fieldset()
+
+ @form.button('Cancel')
+ def handle_cancel(self):
+ ...
+ """
+ # install buttons manager
+ f_locals = sys._getframe(1).f_locals
+
+ buttons = f_locals.get('buttons')
+ if buttons is None:
+ buttons = Buttons()
+ f_locals['buttons'] = buttons
+
+ btn = buttons.add_action(title, **kwargs)
+
+ def createHandler(func):
+ btn.actionName = func.__name__
+ return func
+
+ return createHandler
Oops, something went wrong.

0 comments on commit ab8e6f7

Please sign in to comment.