[Checkins] SVN: gocept.registration/trunk/ Imported first draft.

Christian Theune ct at gocept.com
Wed Mar 12 17:27:54 EDT 2008


Log message for revision 84626:
  Imported first draft.
  
  This is a generalization of a previous internal implentation.
  
  

Changed:
  A   gocept.registration/trunk/
  A   gocept.registration/trunk/COPYRIGHT.txt
  A   gocept.registration/trunk/LICENSE.txt
  A   gocept.registration/trunk/bootstrap.py
  A   gocept.registration/trunk/buildout.cfg
  A   gocept.registration/trunk/setup.py
  A   gocept.registration/trunk/src/
  A   gocept.registration/trunk/src/gocept/
  A   gocept.registration/trunk/src/gocept/__init__.py
  A   gocept.registration/trunk/src/gocept/registration/
  A   gocept.registration/trunk/src/gocept/registration/README.txt
  A   gocept.registration/trunk/src/gocept/registration/__init__.py
  A   gocept.registration/trunk/src/gocept/registration/email.py
  A   gocept.registration/trunk/src/gocept/registration/interfaces.py
  A   gocept.registration/trunk/src/gocept/registration/registrations.py
  A   gocept.registration/trunk/src/gocept/registration/tests.py

-=-
Added: gocept.registration/trunk/COPYRIGHT.txt
===================================================================
--- gocept.registration/trunk/COPYRIGHT.txt	                        (rev 0)
+++ gocept.registration/trunk/COPYRIGHT.txt	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,9 @@
+Copyright (c) 2008 Zope Foundation 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: gocept.registration/trunk/COPYRIGHT.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/LICENSE.txt
===================================================================
--- gocept.registration/trunk/LICENSE.txt	                        (rev 0)
+++ gocept.registration/trunk/LICENSE.txt	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,44 @@
+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: gocept.registration/trunk/LICENSE.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/bootstrap.py
===================================================================
--- gocept.registration/trunk/bootstrap.py	                        (rev 0)
+++ gocept.registration/trunk/bootstrap.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2007 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 73964 2007-04-01 18:58:20Z srichter $
+"""
+
+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: gocept.registration/trunk/bootstrap.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/buildout.cfg
===================================================================
--- gocept.registration/trunk/buildout.cfg	                        (rev 0)
+++ gocept.registration/trunk/buildout.cfg	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,7 @@
+[buildout]
+parts = test
+develop = .
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = gocept.registration [test]

Added: gocept.registration/trunk/setup.py
===================================================================
--- gocept.registration/trunk/setup.py	                        (rev 0)
+++ gocept.registration/trunk/setup.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,49 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+
+import os.path
+
+from setuptools import setup, find_packages
+
+
+setup(
+    name = 'gocept.registration',
+    version = "0.1",
+    author = "Christian Theune, Stephan Richter and others",
+    author_email = "mail at gocept.com",
+    description = "User self-registration",
+    long_description = file(os.path.join(os.path.dirname(__file__),
+                                         'src', 'gocept', 'registration',
+                                         'README.txt')).read(),
+    license = "ZPL 2.1",
+    url='http://pypi.python.org/pypi/gocept.registration/',
+
+    packages = find_packages('src'),
+    package_dir = {'': 'src'},
+
+    include_package_data = True,
+    zip_safe = False,
+
+    namespace_packages = ['gocept'],
+    install_requires = [
+        'setuptools',
+        'zope.app.container',
+        'zope.component',
+        'zope.interface',
+        'zope.sendmail',
+    ],
+    extras_require = dict(
+        test=['zope.testing',
+             ])
+    )


Property changes on: gocept.registration/trunk/setup.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/__init__.py
===================================================================
--- gocept.registration/trunk/src/gocept/__init__.py	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/__init__.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -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: gocept.registration/trunk/src/gocept/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/registration/README.txt
===================================================================
--- gocept.registration/trunk/src/gocept/registration/README.txt	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/registration/README.txt	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,164 @@
+======================
+User self-registration
+======================
+
+This package provides functionality to implement user self-registration for
+applications.
+
+The general workflow requires that every user provides at least his email
+address but additional data may be provided, too.  After a user registered, an
+email is send out asking him to confirm his identity by clicking a link that
+is embedded in the email.  Once a registration is confirmed, the temporarily
+stored registration data is deleted.
+
+Applications can customize the registration behaviour by subscribing to events
+for registration and confirmation and providing application-specific views and
+adapters for registration and email creation.
+
+Registering a user
+==================
+
+Registrations are managed by the registrations utility:
+
+  >>> from gocept.registration.registrations import Registrations
+  >>> registrations = Registrations()
+
+We can now register a user by passing his email address and some additional
+data:
+
+  >>> peter = registrations.register('peter at example.com', {'name': u'Peter'})
+  >>> peter
+  <gocept.registration.registrations.Registration object at 0x...>
+
+All registrations have a hash that anonymous identifies them, the email and
+the data attached:
+
+  >>> peter.hash
+  '<SHA-HASH>'
+  >>> peter.email
+  'peter at example.com'
+  >>> peter.data
+  {'name': u'Peter'}
+
+Peter's registration is contained in the utility identified by the hash:
+
+  >>> registrations[peter.hash]
+  <gocept.registration.registrations.Registration object at 0x...>
+
+Peter can now confirm his registration using the hash that was given to him:
+
+  >>> registrations.confirm(peter.hash)
+
+Now that he confirmed his registration, it isn't stored in the utility
+anymore:
+
+  >>> registrations[peter.hash]
+  Traceback (most recent call last):
+  KeyError: '<SHA-HASH>'
+
+
+Application hooks
+=================
+
+There are two hooks that applications can tap into for customizing the registration process:
+
+- the ObjectAddedEvent for the registration object, and
+- the RegistrationConfirmedEvent when the user confirms his registration
+
+Let's register a subscriber for both events to demonstrate where each is called:
+
+  >>> def registered(event):
+  ...     print event, event.object
+  >>> import zope.component
+  >>> from zope.app.container.interfaces import IObjectAddedEvent
+  >>> zope.component.provideHandler(registered, (IObjectAddedEvent,))
+
+  >>> chuck = registrations.register('chuck at example.com', {'name': u'LeChuck'})
+  <zope.app.container.contained.ObjectAddedEvent object at 0x...>
+  <gocept.registration.registrations.Registration object at 0x...>
+
+  >>> def confirmed(event):
+  ...     print event, event.registration
+  >>> from gocept.registration.interfaces import IRegistrationConfirmed
+  >>> zope.component.provideHandler(confirmed, (IRegistrationConfirmed,))
+
+  >>> registrations.confirm(chuck.hash)
+  <gocept.registration.interfaces.RegistrationConfirmedEvent object at 0x...>
+  <gocept.registration.registrations.Registration object at 0x...>
+
+Let's clean those registrations up again:
+
+  >>> from zope.app.testing import placelesssetup
+  >>> placelesssetup.tearDown()
+
+
+Confirmation emails
+===================
+
+Sending out registration emails is divided into two parts: creating the email
+itself, and sending it.
+
+Creating confirmation mails
+---------------------------
+
+To provide some central configuration, registrations can be adapted to
+IRegistrationEmailConfiguration:
+
+  >>> from gocept.registration.interfaces import IEmailConfiguration
+  >>> from gocept.registration.interfaces import IRegistration
+  >>> class TestConfig(object):
+  ...     zope.interface.implements(IEmailConfiguration)
+  ...     addr_from = "Ad Ministrator <admin at example.com>"
+  ...     confirmation_url = "http://example.com/confirm?hash=%s"
+  ...     confirmation_template = """From: %(from)s
+  ... To: %(to)s
+  ... Subject: Please confirm your registration
+  ... 
+  ... We received your registration. To activate it, please follow this confirmation
+  ... 
+  ... link:
+  ... 
+  ...  %(link)s"""
+  ...     def __init__(self, registration):
+  ...         pass
+  >>> zope.component.provideAdapter(TestConfig, adapts=(IRegistration,))
+
+The confirmation email is created by adapting the registration object to the
+IRegistrationEmail interface. We provide a simple implementation to start
+from.
+
+  >>> from gocept.registration.email import ConfirmationEmail
+  >>> mail = ConfirmationEmail(chuck)
+  >>> print mail.message
+  From: Ad Ministrator <admin at example.com>
+  To: chuck at example.com
+  Subject: Please confirm your registration
+  <BLANKLINE>
+  We received your registration. To activate it, please follow this confirmation
+  link:
+  <BLANKLINE>
+  http://example.com/confirm?hash=<SHA-HASH>
+
+
+Sending confirmation mails
+--------------------------
+
+We provide a standard event handler that will send out an email for the
+registration:
+
+  >>> from gocept.registration.email import send_registration_mail
+  >>> zope.component.provideAdapter(ConfirmationEmail, (IRegistration,))
+  >>> zope.component.provideHandler(send_registration_mail, (IObjectAddedEvent,))
+  >>> from gocept.registration.tests import DummyMailer
+  >>> zope.component.provideUtility(DummyMailer())
+  >>> janine = registrations.register('janine at example.com')
+  (Ad Ministrator <admin at example.com> -> ['janine at example.com'])
+  From: Ad Ministrator <admin at example.com>
+  To: janine at example.com
+  Subject: Please confirm your registration
+  <BLANKLINE>
+  We received your registration. To activate it, please follow this confirmation
+  <BLANKLINE>
+  link:
+  <BLANKLINE>
+  http://example.com/confirm?hash=<SHA-HASH>


Property changes on: gocept.registration/trunk/src/gocept/registration/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/registration/__init__.py
===================================================================
--- gocept.registration/trunk/src/gocept/registration/__init__.py	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/registration/__init__.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1 @@
+# Make this a Python package


Property changes on: gocept.registration/trunk/src/gocept/registration/__init__.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/registration/email.py
===================================================================
--- gocept.registration/trunk/src/gocept/registration/email.py	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/registration/email.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""Confirmation emails."""
+
+import gocept.registration.interfaces
+import zope.interface
+
+
+class ConfirmationEmail(object):
+    """A basic confirmation email."""
+
+    zope.interface.implements(
+      gocept.registration.interfaces.IConfirmationEmail)
+
+    def __init__(self, registration):
+        config = gocept.registration.interfaces.IEmailConfiguration(
+            registration)
+        self.message = config.confirmation_template % {
+            'to': registration.email,
+            'from': config.addr_from,
+            'link': config.confirmation_url % registration.hash}
+
+
+def send_registration_mail(event):
+    """Listen for a registration and send a mail to the user, asking for
+    confirmation.
+    """
+    registration = event.object
+    email = gocept.registration.interfaces.IConfirmationEmail(registration)
+    config = gocept.registration.interfaces.IEmailConfiguration(registration)
+    mailer = zope.component.getUtility(zope.sendmail.interfaces.IMailer)
+    mailer.send(config.addr_from, [registration.email], email.message)


