[Checkins] SVN: grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/ removed user annotations from app.py; interfaces.py became unnecessary

Luciano Ramalho luciano at ramalho.org
Sun Jan 13 08:59:50 EST 2008


Log message for revision 82838:
  removed user annotations from app.py; interfaces.py became unnecessary
  

Changed:
  U   grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/app.py
  U   grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/ftests/test_functional.py
  D   grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/interfaces.py

-=-
Modified: grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/app.py
===================================================================
--- grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/app.py	2008-01-13 13:14:08 UTC (rev 82837)
+++ grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/app.py	2008-01-13 13:59:50 UTC (rev 82838)
@@ -2,23 +2,19 @@
 
 from urllib import urlencode
 
-from zope.interface import Interface, implements, classImplements
-from zope.component import getUtility, provideAdapter
+from zope.interface import Interface
+from zope.component import getUtility
 from zope.app.authentication import PluggableAuthentication
 from zope.app.authentication.principalfolder import PrincipalFolder
 from zope.app.authentication.principalfolder import InternalPrincipal
+from zope.app.authentication.principalfolder import IInternalPrincipal
 from zope.app.authentication.session import SessionCredentialsPlugin
-# XXX: Failed attempt to display the password_encoding field
-# from zope.app.form.browser.source import SourceDropdownWidget
 from zope.app.security.interfaces import IAuthentication
 from zope.app.security.interfaces import IUnauthenticatedPrincipal
 from zope.app.securitypolicy.interfaces import IPrincipalPermissionManager
-from zope.annotation.interfaces import IAttributeAnnotatable
+from zope.schema.interfaces import IField
 from zope.i18n import MessageFactory
 
-
-from interfaces import IUser, UserDataAdapter  
-
 _ = MessageFactory('logindemo')
 
 def setup_pau(pau):
@@ -39,15 +35,12 @@
         
 class LoginDemo(grok.Application, grok.Container):
     """
-    An app that lets you create an account and change your password.
+    An app that lets users create accounts, login, logout and change their
+    passwords.
     """
     # register the authentication utility; see setup_pau for settings
     grok.local_utility(PluggableAuthentication, IAuthentication,
                        setup=setup_pau)
-    # make InternalPrincipal instances annotatable
-    classImplements(InternalPrincipal,IAttributeAnnotatable)
-    # register the adapter for IInternalPrincipal which provides IUser
-    provideAdapter(UserDataAdapter)
            
 class ViewMemberListing(grok.Permission):
     ''' Permission to see the member listing '''
@@ -117,9 +110,7 @@
     """
     User registration form.
     """
-    form_fields = grok.AutoFields(IUser)
-    # XXX: Failed attempt to display the password_encoding field
-    #form_fields[u'password_encoding'].custom_widget = SourceDropdownWidget
+    form_fields = grok.AutoFields(IInternalPrincipal)
     label = u'User registration'
     template = grok.PageTemplateFile('form.pt')
     
@@ -128,24 +119,16 @@
         '''
         Create an InternalPrincipal with the user data.
         
-        This method also sets extra fields using an annotations through
-        the IUser adapter, and grants the ViewMemberListing permission to
-        the principal just created.
+        This method also grants the ViewMemberListing permission to the user.
         '''
         login = data['login']
         pau = getUtility(IAuthentication)
         principals = pau['principals']
         # create an instance of InternalPrincipal
-        principal = InternalPrincipal(login, data['password'], data['name'],
-                                      passwordManagerName='SHA1')
-        # add principal to principal folder; we may assume that the login
-        # name is unique because of validation on the IUser interface
-        # but to be doubly sure, we assert this
+        principal = InternalPrincipal(**data)
+        # XXX: the login name must be unique; need better handling of this
         assert(login not in principals)
         principals[login] = principal
-        # save the e-mail
-        user = IUser(principal)
-        user.email = data['email']
         # grant the user permission to view the member listing
         permission_mngr = IPrincipalPermissionManager(grok.getSite())
         permission_mngr.grantPermissionToPrincipal(
@@ -169,17 +152,23 @@
     grok.require('logindemo.ViewMemberListing')
 
     def fieldNames(self):
-        return (f for f in IUser)
+        # failed attempt to list fields but not methods; this returns empty
+        # return (f for f in IInternalPrincipal if IField.providedBy(f))
+        
+        # another failed attempt to list fields but not methods; this returns
+        # all attributes 
+        # return (f for f in IInternalPrincipal if not callable(f))
+        
+        return ['login', 'title', 'description']
 
     def members(self):
         pau = getUtility(IAuthentication)
         principals = pau['principals']
         roster = []
         for id in sorted(principals.keys()):
-            # adapt the principals to IUser to get all fields
-            user = IUser(principals[id])
+            user = principals[id]
             fields = {}
-            for field in IUser:
+            for field in self.fieldNames():
                 fields[field] = getattr(user, field)
             roster.append(fields)
         return roster

Modified: grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/ftests/test_functional.py
===================================================================
--- grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/ftests/test_functional.py	2008-01-13 13:14:08 UTC (rev 82837)
+++ grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/ftests/test_functional.py	2008-01-13 13:59:50 UTC (rev 82838)
@@ -8,7 +8,7 @@
 import zope.testbrowser.testing
 
 ftesting_zcml = os.path.join(os.path.dirname(logindemo.__file__), 'ftesting.zcml')
-LoginDemoFunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'TestedSampleFunctionalLayer')
+LoginDemoFunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'LoginDemoFunctionalLayer')
 
 def test_suite():
     suite = unittest.TestSuite()

