Skip to content

Commit

Permalink
Fix NameError in idpicker.py on Python 3.
Browse files Browse the repository at this point in the history
Fixes #7.

Also a number of small updates:

- Enable test coverage reporting.
- Add support for Python 3.6.
- Modernize tox.ini
- Use pip on Travis and enable Travis caching.
- Run all doctests with consistent flags and checker
- Use renormalizing.IGNORE_EXCEPTION_MODULE_IN_PYTHON2 instead of
  manually normalizing one exception
- Rename .txt to .rst and include them in the published docs. Fix
  headers to be consistent to enable this.
  • Loading branch information
jamadden committed Apr 30, 2017
1 parent a1b42a4 commit 0e8a928
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 142 deletions.
7 changes: 7 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[run]
source = src

[report]
exclude_lines =
pragma: no cover
if __name__ == '__main__':
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ eggs/
develop-eggs/
dist/
parts/
.coverage
htmlcov/
24 changes: 18 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ python:
- 3.3
- 3.4
- 3.5
- pypy
- pypy3
install:
- pip install tox-travis
- 3.6
- pypy-5.4.1
script:
- tox
- coverage run -m zope.testrunner --test-path=src --auto-color --auto-progress

after_success:
- coveralls
notifications:
email: false
email: false

install:
- pip install -U pip setuptools
- pip install -U coveralls coverage
- pip install -U -e ".[test]"


cache: pip

before_cache:
- rm -f $HOME/.cache/pip/log/debug.log
7 changes: 5 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
Changes
=======

2.1.1 (unreleased)
2.2.0 (unreleased)
------------------

- TBD
- Add support for Python 3.6.

- Fix a NameError in the idpicker under Python 3.6.
See `issue 7 <https://github.com/zopefoundation/zope.pluggableauth/issues/7>`_.

2.1.0 (2016-07-04)
------------------
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ include *.txt
include *.py
include buildout.cfg
include tox.ini
include .travis.yml
include .coveragerc

recursive-include src *

Expand Down
5 changes: 3 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
``zope.pluggableauth``
======================
========================
``zope.pluggableauth``
========================

.. image:: https://travis-ci.org/zopefoundation/zope.pluggableauth.png?branch=master
:target: https://travis-ci.org/zopefoundation/zope.pluggableauth
Expand Down
42 changes: 25 additions & 17 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,28 @@ def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()

tests_require = [
'zope.testing',
'zope.testrunner',
]

setup(
name='zope.pluggableauth',
version='2.1.1.dev0',
version='2.2.1.dev0',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='Pluggable Authentication Utility',
long_description= "\n\n".join((
read('README.rst'),
read('src', 'zope', 'pluggableauth', 'README.txt'),
read('CHANGES.rst'),
)),
read('README.rst'),
read('src', 'zope', 'pluggableauth', 'README.rst'),
read('src', 'zope', 'pluggableauth', 'plugins', 'principalfolder.rst'),
read('src', 'zope', 'pluggableauth', 'plugins', 'groupfolder.rst'),
read('CHANGES.rst'),
)),
url='http://pypi.python.org/pypi/zope.pluggableauth',
license='ZPL 2.1',
keywords='zope3 ztk authentication pluggable',
classifiers = [
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
Expand All @@ -54,18 +61,19 @@ def read(*rnames):
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
'Framework :: Zope3'],
'Framework :: Zope3'
],
packages=find_packages('src'),
package_dir = {'': 'src'},
package_dir={'': 'src'},
namespace_packages=['zope'],
extras_require=dict(test=[
'zope.testing',
#'zope.component[test]' # Pulls in ZODB3 right now. :-(
]),
extras_require={
'test': tests_require,
},
install_requires=[
'persistent',
'setuptools',
Expand All @@ -83,9 +91,9 @@ def read(*rnames):
'zope.session',
'zope.site',
'zope.traversing',
],
tests_require=['zope.testing'],
],
tests_require=tests_require,
test_suite='zope.pluggableauth.tests.test_suite',
include_package_data = True,
zip_safe = False,
)
include_package_data=True,
zip_safe=False,
)
8 changes: 1 addition & 7 deletions src/zope/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
# this is a namespace package
try:
import pkg_resources
pkg_resources.declare_namespace(__name__)
except ImportError:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Pluggable-Authentication Utility
================================
==================================
Pluggable-Authentication Utility
==================================

