# -*- coding: utf-8 -*-"""flask.testing~~~~~~~~~~~~~Implements test support helpers. This module is lazily importedand usually not used in production environments.:copyright: © 2010 by the Pallets team.:license: BSD, see LICENSE for more details."""import werkzeugfrom contextlib import contextmanagerfrom click.testing import CliRunnerfrom flask.cli import ScriptInfofrom werkzeug.test import Client, EnvironBuilderfrom flask import _request_ctx_stackfrom flask.json import dumps as json_dumpsfrom werkzeug.urls import url_parsedef make_test_environ_builder(app, path='/', base_url=None, subdomain=None, url_scheme=None,*args, **kwargs):"""Create a :class:`~werkzeug.test.EnvironBuilder`, taking somedefaults from the application.:param app: The Flask application to configure the environment from.:param path: URL path being requested.:param base_url: Base URL where the app is being served, which``path`` is relative to. If not given, built from:data:`PREFERRED_URL_SCHEME`, ``subdomain``,:data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.:param subdomain: Subdomain name to append to :data:`SERVER_NAME`.:param url_scheme: Scheme to use instead of:data:`PREFERRED_URL_SCHEME`.:param json: If given, this is serialized as JSON and passed as``data``. Also defaults ``content_type`` to``application/json``.:param args: other positional arguments passed to:class:`~werkzeug.test.EnvironBuilder`.:param kwargs: other keyword arguments passed to:class:`~werkzeug.test.EnvironBuilder`."""assert (not (base_url or subdomain or url_scheme)or (base_url is not None) != bool(subdomain or url_scheme)), 'Cannot pass "subdomain" or "url_scheme" with "base_url".'if base_url is None:http_host = app.config.get('SERVER_NAME') or 'localhost'app_root = app.config['APPLICATION_ROOT']if subdomain:http_host = '{0}.{1}'.format(subdomain, http_host)if url_scheme is None:url_scheme = app.config['PREFERRED_URL_SCHEME']url = url_parse(path)base_url = '{scheme}://{netloc}/{path}'.format(scheme=url.scheme or url_scheme,netloc=url.netloc or http_host,path=app_root.lstrip('/'))path = url.pathif url.query:sep = b'?' if isinstance(url.query, bytes) else '?'path += sep + url.queryif 'json' in kwargs:assert 'data' not in kwargs, ("Client cannot provide both 'json' and 'data'.")# push a context so flask.json can use app's json attributeswith app.app_context():kwargs['data'] = json_dumps(kwargs.pop('json'))if 'content_type' not in kwargs:kwargs['content_type'] = 'application/json'return EnvironBuilder(path, base_url, *args, **kwargs)class FlaskClient(Client):"""Works like a regular Werkzeug test client but has some knowledge abouthow Flask works to defer the cleanup of the request context stack to theend of a ``with`` body when used in a ``with`` statement. For generalinformation about how to use this class refer to:class:`werkzeug.test.Client`... versionchanged:: 0.12`app.test_client()` includes preset default environment, which can beset after instantiation of the `app.test_client()` object in`client.environ_base`.Basic usage is outlined in the :ref:`testing` chapter."""preserve_context = Falsedef __init__(self, *args, **kwargs):super(FlaskClient, self).__init__(*args, **kwargs)self.environ_base = {"REMOTE_ADDR": "127.0.0.1","HTTP_USER_AGENT": "werkzeug/" + werkzeug.__version__}@contextmanagerdef session_transaction(self, *args, **kwargs):"""When used in combination with a ``with`` statement this opens asession transaction. This can be used to modify the session thatthe test client uses. Once the ``with`` block is left the session isstored back.::with client.session_transaction() as session:session['value'] = 42Internally this is implemented by going through a temporary testrequest context and since session handling could depend onrequest variables this function accepts the same arguments as:meth:`~flask.Flask.test_request_context` which are directlypassed through."""if self.cookie_jar is None:raise RuntimeError('Session transactions only make sense ''with cookies enabled.')app = self.applicationenviron_overrides = kwargs.setdefault('environ_overrides', {})self.cookie_jar.inject_wsgi(environ_overrides)outer_reqctx = _request_ctx_stack.topwith app.test_request_context(*args, **kwargs) as c:session_interface = app.session_interfacesess = session_interface.open_session(app, c.request)if sess is None:raise RuntimeError('Session backend did not open a session. ''Check the configuration')# Since we have to open a new request context for the session# handling we want to make sure that we hide out own context# from the caller. By pushing the original request context# (or None) on top of this and popping it we get exactly that# behavior. It's important to not use the push and pop# methods of the actual request context object since that would# mean that cleanup handlers are called_request_ctx_stack.push(outer_reqctx)try:yield sessfinally:_request_ctx_stack.pop()resp = app.response_class()if not session_interface.is_null_session(sess):session_interface.save_session(app, sess, resp)headers = resp.get_wsgi_headers(c.request.environ)self.cookie_jar.extract_wsgi(c.request.environ, headers)def open(self, *args, **kwargs):as_tuple = kwargs.pop('as_tuple', False)buffered = kwargs.pop('buffered', False)follow_redirects = kwargs.pop('follow_redirects', False)if (not kwargs and len(args) == 1and isinstance(args[0], (EnvironBuilder, dict))):environ = self.environ_base.copy()if isinstance(args[0], EnvironBuilder):environ.update(args[0].get_environ())else:environ.update(args[0])environ['flask._preserve_context'] = self.preserve_contextelse:kwargs.setdefault('environ_overrides', {}) \['flask._preserve_context'] = self.preserve_contextkwargs.setdefault('environ_base', self.environ_base)builder = make_test_environ_builder(self.application, *args, **kwargs)try:environ = builder.get_environ()finally:builder.close()return Client.open(self, environ,as_tuple=as_tuple,buffered=buffered,follow_redirects=follow_redirects)def __enter__(self):if self.preserve_context:raise RuntimeError('Cannot nest client invocations')self.preserve_context = Truereturn selfdef __exit__(self, exc_type, exc_value, tb):self.preserve_context = False# on exit we want to clean up earlier. Normally the request context# stays preserved until the next request in the same thread comes# in. See RequestGlobals.push() for the general behavior.top = _request_ctx_stack.topif top is not None and top.preserved:top.pop()class FlaskCliRunner(CliRunner):"""A :class:`~click.testing.CliRunner` for testing a Flask app'sCLI commands. Typically created using:meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`."""def __init__(self, app, **kwargs):self.app = appsuper(FlaskCliRunner, self).__init__(**kwargs)def invoke(self, cli=None, args=None, **kwargs):"""Invokes a CLI command in an isolated environment. See:meth:`CliRunner.invoke <click.testing.CliRunner.invoke>` forfull method documentation. See :ref:`testing-cli` for examples.If the ``obj`` argument is not given, passes an instance of:class:`~flask.cli.ScriptInfo` that knows how to load the Flaskapp being tested.:param cli: Command object to invoke. Default is the app's:attr:`~flask.app.Flask.cli` group.:param args: List of strings to invoke the command with.:return: a :class:`~click.testing.Result` object."""if cli is None:cli = self.app.cliif 'obj' not in kwargs:kwargs['obj'] = ScriptInfo(create_app=lambda: self.app)return super(FlaskCliRunner, self).invoke(cli, args, **kwargs)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。