Deleted: grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/interfaces.py
===================================================================
--- grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/interfaces.py	2008-01-13 13:14:08 UTC (rev 82837)
+++ grokapps/LoginDemo/branches/PlainLoginDemo/src/logindemo/interfaces.py	2008-01-13 13:59:50 UTC (rev 82838)
@@ -1,125 +0,0 @@
-import re
-
-from zope.interface import Interface, implements
-from zope import schema
-from zope.component import adapts, getUtility, getUtilitiesFor
-from zope.annotation.interfaces import IAnnotations
-from zope.app.security.interfaces import IAuthentication
-from zope.app.authentication.principalfolder import IInternalPrincipal
-from zope.app.authentication.interfaces import IPasswordManager
-from persistent.dict import PersistentDict
-from zope.i18n import MessageFactory
-
-_ = MessageFactory('logindemo')
-
-USER_DATA_KEY = 'logindemo.iuser.data'
-
-################################################## email validation
-
-class NotAnEmailAddress(schema.ValidationError):
-    __doc__ = _(u"Invalid email address")
-
-check_email = re.compile(r"[a-zA-Z0-9._%-]+@([a-zA-Z0-9-]+\.)*[a-zA-Z]{2,4}").match
-def valid_email(value):
-    if check_email(value):
-        return True
-    raise NotAnEmailAddress(value)
-
-################################################## login name validation
-
-class LoginNameTaken(schema.ValidationError):
-    __doc__ = _(u"Login name already in use. Please choose a different one.")
-
-def unique_login(login):
-    pau = getUtility(IAuthentication)
-    if login in pau['principals']:
-        raise LoginNameTaken
-    return True
-
-################################################## password manager selection
-
-class PasswordManagerChoices(object):
-    implements(schema.interfaces.IIterableSource)
-    
-    def __init__(self):
-        self.choices = [name for name, util in
-                            sorted(getUtilitiesFor(IPasswordManager))]
-        
-    def __iter__(self):
-        return iter(self.choices)
-    
-    def __len__(self):
-        return len(self.choices)
-    
-    def __contains__(self, value):
-        return value in self.choices
-
-################################################## interfaces
-
-class IUser(Interface):
-    """Basic user data."""
-    login = schema.TextLine(title=_(u"Login"),
-                            required=True,
-                            constraint=unique_login)
-    password = schema.Password(title=_(u"Password"),
-                            required=True)
-    # XXX: I have not managed yet to display this in the app.py join form
-    #password_encoding = schema.Choice(title=_(u"Password encoding"),
-    #                        required=True,
-    #                        source=PasswordManagerChoices())
-    name = schema.TextLine(title=_(u"Full name"),
-                            required=False)
-    email = schema.ASCIILine(title=_(u"E-mail"),
-                            required=False,
-                            constraint=valid_email)
-
-################################################## adapters
-
-class UserDataAdapter(object): 
-    """
-    Principal Information Adapter
-    
-    Fields which are common to both IUser and IInternalPrincipal are stored
-    in the context, an InternalPrincipal instance.
-    
-    The IUser.name field is stored in the title attr of the InternalPrincipal.
-    
-    Remaining fields of IUser (such as email) are stored as annotations on the
-    InternalPrincipal instance.
-    """ 
-    implements(IUser)
-    adapts(IInternalPrincipal)
-
-    def __init__(self , context):
-        annotations = IAnnotations(context)
-        self.context = context
-        self.data = annotations.get(USER_DATA_KEY)
-        if self.data is None:
-            self.data = PersistentDict()
-            for field in IUser:
-                if field not in IInternalPrincipal:
-                    self.data[field] = u''
-            annotations[USER_DATA_KEY] = self.data
-        
-    def __getattr__(self, name):
-        if name in IUser:
-            if name == 'name':
-                return self.context.title
-            elif name in IInternalPrincipal:
-                return getattr(self.context, name)
-            return self.data.get(name)
-        else:
-            raise AttributeError, '%s not in IUser'
-        
-    def __setattr__(self, name, value):
-        if name in ['context','data']:
-            super(UserDataAdapter,self).__setattr__(name , value)
-        elif name in IUser:
-            if name in IInternalPrincipal:
-                setattr(self.context, name, value)
-            elif name == 'name':
-                setattr(self.context, 'title', value)
-            else:
-                self.data[name] = value
-        else:
-            raise AttributeError, '%s not in IUser'



More information about the Checkins mailing list