mirror of https://github.com/pallets/flask.git
				
				
				
			
		
			
				
	
	
		
			206 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Python
		
	
	
	
# -*- coding: utf-8 -*-
 | 
						|
"""
 | 
						|
    tests.conftest
 | 
						|
    ~~~~~~~~~~~~~~
 | 
						|
 | 
						|
    :copyright: © 2010 by the Pallets team.
 | 
						|
    :license: BSD, see LICENSE for more details.
 | 
						|
"""
 | 
						|
 | 
						|
import gc
 | 
						|
import os
 | 
						|
import pkgutil
 | 
						|
import sys
 | 
						|
import textwrap
 | 
						|
 | 
						|
import pytest
 | 
						|
from _pytest import monkeypatch
 | 
						|
 | 
						|
import flask
 | 
						|
from flask import Flask as _Flask
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(scope='session', autouse=True)
 | 
						|
def _standard_os_environ():
 | 
						|
    """Set up ``os.environ`` at the start of the test session to have
 | 
						|
    standard values. Returns a list of operations that is used by
 | 
						|
    :func:`._reset_os_environ` after each test.
 | 
						|
    """
 | 
						|
    mp = monkeypatch.MonkeyPatch()
 | 
						|
    out = (
 | 
						|
        (os.environ, 'FLASK_APP', monkeypatch.notset),
 | 
						|
        (os.environ, 'FLASK_ENV', monkeypatch.notset),
 | 
						|
        (os.environ, 'FLASK_DEBUG', monkeypatch.notset),
 | 
						|
        (os.environ, 'FLASK_RUN_FROM_CLI', monkeypatch.notset),
 | 
						|
        (os.environ, 'WERKZEUG_RUN_MAIN', monkeypatch.notset),
 | 
						|
    )
 | 
						|
 | 
						|
    for _, key, value in out:
 | 
						|
        if value is monkeypatch.notset:
 | 
						|
            mp.delenv(key, False)
 | 
						|
        else:
 | 
						|
            mp.setenv(key, value)
 | 
						|
 | 
						|
    yield out
 | 
						|
    mp.undo()
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(autouse=True)
 | 
						|
def _reset_os_environ(monkeypatch, _standard_os_environ):
 | 
						|
    """Reset ``os.environ`` to the standard environ after each test,
 | 
						|
    in case a test changed something without cleaning up.
 | 
						|
    """
 | 
						|
    monkeypatch._setitem.extend(_standard_os_environ)
 | 
						|
 | 
						|
 | 
						|