The Pluggable-Authentication Utility (PAU) provides a framework for
authenticating principals and associating information with them. It uses
Expand All @@ -10,7 +11,7 @@ registered as a utility providing the
`zope.authentication.interfaces.IAuthentication` interface.

Authentication
--------------
==============

The primary job of PAU is to authenticate principals. It uses two types of
plug-ins in its work:
Expand Down Expand Up @@ -42,7 +43,7 @@ the principal. Typically, if a subscriber adds data, it should also add
corresponding interface declarations.

Simple Credentials Plugin
~~~~~~~~~~~~~~~~~~~~~~~~~
-------------------------

To illustrate, we'll create a simple credentials plugin:

Expand All @@ -67,7 +68,7 @@ As a plugin, MyCredentialsPlugin needs to be registered as a named utility:
>>> provideUtility(myCredentialsPlugin, name='My Credentials Plugin')

Simple Authenticator Plugin
~~~~~~~~~~~~~~~~~~~~~~~~~~~
---------------------------

Next we'll create a simple authenticator plugin. For our plugin, we'll need
an implementation of IPrincipalInfo:
Expand Down Expand Up @@ -102,7 +103,7 @@ as a named utility:
>>> provideUtility(myAuthenticatorPlugin, name='My Authenticator Plugin')

Configuring a PAU
~~~~~~~~~~~~~~~~~
-----------------

Finally, we'll create the PAU itself:

Expand All @@ -115,7 +116,7 @@ and configure it with the two plugins:
>>> pau.authenticatorPlugins = ('My Authenticator Plugin', )

Using the PAU to Authenticate
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-----------------------------

>>> from zope.pluggableauth.factories import AuthenticatedPrincipalFactory
>>> provideAdapter(AuthenticatedPrincipalFactory)
Expand All @@ -142,7 +143,7 @@ However, if we provide the proper credentials:
we get an authenticated principal.

Multiple Authenticator Plugins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
------------------------------

The PAU works with multiple authenticator plugins. It uses each plugin, in the
order specified in the PAU's authenticatorPlugins attribute, to authenticate
Expand Down Expand Up @@ -193,7 +194,7 @@ The second plugin, however, gets a chance to authenticate if first does not:
Principal('xyz_white')

Multiple Credentials Plugins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
----------------------------

As with with authenticators, we can specify multiple credentials plugins. To
illustrate, we'll create a credentials plugin that extracts credentials from
Expand Down Expand Up @@ -290,7 +291,7 @@ This highlights PAU's ability to use multiple plugins for authentication:
cheers!)

Multiple Authenticator Plugins
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
------------------------------

As with the other operations we've seen, the PAU uses multiple plugins to
find a principal. If the first authenticator plugin can't find the requested
Expand Down Expand Up @@ -371,7 +372,7 @@ we get a different principal for ID 'white':


Issuing a Challenge
-------------------
===================

Part of PAU's IAuthentication contract is to challenge the user for
credentials when its 'unauthorized' method is called. The need for this
Expand Down Expand Up @@ -452,7 +453,7 @@ the advanced plugin is used because it's first:
'advancedlogin.html'

Challenge Protocols
~~~~~~~~~~~~~~~~~~~
-------------------

Sometimes, we want multiple challengers to work together. For example, the
HTTP specification allows multiple challenges to be issued in a response. A
Expand Down Expand Up @@ -510,7 +511,7 @@ first plugin:


Pluggable-Authentication Prefixes
---------------------------------
=================================

