diff --git a/.gitignore b/.gitignore index 89ba6f5..a28036f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build develop-eggs dist lib +local include man parts diff --git a/.travis.yml b/.travis.yml index 55bc622..7c18b48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: python sudo: false python: - 2.7 - - 3.3 - 3.4 - 3.5 + - 3.6 install: - pip install tox-travis script: diff --git a/CHANGES.rst b/CHANGES.rst index 109b071..b54f2a2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,8 @@ Changelog 1.3.1 (unreleased) ------------------ -- Nothing changed yet. +- Turn fucntional tests into better covering unit tests and also add more tests. + This removes test dependencies on unrelated packages. 1.3 (2016-10-22) diff --git a/README.rst b/README.rst index 9762a0f..af6d89f 100644 --- a/README.rst +++ b/README.rst @@ -1 +1,15 @@ -Please refer to src/zope/globalrequest/README.rst. +zope.globalrequest +================== + +Introduction +------------ + +This package provides a global way to retrieve the currently active request object in a zope-based web framework. +To do so you simply need to do the following:: + + from zope.globalrequest import getRequest + request = getRequest() + +This package is mainly intended to be used with the Zope2/Plone stack. +While it also works with the Zope3 framework, +the latter promotes a clean separation of concerns and the pattern of having a globally available request object is discouraged. diff --git a/buildout.cfg b/buildout.cfg index 4c1cc23..2cfebf7 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,13 +1,14 @@ [buildout] develop = . -parts = interpreter test +parts = interpreter test [interpreter] recipe = zc.recipe.egg eggs = zope.globalrequest -interpreter = python +interpreter = zopepy [test] recipe = zc.recipe.testrunner eggs = zope.globalrequest [test] defaults = ['-v'] + diff --git a/setup.py b/setup.py index cb42e4f..02c8b06 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,9 @@ +# -*- coding: utf-8 -*- from setuptools import setup, find_packages -from os.path import join version = '1.3.1.dev0' -readme = open(join('src', 'zope', 'globalrequest', 'README.rst')).read() +readme = open('README.rst').read() changes = open('CHANGES.rst').read() setup( @@ -25,9 +25,9 @@ 'Programming Language :: Python :: 2', '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', ], keywords='zope request global', author='Zope Foundation and Contributors', @@ -47,13 +47,7 @@ 'zope.traversing', ], extras_require=dict( - test=[ - 'zope.browserpage', - 'zope.app.wsgi', - 'zope.configuration', - 'zope.principalregistry', - 'zope.testbrowser>=5.0', - 'zope.testing', + test=[ # keep empty in case someone uses it ], ), ) diff --git a/src/zope/globalrequest/README.rst b/src/zope/globalrequest/README.rst deleted file mode 100644 index ab1b99a..0000000 --- a/src/zope/globalrequest/README.rst +++ /dev/null @@ -1,133 +0,0 @@ -zope.globalrequest -================== - -Introduction ------------- - -This package provides a global way to retrieve the currently active request -object in a zope-based web framework. To do so you simply need to do the -following:: - - from zope.globalrequest import getRequest - request = getRequest() - -This package is mainly intended to be used with the Zope2/Plone stack. While -it also works with the Zope3 framework, the latter promotes a clean separation -of concerns and the pattern of having a globally available request object is -discouraged. - - -Functional Tests ----------------- - -The remainder of this file contains functional tests to demonstrate that the -package works as intended. - -First we need to define a browser view along with an interface for a utility -that will be used by that view: - - >>> from zope.interface import Interface - >>> class IFoo(Interface): - ... """ interface for a foo-ish utility """ - ... def foo(): - ... """ return some foo """ - - >>> from zope.publisher.browser import BrowserPage - >>> from zope.component import queryUtility - >>> class FooView(BrowserPage): - ... """ a browser view """ - ... def __call__(self, *args, **kw): - ... foo = queryUtility(IFoo, default=None) - ... if foo is not None: - ... return foo.foo() - ... else: - ... return 'sif!' - -Unfortunately the view class cannot be directly imported from here, i.e. -relatively, so we have to make it available from somewhere else in order to register it: - - >>> from zope.globalrequest import tests - >>> tests.FooView = FooView - >>> zcml(""" - ... - ... - ... - ... - ... """) - -Next let's make sure our test view actually works: - - >>> from zope.testbrowser.wsgi import Browser - >>> browser = Browser() - >>> browser.open('http://localhost/@@foo') - >>> browser.contents - 'sif!' - -The view tries to query for a utility and use it to "calculate" it's response, -so let's define one: - - >>> from zope.globalrequest import getRequest - >>> class Foo(object): - ... def foo(self): - ... request = getRequest() - ... if request: - ... name = request.get('name', 'n00b') - ... else: - ... name = 'foo' - ... return 'y0 %s!' % name - -Again, the utility class and interface cannot be directly imported from here, -so let's also make them available from somewhere else in order to register -utility: - - >>> tests.Foo = Foo - >>> tests.IFoo = IFoo - >>> zcml(""" - ... - ... - ... - ... - ... """) - -Rendering the view again should now give us the default value provided by the -utility: - - >>> browser.reload() - >>> browser.contents - 'y0 foo!' - -Up to now the request hasn't been stored for us yet, so let's hook up the -necessary event subscribers and try that again: - - >>> zcml(""" - ... - ... - ... - ... - ... """) - -Now we should get the request and therefore the fallback value from the form -lookup: - - >>> browser.reload() - >>> browser.contents - 'y0 n00b!' - -If we now provide a request value we should be greeted properly: - - >>> browser.open('?name=d4wg!') - >>> browser.contents - 'y0 d4wg!!' - -Once the request has been processed, it should not be available anymore: - - >>> print(getRequest()) - None diff --git a/src/zope/globalrequest/__init__.py b/src/zope/globalrequest/__init__.py index 3d72a2c..11b03d8 100644 --- a/src/zope/globalrequest/__init__.py +++ b/src/zope/globalrequest/__init__.py @@ -1,11 +1,11 @@ -from zope.interface.declarations import moduleProvides +# -*- coding: utf-8 -*- from zope.globalrequest.interfaces import IGlobalRequest - -moduleProvides(IGlobalRequest) - - from zope.globalrequest.local import getLocal from zope.globalrequest.local import setLocal +from zope.globalrequest.local import marker +from zope.interface.declarations import moduleProvides + +moduleProvides(IGlobalRequest) def getRequest(): @@ -20,4 +20,4 @@ def setRequest(request): def clearRequest(): """ clear the stored request object """ - setRequest(None) + setRequest(marker) diff --git a/src/zope/globalrequest/ftesting.zcml b/src/zope/globalrequest/ftesting.zcml deleted file mode 100644 index 6166a06..0000000 --- a/src/zope/globalrequest/ftesting.zcml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/zope/globalrequest/tests.py b/src/zope/globalrequest/tests.py index a6465c2..1f42d1e 100644 --- a/src/zope/globalrequest/tests.py +++ b/src/zope/globalrequest/tests.py @@ -1,37 +1,93 @@ -from unittest import TestSuite -from zope.configuration import config -from zope.configuration import xmlconfig -from zope.testing.cleanup import cleanUp -import doctest -import zope.app.wsgi.testlayer -import zope.globalrequest -import zope.testbrowser.wsgi +# -*- coding: utf-8 -*- +import unittest -def zcml(source): - context = config.ConfigurationMachine() - xmlconfig.registerCommonDirectives(context) - xmlconfig.string(source, context) +class TestGlobalrequest(unittest.TestCase): + def tearDown(self): + # reset the threading local context + from threading import local + import zope.globalrequest.local + zope.globalrequest.local.localData = local() -def tearDown(test): - cleanUp() + def test_unset_local(self): + # test with unset values + import zope.globalrequest.local + self.assertIs(zope.globalrequest.local.getLocal('unsetkey'), None) + def test_set_get_local(self): + # test with simple values + import zope.globalrequest.local + zope.globalrequest.local.setLocal('testkey', 'testvalue') + self.assertIs( + zope.globalrequest.local.getLocal('testkey'), + 'testvalue' + ) -class Layer(zope.testbrowser.wsgi.TestBrowserLayer, - zope.app.wsgi.testlayer.BrowserLayer): - """Layer to prepare zope.testbrowser using the WSGI app.""" + def test_unset_local_with_factory(self): + # test with a factory given and marker set/not set + dummy_default = 'dummy_test_default_value' -testLayer = Layer(zope.globalrequest) + def dummy_default_factory(): + return dummy_default + + import zope.globalrequest.local + + self.assertEqual( + zope.globalrequest.local.getLocal( + 'testdefaultkey', + factory=dummy_default_factory + ), + dummy_default + ) + + def test_unset_global_request(self): + # get w/o any value set returns None + import zope.globalrequest + self.assertIs(zope.globalrequest.getRequest(), None) + + def test_set_get_globalrequest(self): + # set a value and get it back + import zope.globalrequest + test_request = dict(value='I am a dummy request') + zope.globalrequest.setRequest(test_request) + self.assertIs(zope.globalrequest.getRequest(), test_request) + + def test_clear_global_request(self): + # set a value and get it back + import zope.globalrequest + test_request = dict(value='I am a dummy request') + zope.globalrequest.setRequest(test_request) + zope.globalrequest.clearRequest() + self.assertIs(zope.globalrequest.getRequest(), None) + + def test_set_subscriber(self): + import zope.globalrequest.subscribers + test_request = dict(value='I am a dummy request') + + class DummyEvent(object): + request = test_request + + dummy_event = DummyEvent() + + # test set + zope.globalrequest.subscribers.set(None, dummy_event) + self.assertIs(zope.globalrequest.getRequest(), test_request) + + def test_clear_subscriber(self): + import zope.globalrequest.subscribers + test_request = dict(value='I am a dummy request') + + class DummyEvent(object): + request = test_request + + dummy_event = DummyEvent() + + # test clear + zope.globalrequest.subscribers.set(None, dummy_event) + zope.globalrequest.subscribers.clearRequest() + self.assertIs(zope.globalrequest.getRequest(), None) def test_suite(): - flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS - readme = doctest.DocFileSuite( - 'README.rst', - package='zope.globalrequest', - globs={'zcml': zcml}, - optionflags=flags, - tearDown=tearDown) - readme.layer = testLayer - return TestSuite((readme,)) + return unittest.defaultTestLoader.loadTestsFromName(__name__) diff --git a/tox.ini b/tox.ini index 05d8d19..26a12aa 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - py27,py33,py34,py35 + py27,py34,py35,py36 [testenv] deps =