[Checkins] SVN: Sandbox/paulwilson/z3c.schema2json/ Initial import of package.
Paul Wilson
paulalexwilson at gmail.com
Sun Jun 28 19:09:57 EDT 2009
Log message for revision 101308:
Initial import of package.
Changed:
A Sandbox/paulwilson/z3c.schema2json/
A Sandbox/paulwilson/z3c.schema2json/CHANGES.txt
A Sandbox/paulwilson/z3c.schema2json/COPYRIGHT.txt
A Sandbox/paulwilson/z3c.schema2json/CREDITS.txt
A Sandbox/paulwilson/z3c.schema2json/LICENSE.txt
A Sandbox/paulwilson/z3c.schema2json/TODO.txt
A Sandbox/paulwilson/z3c.schema2json/bootstrap.py
A Sandbox/paulwilson/z3c.schema2json/buildout.cfg
A Sandbox/paulwilson/z3c.schema2json/setup.py
A Sandbox/paulwilson/z3c.schema2json/src/
A Sandbox/paulwilson/z3c.schema2json/src/z3c/
A Sandbox/paulwilson/z3c.schema2json/src/z3c/__init__.py
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/README.txt
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/__init__.py
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/_schema2json.py
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/configure.zcml
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/ftesting.zcml
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/testing.py
A Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/tests.py
-=-
Added: Sandbox/paulwilson/z3c.schema2json/CHANGES.txt
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/CHANGES.txt (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/CHANGES.txt 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,7 @@
+CHANGES
+*******
+
+0.10 (2009-XXX)
+=================
+
+* First checkin in svn.zope.org.
Property changes on: Sandbox/paulwilson/z3c.schema2json/CHANGES.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/COPYRIGHT.txt
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/COPYRIGHT.txt (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/COPYRIGHT.txt 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,9 @@
+Copyright (c) 2007-2008 Zope Corporation and Contributors
+All Rights Reserved.
+
+This software is subject to the provisions of the Zope Public License,
+Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+FOR A PARTICULAR PURPOSE.
Property changes on: Sandbox/paulwilson/z3c.schema2json/COPYRIGHT.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/CREDITS.txt
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/CREDITS.txt (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/CREDITS.txt 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,17 @@
+=======================
+z3c.schema2json credits
+=======================
+
+Developers
+----------
+
+* Paul A. Wilson
+
+Thank You
+----------
+
+The developers of z3c.schema2json for inspiration:
+
+* Jan-Wijbrand Kolman
+
+* Martijn Faassen
Property changes on: Sandbox/paulwilson/z3c.schema2json/CREDITS.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/LICENSE.txt
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/LICENSE.txt (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/LICENSE.txt 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,54 @@
+Zope Public License (ZPL) Version 2.1
+-------------------------------------
+
+A copyright notice accompanies this license document that
+identifies the copyright holders.
+
+This license has been certified as open source. It has also
+been designated as GPL compatible by the Free Software
+Foundation (FSF).
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions in source code must retain the
+ accompanying copyright notice, this list of conditions,
+ and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the accompanying
+ copyright notice, this list of conditions, and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+3. Names of the copyright holders must not be used to
+ endorse or promote products derived from this software
+ without prior written permission from the copyright
+ holders.
+
+4. The right to distribute this software or to use it for
+ any purpose does not give you the right to use
+ Servicemarks (sm) or Trademarks (tm) of the copyright
+ holders. Use of them is covered by separate agreement
+ with the copyright holders.
+
+5. If any files are modified, you must cause the modified
+ files to carry prominent notices stating that you changed
+ the files and the date of any change.
+
+Disclaimer
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
+ AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
Property changes on: Sandbox/paulwilson/z3c.schema2json/LICENSE.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/TODO.txt
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/TODO.txt (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/TODO.txt 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,4 @@
+Todo
+====
+
+ * Update the changes page to reflect relevent stuff
Property changes on: Sandbox/paulwilson/z3c.schema2json/TODO.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/bootstrap.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/bootstrap.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/bootstrap.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 73916 2007-03-29 15:28:25Z dobe $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+ cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+ os.P_WAIT, sys.executable, sys.executable,
+ '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+ dict(os.environ,
+ PYTHONPATH=
+ ws.find(pkg_resources.Requirement.parse('setuptools')).location
+ ),
+ ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)
Property changes on: Sandbox/paulwilson/z3c.schema2json/bootstrap.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/buildout.cfg
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/buildout.cfg (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/buildout.cfg 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,18 @@
+[buildout]
+develop = .
+parts = test devpython
+extends = http://grok.zope.org/releaseinfo/grok-0.14.cfg
+versions = versions
+
+[versions]
+zope.testing >= 3.6.0
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.schema2json
+
+# installs bin/devpython to do simple interpreter tests
+[devpython]
+recipe = zc.recipe.egg
+interpreter = devpython
+eggs = z3c.schema2json
Property changes on: Sandbox/paulwilson/z3c.schema2json/buildout.cfg
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/setup.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/setup.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/setup.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+import sys, os
+
+def read(*rnames):
+ return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+long_description = (
+ read('src', 'z3c', 'schema2json', 'README.txt')
+ + '\n' +
+ read('CHANGES.txt')
+ + '\n' +
+ 'Download\n'
+ '********\n'
+ )
+
+setup(name='z3c.schema2json',
+ version='1.1dev',
+ description="Convert schema-described Zope 3 objects to JSON and back",
+ long_description=long_description,
+ classifiers=[],
+ keywords="",
+ author="Paul A Wilson",
+ author_email="paulalexwilson at gmail.com",
+ url="",
+ license="ZPL",
+ package_dir={'': 'src'},
+ packages=find_packages('src'),
+ namespace_packages=['z3c'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'setuptools',
+ 'grokcore.component',
+ ],
+ entry_points="""
+ # -*- Entry points: -*-
+ """,
+ )
Property changes on: Sandbox/paulwilson/z3c.schema2json/setup.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/__init__.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/__init__.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/__init__.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,8 @@
+# this is a namespace package
+try:
+ import pkg_resources
+ pkg_resources.declare_namespace(__name__)
+except ImportError:
+ import pkgutil
+ __path__ = pkgutil.extend_path(__path__, __name__)
+
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/__init__.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/README.txt
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/README.txt (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/README.txt 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,556 @@
+.. -*- coding: utf-8 -*-
+Schema To JSON
+**************
+
+Introduction
+============
+
+``z3c.schema2json`` can take objects enriched with schema definitions
+into the popular JSON serialisation format. It is also capable of
+converting this JSON back into objects.
+
+This package requires ``simplejson`` or Python version 2.6 (which has
+simplejson as part of the standard library).
+
+Only object attributes described by zope schema are recognised by
+this package. Any attributes that do no have corresponding schema
+descriptions will be lost in the serialization/deserialization process.
+
+Serialization
+=============
+
+Let's first define a simple Zope 3 schema::
+
+ >>> from zope import interface, schema
+ >>> class IName(interface.Interface):
+ ... first_name = schema.TextLine(title=u'First name')
+ ... last_name = schema.TextLine(title=u'Last name')
+
+Let's now create a class that implements this schema::
+
+ >>> from zope.interface import implements
+ >>> class Name(object):
+ ... implements(IName)
+ ... def __init__(self, first_name, last_name):
+ ... self.first_name = first_name
+ ... self.last_name = last_name
+
+Now we make an instance of the class::
+
+ >>> name = Name('Paul', 'Tom')
+
+Now let's serialize it to JSON::
+
+ >>> from z3c.schema2json import serialize
+ >>> print serialize(IName, name)
+ {
+ "first_name": "Paul",
+ "last_name": "Tom"
+ }
+
+Since the class is part of a doctest, it's module becomes ``__builtin__``.
+
+We can also serialise other fields too::
+
+ >>> from zope import interface, schema
+ >>> class IAddress(interface.Interface):
+ ... street_name = schema.TextLine(title=u'Street name')
+ ... number = schema.Int(title=u'House Number')
+ >>> class Address(object):
+ ... implements(IAddress)
+ ... def __init__(self, street_name, number):
+ ... self.street_name = street_name
+ ... self.number = number
+ >>> address = Address('Pendle Road', 15)
+ >>> print serialize(IAddress, address)
+ {
+ "number": 15,
+ "street_name": "Pendle Road"
+ }
+
+A schema can define an ``Object`` field with its own schema, which the
+serialisation process can handle::
+
+ >>> class IPerson(interface.Interface):
+ ... name = schema.Object(title=u"Name", schema=IName)
+ ... address =schema.Object(title=u"Address", schema=IAddress)
+
+ >>> class Person(object):
+ ... implements(IPerson)
+ ... def __init__(self, name, address):
+ ... self.name = name
+ ... self.address = address
+
+ >>> person = Person(name, address)
+ >>> print serialize(IPerson, person)
+ {
+ "address": {
+ "number": 15,
+ "street_name": "Pendle Road"
+ },
+ "name": {
+ "first_name": "Paul",
+ "last_name": "Tom"
+ }
+ }
+
+The serialisation process also works for the List schema type containing
+elements with their own schema::
+
+ >>> class ICommission(interface.Interface):
+ ... members = schema.List(
+ ... title = u"Commission",
+ ... value_type=schema.Object(__name__='person',
+ ... schema=IPerson))
+
+Note that we have to explicitly specify __name__ for the field that's
+used for value_type here, otherwise we have no name to serialize to
+JSON with::
+
+ >>> class Commission(object):
+ ... implements(ICommission)
+ ... def __init__(self, members):
+ ... self.members = members
+
+ >>> commission = Commission(
+ ... [person, Person(Name('Jim', 'Bo'), Address('Sci Road', 3))])
+ >>> print serialize(ICommission, commission)
+ {
+ "members": [
+ {
+ "address": {
+ "number": 15,
+ "street_name": "Pendle Road"
+ },
+ "name": {
+ "first_name": "Paul",
+ "last_name": "Tom"
+ }
+ },
+ {
+ "address": {
+ "number": 3,
+ "street_name": "Sci Road"
+ },
+ "name": {
+ "first_name": "Jim",
+ "last_name": "Bo"
+ }
+ }
+ ]
+ }
+
+We get an adapter lookup failure whenever we attempt to serialize a field
+type which there's no serializer::
+
+ >>> class IWithNonSerializableField(interface.Interface):
+ ... field = schema.Field(title=u"Commission")
+ >>> class NotSerializable(object):
+ ... implements(IWithNonSerializableField)
+ ... def __init__(self, value):
+ ... self.field = value
+ >>> not_serializable = NotSerializable(None)
+ >>> serialize(IWithNonSerializableField, not_serializable)
+ Traceback (most recent call last):
+ ...
+ TypeError: ('Could not adapt', <zope.schema._bootstrapfields.Field object at ...>, <InterfaceClass z3c.schema2json._schema2json.IJSONGenerator>)
+
+List fields an also contain more primitive values (rather than Objects) such as Ints::
+
+ >>> class ILottery(interface.Interface):
+ ... numbers = schema.List(
+ ... title = u"Lottery Numbers",
+ ... value_type = schema.Int(title=u"A Lottery Number",
+ ... min=0, max=49))
+ >>> class Lottery(object):
+ ... implements(ILottery)
+ ... def __init__(self, numbers):
+ ... self.numbers = numbers
+ ...
+ >>> lotto = Lottery([10, 17, 20, 21, 23, 31, 32])
+ >>> print serialize(ILottery, lotto)
+ {
+ "numbers": [
+ 10,
+ 17,
+ 20,
+ 21,
+ 23,
+ 31,
+ 32
+ ]
+ }
+
+
+Deserialization
+===============
+
+Now we would like to take some objects represented as JSON strings and
+deserialize them::
+
+ >>> from z3c.schema2json import deserialize
+ >>> json = '''
+ ... {
+ ... "first_name": "Guido",
+ ... "last_name": "Van Rossum"
+ ... }
+ ... '''
+ ... name = Name('', '')
+ >>> deserialize(json, IName, name)
+ >>> name.first_name
+ u'Guido'
+ >>> name.last_name
+ u'Van Rossum'
+
+The order of the fields in the JSON string is irrelevant::
+
+ >>> json = '''
+ ... {
+ ... "last_name": "Van Rossum",
+ ... "first_name": "Guido"
+ ... }
+ ... '''
+ ... name = Name('', '')
+ >>> deserialize(json, IName, name)
+ >>> name.first_name
+ u'Guido'
+ >>> name.last_name
+ u'Van Rossum'
+
+After deserialization, the object ``alsoProvides`` the schema interface::
+
+ >>> IName.providedBy(name)
+ True
+
+This also works for other kinds of fields::
+
+ >>> json = '''
+ ... {
+ ... "street_name": "Baker Street",
+ ... "number": 221
+ ... }
+ ... '''
+ >>> address = Address('',0)
+ >>> deserialize(json, IAddress, address)
+ >>> address.street_name
+ u'Baker Street'
+ >>> address.number
+ 221
+
+If a schema defines an Object field with its own schema, the serialization
+can also handle this::
+
+ >>> json = '''
+ ... {
+ ... "name": {
+ ... "first_name": "Sherlock",
+ ... "last_name": "Holmes"
+ ... },
+ ... "address": {
+ ... "street_name": "Baker Street",
+ ... "number": 221
+ ... }
+ ... }
+ ... '''
+ >>> person = Person(Name('', ''), Address('', 0))
+ >>> deserialize(json, IPerson, person)
+ >>> person.name.first_name
+ u'Sherlock'
+ >>> person.name.last_name
+ u'Holmes'
+ >>> person.address.street_name
+ u'Baker Street'
+ >>> person.address.number
+ 221
+ >>> IPerson.providedBy(person)
+ True
+ >>> IName.providedBy(person.name)
+ True
+ >>> IAddress.providedBy(person.address)
+ True
+
+Again the order in which the fields come in JSON shouldn't matter::
+
+ >>> json = '''
+ ... {
+ ... "address": {
+ ... "number": 221,
+ ... "street_name": "Baker Street"
+ ... },
+ ... "name": {
+ ... "last_name": "Holmes",
+ ... "first_name": "Sherlock"
+ ... }
+ ... }
+ ... '''
+ >>> person = Person(Name('', ''), Address('', 0))
+ >>> deserialize(json, IPerson, person)
+ >>> person.name.first_name
+ u'Sherlock'
+ >>> person.name.last_name
+ u'Holmes'
+ >>> person.address.street_name
+ u'Baker Street'
+ >>> person.address.number
+ 221
+ >>> IPerson.providedBy(person)
+ True
+ >>> IName.providedBy(person.name)
+ True
+ >>> IAddress.providedBy(person.address)
+ True
+
+We can deserialise List types also::
+
+ >>> json = '''
+ ... {
+ ... "members": [
+ ... {
+ ... "name": {
+ ... "first_name": "Melanie",
+ ... "last_name": "Parker"
+ ... },
+ ... "address": {
+ ... "street_name": "Chaigley Court",
+ ... "number": 23
+ ... }
+ ... },
+ ... {
+ ... "name": {
+ ... "first_name": "Rob",
+ ... "last_name": "Hall"
+ ... },
+ ... "address": {
+ ... "street_name": "Queenswood Mount",
+ ... "number": 2
+ ... }
+ ... }
+ ... ]
+ ... }
+ ... '''
+
+ >>> commission = Commission([])
+ >>> deserialize(json, ICommission, commission)
+ >>> len(commission.members)
+ 2
+ >>> member = commission.members[0]
+ >>> member.name.first_name
+ u'Melanie'
+ >>> member.address.street_name
+ u'Chaigley Court'
+ >>> member = commission.members[1]
+ >>> member.name.first_name
+ u'Rob'
+ >>> member.address.street_name
+ u'Queenswood Mount'
+
+Whenever an item is null, the resulting value should be None::
+
+ >>> json = '''
+ ... {
+ ... "first_name": "",
+ ... "last_name": null
+ ... }
+ ... '''
+ >>> name = Name('', '')
+ >>> deserialize(json, IName, name)
+ >>> name.first_name == ''
+ True
+ >>> name.last_name is None
+ True
+
+For all kinds of fields, like strings and ints...::
+
+ >>> json = '''
+ ... {
+ ... "street_name": null,
+ ... "number": null
+ ... }
+ ... '''
+ >>> address = Address('', 0)
+ >>> deserialize(json, IAddress, address)
+ >>> address.street_name is None
+ True
+ >>> address.number is None
+ True
+
+...and the fields of subobjects (but not the subobject themselves!)::
+
+ >>> json = '''
+ ... {
+ ... "name": {
+ ... "first_name": null,
+ ... "last_name": null
+ ... },
+ ... "address": {
+ ... "street_name": null,
+ ... "number": null
+ ... }
+ ... }
+ ... '''
+ >>> person = Person(Name('', ''), Address('', 0))
+ >>> deserialize(json, IPerson, person)
+ >>> person.name.first_name is None
+ True
+ >>> person.name.last_name is None
+ True
+ >>> IPerson.providedBy(person)
+ True
+ >>> IName.providedBy(person.name)
+ True
+ >>> person.address is None
+ False
+ >>> person.address.street_name is None
+ True
+ >>> person.address.number is None
+ True
+ >>> IAddress.providedBy(person.address)
+ True
+
+Similarly, empty sequencies result in an empty list::
+
+ >>> json = '''
+ ... {
+ ... "members" : null
+ ... }
+ ... '''
+ >>> commission = Commission([])
+ >>> deserialize(json, ICommission, commission)
+ >>> len(commission.members)
+ 0
+
+Thus concludes the testing for TextLine, Int Object and List. We will now test other supported field types.
+
+Datetime
+========
+
+Datetime objects::
+
+ >>> from datetime import datetime
+ >>> class IWithDatetime(interface.Interface):
+ ... datetime = schema.Datetime(title=u'Date and Time')
+ >>> class WithDatetime(object):
+ ... implements(IWithDatetime)
+ ... def __init__(self, datetime):
+ ... self.datetime = datetime
+ >>> with_datetime = WithDatetime(datetime(2008, 12, 31))
+ >>> json = serialize(IWithDatetime, with_datetime)
+ >>> print json
+ {
+ "datetime": "2008-12-31T00:00:00"
+ }
+ >>> new_datetime = WithDatetime(None)
+ >>> deserialize(json, IWithDatetime, new_datetime)
+ >>> new_datetime.datetime.year
+ 2008
+ >>> new_datetime.datetime.month
+ 12
+ >>> new_datetime.datetime.day
+ 31
+
+Let's try it with the field not filled in::
+
+ >>> with_datetime = WithDatetime(None)
+ >>> json = serialize(IWithDatetime, with_datetime)
+ >>> print json
+ {
+ "datetime": null
+ }
+ >>> new_datetime = WithDatetime(None)
+ >>> deserialize(json, IWithDatetime, new_datetime)
+ >>> new_datetime.datetime is None
+ True
+
+Choice
+======
+
+Choice fields. Currently, only Choice fields with text values are supported::
+
+ >>> from zc.sourcefactory.basic import BasicSourceFactory
+ >>> class ChoiceSource(BasicSourceFactory):
+ ... def getValues(self):
+ ... return [u'alpha', u'beta']
+ >>> class IWithChoice(interface.Interface):
+ ... choice = schema.Choice(title=u'Choice', required=False,
+ ... source=ChoiceSource())
+ >>> class WithChoice(object):
+ ... implements(IWithChoice)
+ ... def __init__(self, choice):
+ ... self.choice = choice
+
+Let's serialize a choice::
+
+ >>> with_choice = WithChoice('alpha')
+ >>> json = serialize(IWithChoice, with_choice)
+ >>> print json
+ {
+ "choice": "alpha"
+ }
+
+And then deserialize it::
+
+ >>> new_choice = WithChoice(None)
+ >>> deserialize(json, IWithChoice, new_choice)
+ >>> new_choice.choice
+ 'alpha'
+
+Serializing empty choices::
+
+ >>> with_choice = WithChoice(None)
+ >>> json = serialize(IWithChoice, with_choice)
+ >>> print json
+ {
+ "choice": null
+ }
+
+And then deserializing them::
+
+ >>> deserialize(json, IWithChoice, new_choice)
+ >>> new_choice.choice is None
+ True
+
+Set
+===
+
+Set fields are very similar to List fields::
+
+ >>> class IWithSet(interface.Interface):
+ ... set = schema.Set(title=u'Set', required=False,
+ ... value_type=schema.Choice(__name__='choice',
+ ... source=ChoiceSource()))
+ >>> class WithSet(object):
+ ... implements(IWithSet)
+ ... def __init__(self, set):
+ ... self.set = set
+ >>> with_set = WithSet(set(['alpha']))
+ >>> json = serialize(IWithSet, with_set)
+ >>> print json
+ {
+ "set": [
+ "alpha"
+ ]
+ }
+ >>> with_set = WithSet(set(['alpha', 'beta']))
+ >>> json = serialize(IWithSet, with_set)
+ >>> print json
+ {
+ "set": [
+ "alpha",
+ "beta"
+ ]
+ }
+ >>> new_set = WithSet(None)
+ >>> deserialize(json, IWithSet, new_set)
+ >>> new_set.set
+ set(['alpha', 'beta'])
+
+Formatting
+==========
+
+The serializer allows both a human readible format and a compact
+JSON representation to be produced. By default, the human readible
+option is selected, but this may be overridden::
+
+ >>> name = Name('Paul', 'Tom')
+ >>> print serialize(IName, name, pretty_print=False)
+ {"first_name": "Paul", "last_name": "Tom"}
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/README.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/__init__.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/__init__.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/__init__.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,2 @@
+from _schema2json import serialize
+from _schema2json import deserialize
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/__init__.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/_schema2json.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/_schema2json.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/_schema2json.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,157 @@
+try:
+ import json # Python v2.6
+except ImportError:
+ import simplejson as json
+
+import grokcore.component as grok
+import zope.datetime
+from persistent import Persistent
+from zope.interface import Interface, alsoProvides
+from zope.location import Location
+from zope.schema import getFieldsInOrder
+from zope.schema.interfaces import IText, IInt, IObject, IList, IChoice, ISet
+from zope.schema.interfaces import IDatetime
+
+def serialize_to_tree(container, schema, instance):
+ for name, field in getFieldsInOrder(schema):
+ value = field.get(instance)
+ container[name] = IJSONGenerator(field).output(value)
+
+def serialize(schema, instance, encoding='UTF-8',
+ pretty_print=True):
+ json_dict = {}
+ serialize_to_tree(json_dict, schema, instance)
+ if pretty_print:
+ indent = 2
+ else:
+ indent = None
+ return json.dumps(json_dict, sort_keys=True, indent=indent)
+
+def deserialize_from_dict(container, schema, instance):
+ for key, value in container.iteritems():
+ field = schema[key]
+ value = IJSONGenerator(field).input(value)
+ field.set(instance, value)
+
+ alsoProvides(instance, schema)
+
+def deserialize(JSON, schema, instance):
+ obj_dict = json.loads(JSON)
+ deserialize_from_dict(obj_dict, schema, instance)
+
+class GeneratedObject(Location, Persistent):
+ def __init__(self):
+ pass
+
+class IJSONGenerator(Interface):
+
+ def output(value):
+ """Output value as JSON item according to field.
+ """
+
+ def input(item):
+ """Input JSON item according to field and return value.
+ """
+
+class Text(grok.Adapter):
+ grok.context(IText)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ return value
+
+ def input(self, item):
+ if item is not None:
+ return unicode(item)
+ return None
+
+class Int(grok.Adapter):
+ grok.context(IInt)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ return value
+
+ def input(self, item):
+ return item
+
+class Object(grok.Adapter):
+ grok.context(IObject)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ cd = {}
+ for name, field in getFieldsInOrder(self.context.schema):
+ cd[name] = IJSONGenerator(field).output(field.get(value))
+ return cd
+
+ def input(self, item):
+ instance = GeneratedObject()
+ deserialize_from_dict(item, self.context.schema, instance)
+ return instance
+
+class List(grok.Adapter):
+ grok.context(IList)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ lst = []
+ field = self.context.value_type
+ for v in value:
+ lst.append(IJSONGenerator(field).output(v))
+ return lst
+
+ def input(self, item):
+ field = self.context.value_type
+ if item is None:
+ return []
+ return [
+ IJSONGenerator(field).input(sub_item)
+ for sub_item in item]
+
+class Datetime(grok.Adapter):
+ grok.context(IDatetime)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ if value is None:
+ return None
+ else:
+ return value.strftime('%Y-%m-%dT%H:%M:%S')
+
+ def input(self, item):
+ if item is not None:
+ return zope.datetime.parseDatetimetz(item)
+ return None
+
+class Choice(grok.Adapter):
+ grok.context(IChoice)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ return value
+
+ def input(self, item):
+ if item is not None:
+ return item
+ return None
+
+# Remember, sets cannot store non-hashables.
+class Set(grok.Adapter):
+ grok.context(ISet)
+ grok.implements(IJSONGenerator)
+
+ def output(self, value):
+ lst = []
+ field = self.context.value_type
+ for v in value:
+ lst.append(IJSONGenerator(field).output(v))
+ return lst
+
+ def input(self, item):
+ field = self.context.value_type
+ if item is None:
+ return set()
+ return set([
+ IJSONGenerator(field).input(sub_item)
+ for sub_item in item])
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/_schema2json.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/configure.zcml
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/configure.zcml (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/configure.zcml 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,8 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok">
+
+ <include package="grokcore.component" file="meta.zcml" />
+
+ <grok:grok package="."/>
+</configure>
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/configure.zcml
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/ftesting.zcml
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/ftesting.zcml (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/ftesting.zcml 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,6 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ >
+ <include package="z3c.schema2json" />
+
+</configure>
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/ftesting.zcml
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/testing.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/testing.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/testing.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,7 @@
+import os
+import z3c.schema2json
+from zope.app.testing.functional import ZCMLLayer
+
+ftesting_zcml = os.path.join(
+ os.path.dirname(z3c.schema2json.__file__), 'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer')
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/testing.py
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/tests.py
===================================================================
--- Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/tests.py (rev 0)
+++ Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/tests.py 2009-06-28 23:09:57 UTC (rev 101308)
@@ -0,0 +1,13 @@
+import unittest
+
+from zope.app.testing.functional import FunctionalDocFileSuite
+from z3c.schema2json.testing import FunctionalLayer
+
+def test_suite():
+
+ readme = FunctionalDocFileSuite(
+ 'README.txt')
+
+ readme.layer = FunctionalLayer
+
+ return unittest.TestSuite([readme])
Property changes on: Sandbox/paulwilson/z3c.schema2json/src/z3c/schema2json/tests.py
___________________________________________________________________
Added: svn:eol-style
+ native
More information about the Checkins
mailing list