Principal ids are required to be unique system wide. Plugins will often provide
options for providing id prefixes, so that different sets of plugins provide
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
=============
Group Folders
=============
===============
Group Folders
===============

Group folders provide support for groups information stored in the ZODB. They
are persistent, and must be contained within the PAUs that use them.
Expand Down Expand Up @@ -187,8 +187,7 @@ Groups cannot contain cycles:
... # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
GroupCycle: (u'auth.group.G2',
[u'auth.group.G2', u'auth.group.G1'])
zope.pluggableauth.plugins.groupfolder.GroupCycle: (u'auth.group.G2', [u'auth.group.G2', u'auth.group.G1'])

Trying to do so does not fire an event.

Expand Down Expand Up @@ -236,7 +235,7 @@ If you don't supply a search key, no results will be returned:
[]

Identifying groups
------------------
==================
The function, `setGroupsForPrincipal`, is a subscriber to
principal-creation events. It adds any group-folder-defined groups to
users in those groups:
Expand Down Expand Up @@ -266,7 +265,7 @@ function also declares the `IGroup` interface on groups:
['IGroupAwarePrincipal']

Special groups
--------------
==============
Two special groups, Authenticated, and Everyone may apply to users
created by the pluggable-authentication utility. There is a
subscriber, specialGroups, that will set these groups on any non-group
Expand Down Expand Up @@ -345,7 +344,7 @@ And they are only added to group aware principals:
[]

Member-aware groups
-------------------
===================
The groupfolder includes a subscriber that gives group principals the
zope.security.interfaces.IGroupAware interface and an implementation thereof.
This allows groups to be able to get and set their members.
Expand Down Expand Up @@ -397,7 +396,7 @@ The two methods work with the value on the IGroupInformation object.
True

Limitation
==========
----------

The current group-folder design has an important limitation!

Expand Down
18 changes: 12 additions & 6 deletions src/zope/pluggableauth/plugins/idpicker.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
##############################################################################
"""Helper base class that picks principal ids
$Id: idpicker.py 117492 2010-10-13 08:17:55Z janwijbrand $
"""
__docformat__ = 'restructuredtext'

Expand All @@ -23,9 +22,16 @@
from zope.exceptions.interfaces import UserError
from zope.i18nmessageid import MessageFactory

try:
text_type = unicode
except NameError: # py3
text_type = str

_ = MessageFactory('zope')

ok = re.compile('[!-~]+$').match


class IdPicker(NameChooser):
"""Helper base class that picks principal ids.
Expand Down Expand Up @@ -53,11 +59,11 @@ class IdPicker(NameChooser):
"""
def chooseName(self, name, object):
i = 0
name = unicode(name)
name = text_type(name)
orig = name
while (not name) or (name in self.context):
i += 1
name = orig+str(i)
name = orig + str(i)

self.checkName(name, object)
return name
Expand All @@ -76,14 +82,14 @@ def checkName(self, name, object):
>>> try:
... IdPicker({}).checkName(u'bob\xfa', None)
... except UserError, e:
... except UserError as e:
... print(e)
... # doctest: +NORMALIZE_WHITESPACE
Ids must contain only printable 7-bit non-space ASCII characters
>>> try:
... IdPicker({}).checkName(u'big bob', None)
... except UserError, e:
... except UserError as e:
... print(e)
... # doctest: +NORMALIZE_WHITESPACE
Ids must contain only printable 7-bit non-space ASCII characters
Expand All @@ -96,7 +102,7 @@ def checkName(self, name, object):
>>> IdPicker({}).checkName(u'x' * 101, None)
Traceback (most recent call last):
...
UserError: Ids can't be more than 100 characters long.
zope.exceptions.interfaces.UserError: Ids can't be more than 100 characters long.
"""
NameChooser.checkName(self, name, object)
Expand Down
Loading

0 comments on commit 0e8a928

Please sign in to comment.