class Flask(_Flask):
 | 
						|
    testing = True
 | 
						|
    secret_key = 'test key'
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def app():
 | 
						|
    app = Flask('flask_test', root_path=os.path.dirname(__file__))
 | 
						|
    return app
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def app_ctx(app):
 | 
						|
    with app.app_context() as ctx:
 | 
						|
        yield ctx
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def req_ctx(app):
 | 
						|
    with app.test_request_context() as ctx:
 | 
						|
        yield ctx
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def client(app):
 | 
						|
    return app.test_client()
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def test_apps(monkeypatch):
 | 
						|
    monkeypatch.syspath_prepend(
 | 
						|
        os.path.abspath(os.path.join(
 | 
						|
            os.path.dirname(__file__), 'test_apps'))
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(autouse=True)
 | 
						|
def leak_detector():
 | 
						|
    yield
 | 
						|
 | 
						|
    # make sure we're not leaking a request context since we are
 | 
						|
    # testing flask internally in debug mode in a few cases
 | 
						|
    leaks = []
 | 
						|
    while flask._request_ctx_stack.top is not None:
 | 
						|
        leaks.append(flask._request_ctx_stack.pop())
 | 
						|
    assert leaks == []
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(params=(True, False))
 | 
						|
def limit_loader(request, monkeypatch):
 | 
						|
    """Patch pkgutil.get_loader to give loader without get_filename or archive.
 | 
						|
 | 
						|
    This provides for tests where a system has custom loaders, e.g. Google App
 | 
						|
    Engine's HardenedModulesHook, which have neither the `get_filename` method
 | 
						|
    nor the `archive` attribute.
 | 
						|
 | 
						|
    This fixture will run the testcase twice, once with and once without the
 | 
						|
    limitation/mock.
 | 
						|
    """
 | 
						|
    if not request.param:
 | 
						|
        return
 | 
						|
 | 
						|
    class LimitedLoader(object):
 | 
						|
        def __init__(self, loader):
 | 
						|
            self.loader = loader
 | 
						|
 | 
						|
        def __getattr__(self, name):
 | 
						|
            if name in ('archive', 'get_filename'):
 | 
						|
                msg = 'Mocking a loader which does not have `%s.`' % name
 | 
						|
                raise AttributeError(msg)
 | 
						|
            return getattr(self.loader, name)
 | 
						|
 | 
						|
    old_get_loader = pkgutil.get_loader
 | 
						|
 | 
						|
    def get_loader(*args, **kwargs):
 | 
						|
        return LimitedLoader(old_get_loader(*args, **kwargs))
 | 
						|
 | 
						|
    monkeypatch.setattr(pkgutil, 'get_loader', get_loader)
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def modules_tmpdir(tmpdir, monkeypatch):
 | 
						|
    """A tmpdir added to sys.path."""
 | 
						|
    rv = tmpdir.mkdir('modules_tmpdir')
 | 
						|
    monkeypatch.syspath_prepend(str(rv))
 | 
						|
    return rv
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def modules_tmpdir_prefix(modules_tmpdir, monkeypatch):
 | 
						|
    monkeypatch.setattr(sys, 'prefix', str(modules_tmpdir))
 | 
						|
    return modules_tmpdir
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def site_packages(modules_tmpdir, monkeypatch):
 | 
						|
    """Create a fake site-packages."""
 | 
						|
    rv = modules_tmpdir \
 | 
						|
        .mkdir('lib') \
 | 
						|
        .mkdir('python{x[0]}.{x[1]}'.format(x=sys.version_info)) \
 | 
						|
        .mkdir('site-packages')
 | 
						|
    monkeypatch.syspath_prepend(str(rv))
 | 
						|
    return rv
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def install_egg(modules_tmpdir, monkeypatch):
 | 
						|
    """Generate egg from package name inside base and put the egg into
 | 
						|
    sys.path."""
 | 
						|
 | 
						|
    def inner(name, base=modules_tmpdir):
 | 
						|
        if not isinstance(name, str):
 | 
						|
            raise ValueError(name)
 | 
						|
        base.join(name).ensure_dir()
 | 
						|
        base.join(name).join('__init__.py').ensure()
 | 
						|
 | 
						|
        egg_setup = base.join('setup.py')
 | 
						|
        egg_setup.write(textwrap.dedent("""
 | 
						|
        from setuptools import setup
 | 
						|
        setup(name='{0}',
 | 
						|
              version='1.0',
 | 
						|
              packages=['site_egg'],
 | 
						|
              zip_safe=True)
 | 
						|
        """.format(name)))
 | 
						|
 | 
						|
        import subprocess
 | 
						|
        subprocess.check_call(
 | 
						|
            [sys.executable, 'setup.py', 'bdist_egg'],
 | 
						|
            cwd=str(modules_tmpdir)
 | 
						|
        )
 | 
						|
        egg_path, = modules_tmpdir.join('dist/').listdir()
 | 
						|
        monkeypatch.syspath_prepend(str(egg_path))
 | 
						|
        return egg_path
 | 
						|
 | 
						|
    return inner
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture
 | 
						|
def purge_module(request):
 | 
						|
    def inner(name):
 | 
						|
        request.addfinalizer(lambda: sys.modules.pop(name, None))
 | 
						|
 | 
						|
    return inner
 | 
						|
 | 
						|
 | 
						|
@pytest.fixture(autouse=True)
 | 
						|
def catch_deprecation_warnings(recwarn):
 | 
						|
    yield
 | 
						|
    gc.collect()
 | 
						|
    assert not recwarn.list, '\n'.join(str(w.message) for w in recwarn.list)
 |