{ "info": { "author": "Adrian Cristea", "author_email": "adrian.cristea@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Other Environment", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "*formv* is a configurable Python library that can be used to validate, \r\nconvert & transform HTML forms data.\r\n \r\nTested under Python 2.7 and 3.2.\r\n\r\nIncludes validators for::\r\n\r\n - basic types \r\n boolean, strings, numbers, dates, time, ranges, lists, sets\r\n - chained types \r\n pairs, multiple fields, post-codes, states, currencies, \r\n languages, phone numbers, credit cards\r\n - compound types \r\n any validator, piped validators\r\n - signers & encoders \r\n cost-based PBKDF2 encoding used to sign strings (e.g. cookies), \r\n encode strings (e.g. user, password) and sign serialized objects \r\n (e.g. serialized sessions stored on disk) \r\n - documents (.pdf, .txt, .csv, .doc, etc.)\r\n can be validated (size, mime-type), stored, backed-up, compressed, reused\r\n - images (.jpg, .png, .gif, etc.)\r\n can be validated (size, mime-type), stored, backed-up, resized, watermarked, \r\n imprinted, reused\r\n - geographic data \r\n based on extendable YAML configuration files or user-defined callables: \r\n countries, country-codes, states, various naming styles, currencies, \r\n languages, post-codes, latitude, longitude, geo-distance calculation\r\n - network related \r\n IPv4, IPv6, CIDR, MAC\r\n - web-forms (schema validation)\r\n simple fields, chained fields, key-based dependency\r\n \r\nExample:: \r\n\r\n #------------------------------------------------------------------------\r\n # schema validation including file upload, transformation and recovery \r\n #------------------------------------------------------------------------\r\n \r\n import os, formv\r\n from formv.configuration import build\r\n from formv.validators import *\r\n from formv.exception import Invalid\r\n \r\n from formv.utils import dict_object\r\n from formv.utils.compat import PY2\r\n from formv.utils.fileinfo import BaseFileInfo, ReusedFileInfo \r\n \r\n from tests import multipart\r\n from examples import to_str, setup_mime_types, make_environ as env\r\n \r\n from datetime import datetime\r\n from mimetypes import guess_type\r\n from webob import Request, Response\r\n \r\n app_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\r\n \r\n # ----------------------------------------------------------------\r\n # configuration is required only if you use validators based on \r\n # geographic data: countries, currencies, languages, post-codes, \r\n # latitude, longitude, geo-distance calculation,...\r\n \r\n formv.config = build(config_root=os.path.join(app_root, 'tests'))\r\n\r\n # ----------------------------------------------------------------\r\n\r\n mime_types = setup_mime_types()\r\n \r\n session = dict_object(files=dict_object())\r\n \r\n class WebForm(VSchema): \r\n fields = { \r\n 'first_name': VString(min_len=3, max_len=50), \r\n 'last_name': VString(min_len=3, max_len=50), \r\n 'postcode': VString(), \r\n 'state': VString(),\r\n 'country': VCountry(required=True, mode='by-name'), \r\n 'email': VEmail(required=True), \r\n 'password': VPassword(special_chars=3),\r\n 'file_upload': VPipe(VUploadFile(mime_types=mime_types,\r\n temp_dir='/tmp/formv/test/tmp',), \r\n VWatermarkImage(type='image', \r\n file=os.path.join(app_root, 'tests/watermarks/copyright.jpg'), \r\n opacity=.04, angle=45), \r\n VWatermarkImage(text='formv text watermark', angle=25, \r\n color=(0,0,0,128), opacity=1), \r\n VImprintImage(text='Note the image watermark in the background', \r\n color=(0,128,128,255)), \r\n VImprintImage(text=datetime.strftime(datetime.utcnow(), \r\n 'Uploaded on %Y/%m/%d - %H:%M:%S GMT'), \r\n color=(255,128,128,255), \r\n margin=(25,10)), \r\n ) \r\n } \r\n \r\n chains = { \r\n 'coordinates': VCountryPostcode(country_field='country', # extracts (latitude, longitude) pair\r\n postcode_field='postcode'), \r\n 'password': VEncodedPair(required_field='password', # encodes (password, email) pair\r\n required_label='Password', \r\n available_field='email'),\r\n 'state': VState(country_field='country', # validates state against country\r\n state_field='state', mode='by-name'),\r\n } \r\n \r\n class Application(object):\r\n def __call__(self, environ, start_response):\r\n self.request = Request(make_environ()) \r\n response = self.request.get_response(self.response())\r\n return response(self.request.environ, start_response)\r\n \r\n def response(self):\r\n try:\r\n form = self.validate(self.request.POST) # - form validation\r\n body = to_str(form)\r\n except Invalid as e:\r\n # - recover successfully uploaded files \r\n if isinstance(e.value.get('file_upload'), BaseFileInfo): \r\n session.files['file_upload'] = ReusedFileInfo(e.value['file_upload']) \r\n \r\n body = e.message\r\n body += '
errors'\r\n body += to_str(e.errors)\r\n body += '
values'\r\n body += to_str(e.value)\r\n \r\n response = Response() \r\n response.text = unicode(body) if PY2 else body\r\n return response\r\n \r\n def validate(self, request): \r\n form = WebForm(allow_missing_keys=True, \r\n allow_extra_keys=True, \r\n replace_empty_value=True, \r\n empty_values={ \r\n # inject recovered file back into form if no new file has been uploaded \r\n 'file_upload': session.files.get('file_upload'), \r\n }) \r\n return form.validate(request) \r\n \r\n application = Application() \r\n \r\n def make_environ():\r\n ''' simulates a POST request (multipart/form-data) '''\r\n \r\n app_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\r\n test_files_dir = os.path.join(app_root, 'tests/files') \r\n form = []\r\n \r\n # - plain fields\r\n form.append(multipart.field('first_name', 'John'))\r\n form.append(multipart.field('last_name', 'Smith'))\r\n form.append(multipart.field('email', 'dummy@dummy.com'))\r\n form.append(multipart.field('postcode', '99501'))\r\n form.append(multipart.field('state', 'Alaska'))\r\n form.append(multipart.field('country', 'U.S.A.'))\r\n form.append(multipart.field('password', 'dummy-secret-password-1'))\r\n \r\n # - file upload\r\n f = os.path.join(test_files_dir, 'test.jpg')\r\n form.append(multipart.file('file_upload', filename=f, \r\n content_type=guess_type(f, False)[0])) \r\n return env(*form)\r\n \r\n \r\n if __name__ == '__main__':\r\n from wsgiref.simple_server import make_server \r\n httpd = make_server('127.0.0.1', 9000, application)\r\n sn = httpd.socket.getsockname()\r\n print(\"Serving HTTP on\", sn[0], \"port\", sn[1], \"...\") \r\n httpd.serve_forever()\r\n \r\nOutput::\r\n\r\n +----------------------------------------------------------------------------------------------------------+\r\n | Field Name | Field Value |\r\n +==========================================================================================================+\r\n | coordinates | (61.216799, -149.87828) |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | country | 'USA' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | email | 'dummy@dummy.com' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | file_upload | dir_path = '/tmp/formv/test/public' |\r\n | | file_date = datetime.datetime(2014, 4, 4, 1, 33, 39, 453000) |\r\n | | file_ext ='.jpg' |\r\n | | file_name = '16c2493562644b15b4093a02973097b1.jpg' |\r\n | | file_object = None |\r\n | | file_path = '/tmp/formv/test/public/16c2493562644b15b4093a02973097b1.jpg' |\r\n | | file_size = 5129 |\r\n | | guid_name ='16c2493562644b15b4093a02973097b1' |\r\n | | html_field = 'file_upload' |\r\n | | mime_type = 'image/pjpeg' |\r\n | | orig_name = 'test.jpg' |\r\n | | thumb_name = '16c2493562644b15b4093a02973097b1_th.jpg' |\r\n | | thumb_path = '/tmp/formv/test/public/16c2493562644b15b4093a02973097b1_th.jpg' |\r\n | | zip_name = None |\r\n | | zip_path = None |\r\n | | zip_size = None |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | first_name | 'John' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | last_name | 'Smith' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | password | '$x-pbkdf2$20$1000$rmQEpiAjI7/FaNpFECFb2w==$l5AfchT7rWwPVxofHhhpSZPu4SJPiU4QTtD/cqmE6og=' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | postcode | '99501' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n | state | 'AK' |\r\n +----------------------------------------------------------------------------------------------------------+\r\n\r\nGeographic configuration::\r\n\r\n As of now the configuration available includes only USA. If you have to\r\n validates other countries, you have build similar configuration files and \r\n place them in the corresponding folders.\r\n \r\nPostcodes validation warning:: \r\n\r\n If you plan to do USA postcodes validation based on the included YAML \r\n file, expect a high memory usage as the file contains ~44000 postcodes.\r\n A better alternative would be to dump the file in a database, build \r\n necessary callables to read the data and instruct formv to use these \r\n callables. See formv/configuration.py for an example.\r\n\r\nUSA postcodes data source::\r\n \r\n http://www.boutell.com/zipcodes/\r\n http://www.boutell.com/zipcodes/zipcode.zip\r\n \r\nSource:: \r\n\r\n https://pypi.python.org/pypi/formv\r\n\r\nFor usage and more examples, see examples & tests.", "description_content_type": null, "docs_url": null, "download_url": "https://pypi.python.org/pypi/formv", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": "HTML form data validation conversion transformation schema", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "formv", "package_url": "https://pypi.org/project/formv/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/formv/", "project_urls": { "Download": "https://pypi.python.org/pypi/formv", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/formv/0.0.6/", "requires_dist": null, "requires_python": null, "summary": "HTML forms data validation, conversion & transformation", "version": "0.0.6" }, "last_serial": 1498345, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "378da6cc438bffc616bd2e7f76281d72", "sha256": "00af8b02402805f3d1adf677ce38c300a6cc58d223add9af9b0c8c7133383572" }, "downloads": -1, "filename": "formv-0.0.1.zip", "has_sig": false, "md5_digest": "378da6cc438bffc616bd2e7f76281d72", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2647852, "upload_time": "2013-11-15T00:33:14", "url": "https://files.pythonhosted.org/packages/f1/71/3320134622d0f6758ed18d34cabe1ccb943b45bb0ea5781837e15931cbe9/formv-0.0.1.zip" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "2fb4fc8c19c8ce8b1f7fea3ad9354bb6", "sha256": "09c44ef19bb315ddca66b5798b93eb9803bb80633e81577e0e158e7443b88f3c" }, "downloads": -1, "filename": "formv-0.0.2.zip", "has_sig": false, "md5_digest": "2fb4fc8c19c8ce8b1f7fea3ad9354bb6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2610237, "upload_time": "2014-01-30T01:07:11", "url": "https://files.pythonhosted.org/packages/00/24/7df8d21a2ae8a238be80d66777b6a582a5adaca0257c40fa095032e66373/formv-0.0.2.zip" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "d9e74e3934fabe8c350c55be68cb0852", "sha256": "496f3a8f364f9395a623b68c6cc66fce83dcc1c65ecfa7ad464989fbe63cdd7b" }, "downloads": -1, "filename": "formv-0.0.3.zip", "has_sig": false, "md5_digest": "d9e74e3934fabe8c350c55be68cb0852", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3283402, "upload_time": "2014-04-04T03:04:19", "url": "https://files.pythonhosted.org/packages/e2/a2/4149b468193b909407634feb8c2f68f079ab1f0cea045b453f8f9d634cc5/formv-0.0.3.zip" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "1fd96752a6636daaa96401b18ead62d6", "sha256": "27166f572d412be246d81900f15c41346521900c285d7c4dcb60f2d9578b8de7" }, "downloads": -1, "filename": "formv-0.0.4.tar.gz", "has_sig": false, "md5_digest": "1fd96752a6636daaa96401b18ead62d6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 907204, "upload_time": "2014-06-21T00:56:54", "url": "https://files.pythonhosted.org/packages/03/5c/96d401add2f05d5e13545e194dfa172a632c176ae5e196f4e7f099ce1c65/formv-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "18fe8b32d4356e2b2a28b1b1b01a195e", "sha256": "d1768010721d9b8b9f97fc7edb157d8ab83ac016a885684ab0de0e46c089eda1" }, "downloads": -1, "filename": "formv-0.0.5.tar.gz", "has_sig": false, "md5_digest": "18fe8b32d4356e2b2a28b1b1b01a195e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1660757, "upload_time": "2014-06-21T01:13:03", "url": "https://files.pythonhosted.org/packages/65/e9/301cf2c0fdef4545eedaf96579c219063182354f7c0856b2d7fab901d9a4/formv-0.0.5.tar.gz" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "6aeaa0908c46f02a5c477bcfb2f9313a", "sha256": "b7f7a6ddc9e380b09b9e961a7cdbd859f1ba98518036e63f5c2373cae8490fdf" }, "downloads": -1, "filename": "formv-0.0.6.tar.gz", "has_sig": false, "md5_digest": "6aeaa0908c46f02a5c477bcfb2f9313a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1660886, "upload_time": "2014-08-10T23:41:30", "url": "https://files.pythonhosted.org/packages/4f/40/6eacec9a4828263fbda2121d2b236b7ec71a39e464c52f64c493f6b10deb/formv-0.0.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6aeaa0908c46f02a5c477bcfb2f9313a", "sha256": "b7f7a6ddc9e380b09b9e961a7cdbd859f1ba98518036e63f5c2373cae8490fdf" }, "downloads": -1, "filename": "formv-0.0.6.tar.gz", "has_sig": false, "md5_digest": "6aeaa0908c46f02a5c477bcfb2f9313a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1660886, "upload_time": "2014-08-10T23:41:30", "url": "https://files.pythonhosted.org/packages/4f/40/6eacec9a4828263fbda2121d2b236b7ec71a39e464c52f64c493f6b10deb/formv-0.0.6.tar.gz" } ] }