[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