Skip to content
This repository has been archived by the owner on Feb 17, 2023. It is now read-only.

Commit

Permalink
100% test coverage; modernize project
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Apr 27, 2017
1 parent b34fb97 commit aa23758
Show file tree
Hide file tree
Showing 22 changed files with 231 additions and 108 deletions.
6 changes: 6 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[run]
source = src

[report]
exclude_lines =
pragma: no cover
24 changes: 14 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
bin/
eggs/
develop-eggs/
parts/
*.pyc
*.so
*.dll
__pycache__
src/*.egg-info

.installed.cfg
*.py[co]
__pycache__/
build/
dist/
*.egg-info/
.tox/
.tox
bin
build
develop-eggs
parts
doc/_build
.coverage
htmlcov
27 changes: 22 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
language: python
sudo: false
python:
- 2.7
install:
- pip install .
- 2.7
- 3.4
- 3.5
- 3.6
- pypy-5.4.1
script:
- python setup.py test -q
- 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
8 changes: 6 additions & 2 deletions CHANGES.txt → CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
CHANGES
=======

3.7.6 (unreleased)
4.0.0 (unreleased)
------------------

- Removed use of 'zope.testing.doctestunit' in favor of stdlib's doctest.

- Removed use of ``zope.app.testing`` in favor of ``zope.app.wsgi``.

- Add support for PyPy, Python 3.4, 3.5 and 3.6.


3.7.5 (2010-01-08)
------------------
Expand Down Expand Up @@ -75,7 +79,7 @@ CHANGES

- Cleanup dependencies after refactorings. Also, don't depend on
zope.app.testing for tests anymore.

- Update package's description to point about refactorings done.

3.6.2 (2009-03-10)
Expand Down
6 changes: 5 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
include *.py
include *.txt
include *.rst
include buildout.cfg
include tox.ini
include .travis.yml
include .coveragerc
recursive-include src *.pt
recursive-include src *.txt
recursive-include src *.rst
recursive-include src *.zcml
File renamed without changes.
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1
58 changes: 37 additions & 21 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,69 @@
# Zope Toolkit policies as described by this documentation.
##############################################################################

version = '3.7.6dev'
version = '4.0.0.dev0'

import os
from setuptools import setup, find_packages

def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()

test_requires = [
'zope.app.wsgi',
'zope.testrunner',
'webtest',
]

setup(name='zope.app.security',
version = version,
version=version,
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='ZMI Views For Zope3 Security Components',
long_description=(
read('README.txt')
read('README.rst')
+ '\n\n' +
'Detailed Documentation\n' +
'======================\n'
+ '\n\n' +
read('src', 'zope', 'app', 'security', 'browser',
'authutilitysearchview.txt')
'authutilitysearchview.rst')
+ '\n\n' +
read('src', 'zope', 'app', 'security', 'browser', 'loginlogout.txt')
read('src', 'zope', 'app', 'security', 'browser', 'loginlogout.rst')
+ '\n\n' +
read('CHANGES.txt')
read('CHANGES.rst')
),
keywords = "zope security authentication principal ftp http",
classifiers = [
keywords="zope security authentication principal ftp http",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
'Framework :: Zope3'],
url='http://pypi.python.org/pypi/zope.app.security',
'Framework :: Zope3'
],
url='http://github.com/zopefoundation/zope.app.security',
license='ZPL 2.1',
packages=find_packages('src'),
package_dir = {'': 'src'},
package_dir={'': 'src'},
namespace_packages=['zope', 'zope.app'],
extras_require=dict(
test=[
'zope.app.testing',
]),
install_requires = [
extras_require={
'test': test_requires,
},
test_requires=test_requires,
install_requires=[
'setuptools',
'zope.app.localpermission',
'zope.app.pagetemplate',
Expand All @@ -73,11 +89,11 @@ def read(*rnames):
'zope.i18nmessageid',
'zope.interface',
'zope.principalregistry',
'zope.publisher >= 3.12',
'zope.publisher >= 4.3.1',
'zope.security',
'zope.securitypolicy',
'zope.login',
],
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
8 changes: 1 addition & 7 deletions src/zope/app/__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
2 changes: 1 addition & 1 deletion src/zope/app/security/_protections.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#
##############################################################################
"""
$Id$
Deprecated and unused.
"""

def protect():
Expand Down
18 changes: 8 additions & 10 deletions src/zope/app/security/browser/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
#
##############################################################################
"""Login and Logout screens
$Id$
"""
from __future__ import absolute_import
import urllib

from zope import component
Expand Down Expand Up @@ -64,10 +63,12 @@ def login(self, nextURL=None):
self.request.principal.id, self.request)
return self.failed()
else:
if nextURL is None:
return self.confirmation()
else:
self.request.response.redirect(nextURL)
return self._confirm(nextURL)

def _confirm(self, nextURL):
if nextURL is None:
return self.confirmation()
self.request.response.redirect(nextURL)


class HTTPBasicAuthenticationLogin(HTTPAuthenticationLogin):
Expand All @@ -87,10 +88,7 @@ def login(self, nextURL=None):
self.request.unauthorized('basic realm="Zope"')
return self.failed()
else:
if nextURL is None:
return self.confirmation()
else:
self.request.response.redirect(nextURL)
return self._confirm(nextURL)


class HTTPAuthenticationLogout(object):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,40 @@ it provides the user with a link to 'Login':
>>> LoginLogout(None, request)()
u'<a href="@@login.html?nextURL=http%3A//127.0.0.1">[Login]</a>'

Attempting to login at this point will fail because nothing has
authorized the principal yet:

>>> from zope.app.security.browser.auth import HTTPAuthenticationLogin
>>> login = HTTPAuthenticationLogin()
>>> login.request = request
>>> login.context = None
>>> login.failed = lambda: 'Login Failed'
>>> login.login()
'Login Failed'

There is a failsafe that will attempt to ask for HTTP Basic authentication:

>>> from zope.app.security.browser.auth import HTTPBasicAuthenticationLogin
>>> basic_login = HTTPBasicAuthenticationLogin()
>>> basic_login.request = request
>>> basic_login.failed = lambda: 'Basic Login Failed'
>>> basic_login.login()
'Basic Login Failed'
>>> request._response.getHeader('WWW-Authenticate', literal=True)
'basic realm="Zope"'
>>> request._response.getStatus()
401

Of course, an unauthorized principal is confirmed to be logged out:

>>> from zope.app.security.browser.auth import HTTPAuthenticationLogout
>>> logout = HTTPAuthenticationLogout(None, request)
>>> logout.logout(nextURL="bye.html")
'bye.html'
>>> logout.confirmation = lambda: 'Good Bye'
>>> logout.logout()
'Good Bye'

Logout, however, behaves differently. Not all authentication protocols (i.e.
credentials extractors/challengers) support 'logout'. Furthermore, we don't
know how an admin may have configured Zope's authentication. Our solution is
Expand All @@ -52,6 +86,27 @@ In this case, the default behavior is to return None for the snippet:
>>> print LoginLogout(None, request)()
None

And at this time, login will correctly direct us to the next URL, or
to the confirmation page:

>>> login = HTTPAuthenticationLogin()
>>> login.request = request
>>> login.context = None
>>> login.login(nextURL='good.html')
>>> login.confirmation = lambda: "You Passed"
>>> login.login()
'You Passed'

Likewise for HTTP Basic authentication:

>>> login = HTTPBasicAuthenticationLogin()
>>> login.request = request
>>> login.context = None
>>> login.confirmation = lambda: "You Passed"
>>> login.login()
'You Passed'


To show a logout prompt, an admin must register a marker adapter that provides
the interface:

Expand All @@ -69,3 +124,10 @@ prompt:

>>> LoginLogout(None, request)()
u'<a href="@@logout.html?nextURL=http%3A//127.0.0.1">[Logout]</a>'

And we can log this principal out, passing a URL to redirect to:

>>> logout = HTTPAuthenticationLogout(None, request)
>>> logout.redirect = lambda: 'You have been redirected.'
>>> logout.logout(nextURL="loggedout.html")
'You have been redirected.'
Loading

0 comments on commit aa23758

Please sign in to comment.