Tres Seaver
2011-01-10 03fba87e577d28adff2fa6f22c13330c28335229
Make 'make_api_factory_with_config' tolerate bad confi filename/content.

In such cases, the API factory will have *no* configured plugins or policies:
it will only be useful for retrieving the API from an environment populated by
middleware. Issue warnings for either case.

3 files modified
104 ■■■■ changed files
CHANGES.txt 5 ●●●●● patch | view | raw | blame | history
repoze/who/config.py 37 ●●●● patch | view | raw | blame | history
repoze/who/tests/test_config.py 62 ●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -4,6 +4,11 @@
After 2.0a3 (unreleased)
------------------------
- Make ``make_api_factory_with_config`` tolerant of invalid filenames /
  content for the config file:  in such cases, the API factory will have
  *no* configured plugins or policies:  it will only be useful for retrieving
  the API from an environment populated by middleware.
- Fix bug in ``repoze.who.api`` where the ``remember()`` or ``forget()``
  methods could return a None if the identifier plugin returned a None.
repoze/who/config.py
@@ -1,10 +1,12 @@
""" Configuration parser
"""
from ConfigParser import ConfigParser
from ConfigParser import ParsingError
from StringIO import StringIO
import logging
from pkg_resources import EntryPoint
import sys
import warnings
from repoze.who.api import APIFactory
from repoze.who.interfaces import IAuthenticator
@@ -138,14 +140,35 @@
                                 remote_user_key = 'REMOTE_USER',
                                 logger=None,
                                ):
    identifiers = authenticators = challengers = mdproviders = ()
    request_classifier = None
    challenge_decider = None
    parser = WhoConfig(global_conf['here'])
    parser.parse(open(config_file))
    return APIFactory(parser.identifiers,
                      parser.authenticators,
                      parser.challengers,
                      parser.mdproviders,
                      parser.request_classifier,
                      parser.challenge_decider,
    try:
        opened = open(config_file)
    except IOError:
        warnings.warn('Non-existent who config file: %s' % config_file,
                      stacklevel=2)
    else:
        try:
            parser.parse(opened)
        except ParsingError:
            warnings.warn('Invalid who config file: %s' % config_file,
                          stacklevel=2)
        else:
            identifiers = parser.identifiers
            authenticators = parser.authenticators
            challengers = parser.challengers
            mdproviders = parser.mdproviders
            request_classifier = parser.request_classifier
            challenge_decider = parser.challenge_decider
    return APIFactory(identifiers,
                      authenticators,
                      challengers,
                      mdproviders,
                      request_classifier,
                      challenge_decider,
                      remote_user_key,
                      logger,
                     )
repoze/who/tests/test_config.py
@@ -343,15 +343,15 @@
"""
class TestConfigMiddleware(unittest.TestCase):
    tempdir = None
    _tempdir = None
    def setUp(self):
        pass
    def tearDown(self):
        if self.tempdir is not None:
        if self._tempdir is not None:
            import shutil
            shutil.rmtree(self.tempdir)
            shutil.rmtree(self._tempdir)
    def _getFactory(self):
        from repoze.who.config import make_middleware_with_config
@@ -360,7 +360,7 @@
    def _getTempfile(self, text):
        import os
        import tempfile
        tempdir = self.tempdir = tempfile.mkdtemp()
        tempdir = self._tempdir = tempfile.mkdtemp()
        path = os.path.join(tempdir, 'who.ini')
        config = open(path, 'w')
        config.write(text)
@@ -400,7 +400,7 @@
        app = DummyApp()
        factory = self._getFactory()
        path = self._getTempfile(SAMPLE_CONFIG)
        logfile = os.path.join(self.tempdir, 'who.log')
        logfile = os.path.join(self._tempdir, 'who.log')
        global_conf = {'here': '/'}
        middleware = factory(app, global_conf, config_file=path,
                             log_file=logfile)
@@ -408,15 +408,29 @@
        logging.shutdown()
class Test_make_api_factory_with_config(unittest.TestCase):
    tempdir = None
    _tempdir = None
    _warning_filters = None
    def setUp(self):
        pass
    def tearDown(self):
        if self.tempdir is not None:
        if self._tempdir is not None:
            import shutil
            shutil.rmtree(self.tempdir)
            shutil.rmtree(self._tempdir)
        if self._warning_filters is not None:
            import warnings
            warnings.filters[:] = self._warning_filters
    def _filterWarnings(self):
        global __warningregistry__
        try:
            del __warningregistry__
        except NameError:
            pass
        import warnings
        self._warning_filters = warnings.filters[:]
        warnings.filterwarnings("ignore")
    def _getFactory(self):
        from repoze.who.config import make_api_factory_with_config
@@ -425,7 +439,7 @@
    def _getTempfile(self, text):
        import os
        import tempfile
        tempdir = self.tempdir = tempfile.mkdtemp()
        tempdir = self._tempdir = tempfile.mkdtemp()
        path = os.path.join(tempdir, 'who.ini')
        config = open(path, 'w')
        config.write(text)
@@ -433,6 +447,36 @@
        config.close()
        return path
    def test_bad_config_filename(self):
        global __warningregistry__
        self._filterWarnings()
        factory = self._getFactory()
        path = '/nonesuch/file/should/exist'
        global_conf = {'here': '/'}
        api_factory = factory(global_conf, config_file=path)
        self.assertEqual(len(api_factory.identifiers), 0)
        self.assertEqual(len(api_factory.authenticators), 0)
        self.assertEqual(len(api_factory.challengers), 0)
        self.assertEqual(len(api_factory.mdproviders), 0)
        self.assertEqual(api_factory.remote_user_key, 'REMOTE_USER')
        self.failUnless(api_factory.logger is None)
        self.failUnless(__warningregistry__)
    def test_bad_config_content(self):
        global __warningregistry__
        self._filterWarnings()
        factory = self._getFactory()
        path = self._getTempfile('this is not an INI file')
        global_conf = {'here': '/'}
        api_factory = factory(global_conf, config_file=path)
        self.assertEqual(len(api_factory.identifiers), 0)
        self.assertEqual(len(api_factory.authenticators), 0)
        self.assertEqual(len(api_factory.challengers), 0)
        self.assertEqual(len(api_factory.mdproviders), 0)
        self.assertEqual(api_factory.remote_user_key, 'REMOTE_USER')
        self.failUnless(api_factory.logger is None)
        self.failUnless(__warningregistry__)
    def test_sample_config_no_logger(self):
        factory = self._getFactory()
        path = self._getTempfile(SAMPLE_CONFIG)