Property changes on: gocept.registration/trunk/src/gocept/registration/email.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/registration/interfaces.py
===================================================================
--- gocept.registration/trunk/src/gocept/registration/interfaces.py	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/registration/interfaces.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,103 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""User self-registration interfaces. """
+
+import zope.interface
+import zope.schema
+
+
+class IRegistrations(zope.interface.Interface):
+    """Provide self-registration functionality.
+
+    Registrations are done for users giving their email address and
+    possibly more data.
+
+    A registration requires confirmation by the user. For this we
+    send an email containing a confirmation link to his address.
+
+    Upon opening the link a RegistrationConfirmedEvent is sent out
+    and the application can perform whatever is necessary to active
+    the user's account.
+
+    After the successful confirmation the intermediate registration
+    object is deleted.
+
+    """
+
+    def register(email, data=None):
+        """Create a new registration for the given email address and
+        data.
+
+        Sends out an ObjectAddedEvent for the newly created
+        IRegistration object.
+
+        """
+
+    def confirm(hash):
+        """Confirm the registration identified by the hash.
+
+        If successful sends out an IRegistrationConfirmed event.
+
+        """
+
+
+class IEmailConfiguration(zope.interface.Interface):
+    """Defines configuration data for sending registration-related emails."""
+
+    addr_from = zope.schema.TextLine(
+        title=u"The sender's name and email address.")
+
+    confirmation_url = zope.schema.TextLine(
+        title=u"A URL including a single '%s' which can be replaced "
+              u"by the confirmation hash.")
+
+    confirmation_template = zope.interface.Attribute(
+        u"A string with an RFC 822 message. The string is required "
+        u"to include %()s places for the variables `from`, `to`, and "
+        u"`link`.")
+
+
+class IConfirmationEmail(zope.interface.Interface):
+    """An email to confirm a registration."""
+
+    message = zope.interface.Attribute(
+        "A string containing an RFC 2822 message.")
+
+
+class IRegistration(zope.interface.Interface):
+    """A registration."""
+
+    hash = zope.schema.BytesLine(
+        title=u"A hash identifying this registration",)
+
+    email = zope.schema.TextLine(
+        title=u"The email for sending the confirmation mail to.")
+
+    data = zope.interface.Attribute(
+        u"Application-specific registration data.")
+
+
+class IRegistrationConfirmed(zope.interface.Interface):
+
+    registration = zope.schema.Object(
+        title=u"The registration that was confirmed.",
+        schema=IRegistration)
+
+
+class RegistrationConfirmedEvent(object):
+
+    zope.interface.implements(IRegistrationConfirmed)
+
+    def __init__(self, registration):
+        self.registration = registration


Property changes on: gocept.registration/trunk/src/gocept/registration/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/registration/registrations.py
===================================================================
--- gocept.registration/trunk/src/gocept/registration/registrations.py	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/registration/registrations.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,53 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""A utility for managing registrations."""
+
+import datetime
+import gocept.registration.interfaces
+import persistent
+import sha
+import zope.app.container.btree
+import zope.interface
+
+
+class Registrations(zope.app.container.btree.BTreeContainer):
+
+    zope.interface.implements(gocept.registration.interfaces.IRegistrations)
+
+    def register(self, email, data=None):
+        """Create a new registration for the given email address and data."""
+        hash = sha.new(email+datetime.datetime.now().isoformat()).hexdigest()
+        self[hash] = registration = Registration(hash, email, data)
+        return registration
+
+    def confirm(self, hash):
+        """Confirm the registration identified by the hash."""
+        registration = self[hash]
+
+        event = gocept.registration.interfaces.RegistrationConfirmedEvent(
+            registration)
+        zope.event.notify(event)
+
+        del self[hash]
+
+
+class Registration(zope.app.container.contained.Contained,
+                   persistent.Persistent):
+
+    zope.interface.implements(gocept.registration.interfaces.IRegistration)
+
+    def __init__(self, hash, email, data):
+        self.hash = hash
+        self.email = email
+        self.data = data


