Skip to content

Commit

Permalink
Port to Python 3.3.
Browse files Browse the repository at this point in the history
  • Loading branch information
alga committed Feb 28, 2013
1 parent 358526e commit fa7b632
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 99 deletions.
36 changes: 20 additions & 16 deletions src/z3c/authenticator/README.txt
Expand Up @@ -137,8 +137,8 @@ Such a principal provides the following attributes be default
>>> p.login
u'bob'

>>> p.password
'secret'
>>> p.password.decode('utf-8')
u'secret'

>>> p.title
u'Bob'
Expand Down Expand Up @@ -189,8 +189,8 @@ The returned user is still our previous added IUser
>>> user.login
u'bob'

>>> user.password
'secret'
>>> user.password.decode('utf-8')
u'secret'

>>> user.title
u'Bob'
Expand All @@ -212,9 +212,9 @@ plugin:
>>> import zope.interface
>>> import zope.component

>>> class MyCredentialsPlugin(object):
>>> @zope.interface.implementer(interfaces.ICredentialsPlugin)
... class MyCredentialsPlugin(object):
...
... zope.interface.implements(interfaces.ICredentialsPlugin)
...
... def extractCredentials(self, request):
... return {'login': request.get('login', ''),
Expand Down Expand Up @@ -270,14 +270,14 @@ Authenticate
We can now use the Authenticator to authenticate a sample request:

>>> from zope.publisher.browser import TestRequest
>>> print auth.authenticate(TestRequest())
>>> print(auth.authenticate(TestRequest()))
None

In this case, we cannot authenticate an empty request. In the same way, we
will not be able to authenticate a request with the wrong credentials:

>>> request = TestRequest(form={'login': 'let me in!', 'password': 'secret'})
>>> print auth.authenticate(request)
>>> print(auth.authenticate(request))
None

However, if we provide the proper credentials:
Expand Down Expand Up @@ -407,25 +407,25 @@ First we have to define the interfaces declaring the email attribute:
After the schema, we define a custom principal implementation implementing
this interface:

>>> class MyUser(User):
... zope.interface.implements(IMyUser)
>>> @zope.interface.implementer(IMyUser)
... class MyUser(User):
... def __init__(self, login, password, title, description, email):
... super(MyUser, self).__init__(login, password, title,
... description)
... self.email = email

Now we have to define the AuthenticatedPrincipal for MyUser:

>>> class MyAuthenticatedPrincipal(AuthenticatedPrincipal):
... zope.interface.implements(IMyAuthenticatedPrincipal)
>>> @zope.interface.implementer(IMyAuthenticatedPrincipal)
... class MyAuthenticatedPrincipal(AuthenticatedPrincipal):
... def __init__(self, principal):
... super(MyAuthenticatedPrincipal, self).__init__(principal)
... self.email = principal.email

And we have to define the FoundPrincipal for MyUser:

>>> class MyFoundPrincipal(FoundPrincipal):
... zope.interface.implements(IMyFoundPrincipal)
>>> @zope.interface.implementer(IMyFoundPrincipal)
... class MyFoundPrincipal(FoundPrincipal):
... def __init__(self, principal):
... super(MyFoundPrincipal, self).__init__(principal)
... self.email = principal.email
Expand Down Expand Up @@ -454,8 +454,8 @@ in our principal container. Let's add a principal to this container:
>>> max.__name__ == token
True

>>> max.password
'password'
>>> max.password.decode('utf-8')
u'password'

>>> max.title
u'Max'
Expand Down Expand Up @@ -528,6 +528,10 @@ Edge cases

We can have Users with unicode logins, as we allow this with TextLine in IUser.

>>> try:
... unichr = unichr
... except NameError:
... unichr = chr # PY3
>>> p = User(u'bob'+unichr(233), 'password', 'title')

Adding it should not fail:
Expand Down
57 changes: 28 additions & 29 deletions src/z3c/authenticator/credential.py
Expand Up @@ -20,6 +20,7 @@
import transaction
import persistent

import six
import zope.interface
from zope.publisher.interfaces.http import IHTTPRequest
from zope.session.interfaces import ISession
Expand Down Expand Up @@ -53,25 +54,25 @@ def extractCredentials(self, request):
Now create the plugin and get the credentials.
>>> plugin = HTTPBasicAuthCredentialsPlugin()
>>> plugin.extractCredentials(request)
{'login': u'mgr', 'password': u'mgrpw'}
>>> sorted(plugin.extractCredentials(request).items())
[('login', 'mgr'), ('password', 'mgrpw')]
Make sure we return `None`, if no authentication header has been
specified.
>>> print plugin.extractCredentials(TestRequest())
>>> print(plugin.extractCredentials(TestRequest()))
None
Also, this plugin can *only* handle basic authentication.
>>> request = TestRequest(environ={'HTTP_AUTHORIZATION': 'foo bar'})
>>> print plugin.extractCredentials(TestRequest())
>>> print(plugin.extractCredentials(TestRequest()))
None
This plugin only works with HTTP requests.
>>> from zope.publisher.base import TestRequest
>>> print plugin.extractCredentials(TestRequest('/'))
>>> print(plugin.extractCredentials(TestRequest('/')))
None
"""
Expand All @@ -81,7 +82,9 @@ def extractCredentials(self, request):
if request._auth:
if request._auth.lower().startswith(u'basic '):
credentials = request._auth.split()[-1]
login, password = base64.decodestring(credentials).split(':')
if isinstance(credentials, six.text_type):
credentials = credentials.encode('utf-8')
login, password = base64.decodestring(credentials).split(b':')
return {'login': login.decode('utf-8'),
'password': password.decode('utf-8')}
return None
Expand Down Expand Up @@ -113,7 +116,7 @@ def challenge(self, request):
>>> from zope.publisher.base import TestRequest
>>> request = TestRequest('/')
>>> response = request.response
>>> print plugin.challenge(request)
>>> print(plugin.challenge(request))
False
"""
Expand Down Expand Up @@ -174,9 +177,7 @@ class SessionCredentialsPlugin(persistent.Persistent, contained.Contained):
To illustrate how a session plugin works, we'll first setup some session
machinery:
>>> from zope.app.testing import placelesssetup
>>> from z3c.authenticator.testing import sessionSetUp
>>> placelesssetup.setUp()
>>> sessionSetUp()
This lets us retrieve the same session info from any test request, which
Expand All @@ -193,39 +194,39 @@ class SessionCredentialsPlugin(persistent.Persistent, contained.Contained):
If the given extractCredentials argument doesn't provide IHTTPRequest the
result will always be None:
>>> print plugin.extractCredentials(None)
>>> print(plugin.extractCredentials(None))
None
Our test environment is initially configured without credentials:
>>> from zope.publisher.tests.httprequest import TestRequest
>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()
>>> print plugin.extractCredentials(request)
>>> print(plugin.extractCredentials(request))
None
We must explicitly provide credentials once so the plugin can store
them in a session:
>>> request = TestRequest(login='scott', password='tiger')
>>> plugin.extractCredentials(request)
{'login': 'scott', 'password': 'tiger'}
>>> request = TestRequest(form=dict(login='scott', password='tiger'))
>>> sorted(plugin.extractCredentials(request).items())
[('login', 'scott'), ('password', 'tiger')]
Subsequent requests now have access to the credentials even if they're
not explicitly in the request:
>>> plugin.extractCredentials(TestRequest())
{'login': 'scott', 'password': 'tiger'}
>>> sorted(plugin.extractCredentials(request).items())
[('login', 'scott'), ('password', 'tiger')]
We can always provide new credentials explicitly in the request:
>>> plugin.extractCredentials(TestRequest(
... login='harry', password='hirsch'))
{'login': 'harry', 'password': 'hirsch'}
>>> sorted(plugin.extractCredentials(TestRequest(
... login='harry', password='hirsch')).items())
[('login', 'harry'), ('password', 'hirsch')]
and these will be used on subsequent requests:
>>> plugin.extractCredentials(TestRequest())
{'login': 'harry', 'password': 'hirsch'}
>>> sorted(plugin.extractCredentials(TestRequest()).items())
[('login', 'harry'), ('password', 'hirsch')]
We can also change the fields from which the credentials are extracted:
Expand All @@ -239,8 +240,8 @@ class SessionCredentialsPlugin(persistent.Persistent, contained.Contained):
The plugin now extracts the credentials information from these new fields:
>>> plugin.extractCredentials(request)
{'login': 'luke', 'password': 'the_force'}
>>> sorted(plugin.extractCredentials(request).items())
[('login', 'luke'), ('password', 'the_force')]
We can also set prefixes for the fields from which the credentials are
extracted:
Expand All @@ -259,8 +260,8 @@ class SessionCredentialsPlugin(persistent.Persistent, contained.Contained):
The plugin now extracts the credentials information from these new fields:
>>> plugin.extractCredentials(request)
{'login': 'harry', 'password': 'potter'}
>>> sorted(plugin.extractCredentials(request).items())
[('login', 'harry'), ('password', 'potter')]
Finally, we clear the session credentials using the logout method.
If the given logout argument doesn't provide IHTTPRequest the
Expand All @@ -276,7 +277,7 @@ class SessionCredentialsPlugin(persistent.Persistent, contained.Contained):
After logout we can not logaout again:
>>> print plugin.extractCredentials(TestRequest())
>>> print(plugin.extractCredentials(TestRequest()))
None
"""
Expand Down Expand Up @@ -322,9 +323,7 @@ def challenge(self, request):
To illustrate how a session plugin works, we'll first setup some session
machinery:
>>> from zope.app.testing import placelesssetup
>>> from z3c.authenticator.testing import sessionSetUp
>>> placelesssetup.setUp()
>>> sessionSetUp()
and we'll create a test request:
Expand Down
8 changes: 4 additions & 4 deletions src/z3c/authenticator/group.py
Expand Up @@ -116,17 +116,17 @@ def __setitem__(self, name, group):
Try to add something not providing IGroup
>>> try:
... gc.__setitem__(u'groups.members', object())
... except Exception, e:
... print e
... except Exception as e:
... print(e)
Group does not support IGroup!
Create a group and add them with a wrong prefix:
>>> group = Group(u'users')
>>> try:
... gc.__setitem__(u'123', group)
... except Exception, e:
... print e
... except Exception as e:
... print(e)
'Wrong prefix used in group id!'
Add a login attr since __setitem__ is in need of one
Expand Down
15 changes: 8 additions & 7 deletions src/z3c/authenticator/group.txt
Expand Up @@ -93,9 +93,8 @@ plugin and add them to the authentication utility:
>>> import zope.interface
>>> from z3c.authenticator import interfaces

>>> class MyCredentialsPlugin(object):
...
... zope.interface.implements(interfaces.ICredentialsPlugin)
>>> @zope.interface.implementer(interfaces.ICredentialsPlugin)
... class MyCredentialsPlugin(object):
...
... def extractCredentials(self, request):
... return {'login':request.get('login', ''),
Expand Down Expand Up @@ -443,9 +442,10 @@ because the groups haven't been defined:
Now, if we define the Everybody group:

>>> import zope.authentication.interfaces
>>> class EverybodyGroup(Group):
... zope.interface.implements(
>>> @zope.interface.implementer(
... zope.authentication.interfaces.IEveryoneGroup)
... class EverybodyGroup(Group):
... pass

>>> all = EverybodyGroup('groups.all')
>>> groups['groups.all'] = all
Expand All @@ -460,9 +460,10 @@ Then the group will be added to the principal:

Similarly for the authenticated group:

>>> class AuthenticatedGroup(Group):
... zope.interface.implements(
>>> @zope.interface.implementer(
... zope.authentication.interfaces.IAuthenticatedGroup)
... class AuthenticatedGroup(Group):
... pass

>>> authenticated = AuthenticatedGroup('groups.authenticated')
>>> groups['groups.authenticated'] = authenticated
Expand Down
2 changes: 1 addition & 1 deletion src/z3c/authenticator/principal.py
Expand Up @@ -46,7 +46,7 @@ def allGroups(self):
stack = [iter(self.groups)]
while stack:
try:
group_id = stack[-1].next()
group_id = next(stack[-1])
except StopIteration:
stack.pop()
else:
Expand Down
10 changes: 5 additions & 5 deletions src/z3c/authenticator/testing.py
Expand Up @@ -18,8 +18,8 @@

import zope.component
import zope.interface
import zope.traversing
from zope.publisher.interfaces import IRequest
from zope.app.testing import setup

from zope.session.interfaces import IClientId
from zope.session.interfaces import IClientIdManager
Expand All @@ -43,8 +43,8 @@ def setUpPasswordManager():
IPasswordManager, "Plain Text")


@zope.interface.implementer(IClientId)
class TestClientId(object):
zope.interface.implements(IClientId)
def __new__(cls, request):
return 'dummyclientidfortesting'

Expand All @@ -64,10 +64,10 @@ def sessionSetUp(session_data_container_class=RAMSessionDataContainer):
###############################################################################

def placefulSetUp(test):
site = setup.placefulSetUp(site=True)
site = zope.site.testing.siteSetUp(site=True)
test.globs['rootFolder'] = site
zope.traversing.testing.setUp()
setUpPasswordManager()


def placefulTearDown(test):
setup.placefulTearDown()
zope.site.testing.siteTearDown()

0 comments on commit fa7b632

Please sign in to comment.