Skip to content

Commit

Permalink
Python 3.4/5/6 and PyPy support.
Browse files Browse the repository at this point in the history
- 100% test coverage
- Drop 2.6 support.
- Enable pip caching and coverage reporting on Travis.
- Rename .txt -> .rst
- Make the configuration file work and test it. Add a zcml extra to include what's
  needed to execute it.
  • Loading branch information
jamadden committed May 9, 2017
1 parent b5abc64 commit 518a81d
Show file tree
Hide file tree
Showing 18 changed files with 198 additions and 92 deletions.
8 changes: 8 additions & 0 deletions .coveragerc
@@ -0,0 +1,8 @@
[run]
source = src

[report]
exclude_lines =
pragma: no cover
raise NotImplementedError
if __name__ == '__main__':
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -9,3 +9,5 @@ bin
develop-eggs
docs
parts
.coverage
htmlcov/
30 changes: 23 additions & 7 deletions .travis.yml
@@ -1,11 +1,27 @@
language: python
sudo: false
python:
- 2.6
- 2.7
- 3.3
install:
- pip install .
- 2.7
- 3.3
- 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
20 changes: 12 additions & 8 deletions CHANGES.txt → CHANGES.rst
@@ -1,15 +1,19 @@
=======
CHANGES
=======
=========
CHANGES
=========

4.0.0a2 (unreleased)
--------------------
4.0.0 (unreleased)
==================

- Nothing changed yet.
- Add support for Python 3.4, 3.5 and 3.6.

- Add support for PyPy.

- Drop support for Python 2.6.


4.0.0a1 (2013-02-24)
--------------------
====================

- Added support for Python 3.3.

Expand All @@ -24,7 +28,7 @@ CHANGES


3.8.0 (2010-06-12)
------------------
==================

- Split out from `zope.app.preference`.

Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
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
File renamed without changes.
2 changes: 2 additions & 0 deletions setup.cfg
@@ -0,0 +1,2 @@
[bdist_wheel]
universal = 1
63 changes: 37 additions & 26 deletions setup.py
Expand Up @@ -17,48 +17,62 @@
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()

setup(name = 'zope.preference',
version='4.0.0a2.dev0',
tests_require = [
'zope.security',
'zope.site',
'zope.testing',
'zope.testrunner',
]

setup(name='zope.preference',
version='4.0.0.dev0',
author='Zope Corporation and Contributors',
author_email='zope-dev@zope.org',
description='User Preferences Framework',
long_description=(
read('README.txt')
read('README.rst')
+ '\n\n' +
'.. contents::\n\n' +
read('src', 'zope', 'preference', 'README.txt')
read('src', 'zope', 'preference', 'README.rst')
+ '\n\n' +
read('CHANGES.txt')
read('CHANGES.rst')
),
keywords = "bluebream zope zope3 user preference",
classifiers = [
keywords="bluebream zope zope3 user preference",
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.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'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',
'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.preference',
'Framework :: Zope3',
],
url='http://github.com/zopefoundation/zope.preference',
license='ZPL 2.1',
packages=find_packages('src'),
package_dir = {'': 'src'},
package_dir={'': 'src'},
namespace_packages=['zope'],
extras_require=dict(test=[
'zope.site',
'zope.testing',
]),
install_requires = [
extras_require={
'test': tests_require,
'zcml': [
'zope.security',
],
},
install_requires=[
'setuptools',
'BTrees',
'zope.annotation',
Expand All @@ -67,12 +81,9 @@ def read(*rnames):
'zope.schema',
'zope.security',
'zope.traversing',
],
tests_require = [
'zope.site',
'zope.testing',
],
test_suite = 'zope.preference.tests.test_suite',
include_package_data = True,
zip_safe = False,
)
],
tests_require=tests_require,
test_suite='zope.preference.tests.test_suite',
include_package_data=True,
zip_safe=False,
)
2 changes: 1 addition & 1 deletion src/zope/__init__.py
@@ -1 +1 @@
__import__('pkg_resources').declare_namespace(__name__)
__import__('pkg_resources').declare_namespace(__name__) # pragma: no cover
69 changes: 55 additions & 14 deletions src/zope/preference/README.txt → src/zope/preference/README.rst
@@ -1,6 +1,6 @@
================
User Preferences
================
==================
User Preferences
==================

Implementing user preferences is usually a painful task, since it requires a
lot of custom coding and constantly changing preferences makes it hard to
Expand All @@ -12,7 +12,7 @@ eases this pain by providing a generic user preferences framework that uses
schemas to categorize and describe the preferences.

Preference Groups
------------------
=================

Preferences are grouped in preference groups and the preferences inside a
group are specified via the preferences group schema:
Expand Down Expand Up @@ -67,7 +67,7 @@ So let's ask the preference group for the `skin` setting:
>>> settings.skin #doctest:+ELLIPSIS
Traceback (most recent call last):
...
NoInteraction
zope.security.interfaces.NoInteraction


So why did the lookup fail? Because we have not specified a principal yet, for
Expand Down Expand Up @@ -132,7 +132,7 @@ assignment:


Preference Group Trees
----------------------
======================

The preferences would not be very powerful, if you could create a full
preferences. So let's create a sub-group for our ZMI user settings, where we
Expand Down Expand Up @@ -166,8 +166,12 @@ item on the parent group ...
Traceback (most recent call last):
...
AttributeError: 'Folder' is not a preference or sub-group.
>>> settings['Folder']
Traceback (most recent call last):
...
KeyError: 'Folder'

... but not before we register the groups as utilities:
but not before we register the groups as utilities:

>>> from zope.preference import interfaces
>>> from zope.component import provideUtility
Expand All @@ -184,6 +188,10 @@ If we now try to lookup the sub-group again, we should be successful:

>>> settings['Folder'] #doctest:+ELLIPSIS
<zope.preference.preference.PreferenceGroup object at ...>
>>> 'Folder' in settings
True
>>> list(settings)
[<zope.preference.preference.PreferenceGroup object at ...>]

While the registry of the preference groups is flat, the careful naming of the
ids allows us to have a tree of preferences. Note that this pattern is very
Expand All @@ -196,14 +204,25 @@ to Python packages. They basically are just a higher level grouping concept
that is used by the UI to better organize the preferences. A preference group
can be converted to a category by simply providing an additional interface:

>>> zope.interface.alsoProvides(settings, interfaces.IPreferenceCategory)
>>> zope.interface.alsoProvides(folderSettings, interfaces.IPreferenceCategory)

>>> interfaces.IPreferenceCategory.providedBy(settings)
>>> interfaces.IPreferenceCategory.providedBy(folderSettings)
True

Preference group objects can also hold arbitrary attributes, but since
they're not persistent this must be used with care:

>>> settings.not_in_schema = 1
>>> settings.not_in_schema
1
>>> del settings.not_in_schema
>>> settings.not_in_schema
Traceback (most recent call last):
...
AttributeError: 'not_in_schema' is not a preference or sub-group.

Default Preferences
-------------------
===================

It sometimes desirable to define default settings on a site-by-site basis,
instead of just using the default value from the schema. The preferences
Expand Down Expand Up @@ -241,6 +260,12 @@ then the default of the setting changes:
>>> settings.Folder.sortedBy
'size'

Because the ``ZMISettings.Folder`` was declared as a preference
category, the default implementation is too:

>>> interfaces.IPreferenceCategory.providedBy(defaultFolder)
True

The default preference providers also implicitly acquire default values from
parent sites. So if we make `folder1` a site and set it as the active site

Expand Down Expand Up @@ -304,9 +329,25 @@ default value:
>>> settings.Folder.sortedBy
'size'

Just as with regular preference groups, the default preference groups
are arranged in a matching hierarchy:

>>> defaultSettings = provider.getDefaultPreferenceGroup('ZMISettings')
>>> defaultSettings.get('Folder')
<zope.preference.default.DefaultPreferenceGroup object at ...>
>>> defaultSettings.Folder
<zope.preference.default.DefaultPreferenceGroup object at ...>

They also report useful AttributeErrors for bad accesses:

>>> defaultSettings.not_in_schema
Traceback (most recent call last):
...
AttributeError: 'not_in_schema' is not a preference or sub-group.


Creating Preference Groups Using ZCML
-------------------------------------
=====================================

If you are using the user preference system in Zope 3, you will not have to
manually setup the preference groups as we did above (of course). We will use
Expand Down Expand Up @@ -393,7 +434,7 @@ And the tree can built again by carefully constructing the id:


Simple Python-Level Access
--------------------------
==========================

If a site is set, getting the user preferences is very simple:

Expand All @@ -415,7 +456,7 @@ so that you can adapt any location to the user preferences:


Traversal
---------
=========

Okay, so all these objects are nice, but they do not make it any easier to
access the preferences in page templates. Thus, a special traversal namespace
Expand All @@ -439,7 +480,7 @@ We can now access the preferences as follows:


Security
--------
========

You might already wonder under which permissions the preferences are
available. They are actually available publicly (`CheckerPublic`), but that
Expand Down
7 changes: 6 additions & 1 deletion src/zope/preference/configure.zcml
Expand Up @@ -5,6 +5,12 @@
i18n_domain="zope"
>

<include package="zope.component" file="meta.zcml" />
<include package="." file="meta.zcml" />
<include package="zope.security" file="meta.zcml" />

<include package="zope.security" />

<view
name="preferences"
for="*"
Expand All @@ -28,7 +34,6 @@

<!-- Root preference group -->
<preferenceGroup
id=""
title="User Preferences"
/>

Expand Down
3 changes: 0 additions & 3 deletions src/zope/preference/default.py
Expand Up @@ -12,8 +12,6 @@
#
##############################################################################
"""Default Preferences Provider
$Id$
"""
from BTrees.OOBTree import OOBTree
from zope.container.contained import Contained
Expand All @@ -23,7 +21,6 @@
from zope.traversing.interfaces import IContainmentRoot
import persistent
import zope.component
import zope.component
import zope.interface


Expand Down

0 comments on commit 518a81d

Please sign in to comment.