Property changes on: gocept.registration/trunk/src/gocept/registration/registrations.py
___________________________________________________________________
Name: svn:eol-style
   + native

Added: gocept.registration/trunk/src/gocept/registration/tests.py
===================================================================
--- gocept.registration/trunk/src/gocept/registration/tests.py	                        (rev 0)
+++ gocept.registration/trunk/src/gocept/registration/tests.py	2008-03-12 21:27:54 UTC (rev 84626)
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Foundation 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.
+#
+##############################################################################
+"""Test harness for gocept.registration."""
+
+import re
+import unittest
+import zope.testing.renormalizing
+import zope.sendmail.interfaces
+
+from zope.app.testing import placelesssetup
+from zope.testing import doctest
+
+
+checker = zope.testing.renormalizing.RENormalizing([
+    (re.compile('[a-z0-9]{40}'), '<SHA-HASH>')])
+
+
+class DummyMailer(object):
+    """A dummy mailer."""
+
+    zope.interface.implements(zope.sendmail.interfaces.IMailer)
+
+    def send(self, fromaddr, toaddr, msg):
+        print "(%s -> %s)" % (fromaddr, toaddr)
+        print msg
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocFileSuite(
+        'README.txt',
+        optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE,
+        checker=checker, setUp=placelesssetup.setUp,
+        tearDown=placelesssetup.tearDown))
+    return suite


Property changes on: gocept.registration/trunk/src/gocept/registration/tests.py
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list