flask.ctx -- Flask上下文

class AppContext(object):
    """应用程序上下文将应用程序对象隐式绑定到当前线程或greenlet,
    类似于:class:`RequestContext`绑定请求信息。
    如果创建了请求上下文但应用程序不是,则也会隐式创建应用程序上下文 在个人应用程序上下文之上。
    """

    def __init__(self, app):
        self.app = app
        self.url_adapter = app.create_url_adapter(None)
        self.g = app.app_ctx_globals_class()

        # 与请求上下文一样,应用程序上下文可以多次推送,但基本的“引用计数”足以跟踪它们。
        self._refcnt = 0

    def push(self):
        """将应用程序上下文绑定到当前上下文。"""
        self._refcnt += 1
        if hasattr(sys, 'exc_clear'):
            sys.exc_clear()
        _app_ctx_stack.push(self)
        appcontext_pushed.send(self.app)

    def pop(self, exc=_sentinel):
        """删除应用程序上下文。"""
        try:
            self._refcnt -= 1
            if self._refcnt <= 0:
                if exc is _sentinel:
                    exc = sys.exc_info()[1]
                self.app.do_teardown_appcontext(exc)
        finally:
            rv = _app_ctx_stack.pop()
        assert rv is self, 'Popped wrong app context.  (%r instead of %r)' \
            % (rv, self)
        appcontext_popped.send(self.app)

    def __enter__(self):
        self.push()
        return self

    def __exit__(self, exc_type, exc_value, tb):
        self.pop(exc_value)

        if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None:
            reraise(exc_type, exc_value, tb)
class RequestContext(object):
    """
    请求上下文包含所有与请求相关的信息。它是在请求开始时创建的,
    并被推送到“_request_ctx_stack”并在请求结束时删除。它将为提供的WSGI环境创建URL适配器和请求对象。
	不要尝试直接使用这个类,而是使用
	:meth:“~ flask.Flask。test_request_context”和
	:meth:“~ flask.Flask。request_context '来创建这个对象。
	当请求上下文弹出时,它将计算所有
	在应用程序上注册的用于拆卸执行的函数
	(:meth:“~ flask.Flask.teardown_request”)。
	请求上下文会在请求的末尾自动弹出。在调试模式下,如果发生异常,请求上下文将保留,以便交互式调试器有机会内省数据。
	对于没有失败且在“调试”模式之外的请求,也可以强制使用0.4。
	通过设置“meth。在WSGI环境中,上下文不会在请求结束时弹出自己。
	这是由:meth:' ~flask.Flask。例如test_client '来实现延迟清理功能。
	您可能会发现这对单元测试很有帮助,因为您需要
	从上下文本地获取信息的时间更长一些。确保正确:meth:' ~werkzeug.LocalStack。在这种情况下自己弹出堆栈,
	否则单元测试将泄漏内存。
    """

    def __init__(self, app, environ, request=None):
        self.app = app
        if request is None:
            request = app.request_class(environ)
        self.request = request
        self.url_adapter = app.create_url_adapter(self.request)
        self.flashes = None
        self.session = None

       # 可以多次推送请求上下文并与其他请求上下文交织。
       # 现在,只有弹出最后一个级别,我们才能摆脱它们。 
       # 此外,如果缺少应用程序上下文,则会隐式创建,因此对于每个级别,我们都会添加此信息
        self._implicit_app_ctx_stack = []

       # 如果保留上下文,则指示。 下次推送另一个上下文时,将弹出保留的上下文。
        self.preserved = False

       # 如果存在上下文保留的情况,则会记住pop的异常。
        self._preserved_exc = None
		
	   # 在响应对象上发出请求后应执行的函数。 这些将在常规“after_request”函数之前调用。
        self._after_request_functions = []

        self.match_request()

    def _get_g(self):
        return _app_ctx_stack.top.g
    def _set_g(self, value):
        _app_ctx_stack.top.g = value
    g = property(_get_g, _set_g)
    del _get_g, _set_g

    def copy(self):
        """
        使用相同的请求对象创建此请求上下文的副本。
         这可用于将请求上下文移动到不同的greenlet。
         因为实际的请求对象是相同的,所以除非锁定对请求对象的访问,否则不能将请求上下文移动到不同的线程。
        """
        return self.__class__(self.app,
            environ=self.request.environ,
            request=self.request
        )

    def match_request(self):
        """
        可以被子类覆盖,以连接到请求的匹配。
        """
        try:
            url_rule, self.request.view_args = \
                self.url_adapter.match(return_rule=True)
            self.request.url_rule = url_rule
        except HTTPException as e:
            self.request.routing_exception = e

    def push(self):
        """将请求上下文绑定到当前上下文。"""
        """
        如果在调试模式下发生异常,或者在异常情况下激活了上下文保留,则只有一个上下文保留在堆栈上。 
        理由是您希望在调试情况下访问该信息。 但是,如果有人忘记再次弹出该上下文,
        我们希望确保在下一次推送时它无效,否则我们会冒一些泄漏内存的风险。 
        这通常只是测试套件中的一个问题,因为此功能在生产环境中不活动。
        """
        top = _request_ctx_stack.top
        if top is not None and top.preserved:
            top.pop(top._preserved_exc)

		# 在我们推送请求上下文之前,我们必须确保存在应用程序上下文。
        app_ctx = _app_ctx_stack.top
        if app_ctx is None or app_ctx.app != self.app:
            app_ctx = self.app.app_context()
            app_ctx.push()
            self._implicit_app_ctx_stack.append(app_ctx)
        else:
            self._implicit_app_ctx_stack.append(None)

        if hasattr(sys, 'exc_clear'):
            sys.exc_clear()

        _request_ctx_stack.push(self)

		# 在请求上下文可用时打开会话。 这允许自定义open_session方法使用请求上下文。 
		# 如果这是第一次推送请求,则仅打开新会话,否则stream_with_context将丢失会话。
        if self.session is None:
            session_interface = self.app.session_interface
            self.session = session_interface.open_session(
                self.app, self.request
            )

            if self.session is None:
                self.session = session_interface.make_null_session(self.app)

    def pop(self, exc=_sentinel):
        """
        弹出请求上下文并通过执行此操作解除绑定。 这也将触发执行注册的功能
         :meth:`~flask.Flask.teardown_request`装饰。
        """
        app_ctx = self._implicit_app_ctx_stack.pop()

        try:
            clear_request = False
            if not self._implicit_app_ctx_stack:
                self.preserved = False
                self._preserved_exc = None
                if exc is _sentinel:
                    exc = sys.exc_info()[1]
                self.app.do_teardown_request(exc)

               # 如果此解释器支持清除异常信息,我们现在就这样做。 这只会在Python 2.x上生效,
  			   
  			   # 在3.x上,它在异常堆栈结束时自动消失。
                if hasattr(sys, 'exc_clear'):
                    sys.exc_clear()

                request_close = getattr(self.request, 'close', None)
                if request_close is not None:
                    request_close()
                clear_request = True
        finally:
            rv = _request_ctx_stack.pop()

	 		# 在请求结束时摆脱循环依赖关系,这样我们就不需要GC处于活动状态。
            if clear_request:
                rv.request.environ['werkzeug.request'] = None

            # 如有必要,摆脱应用程序
            if app_ctx is not None:
                app_ctx.pop(exc)

            assert rv is self, 'Popped wrong request context.  ' \
                '(%r instead of %r)' % (rv, self)

    def auto_pop(self, exc):
        if self.request.environ.get('flask._preserve_context') or \
           (exc is not None and self.app.preserve_context_on_exception):
            self.preserved = True
            self._preserved_exc = exc
        else:
            self.pop(exc)

    def __enter__(self):
        self.push()
        return self

    def __exit__(self, exc_type, exc_value, tb):
        # 如果我们处于调试模式并且发生异常,请不要弹出请求堆栈。 
        # 这将允许调试器仍然访问交互式shell中的请求对象。 此外上下文可以为测试客户端强制保持活动状态。
        self.auto_pop(exc_value)

        if BROKEN_PYPY_CTXMGR_EXIT and exc_type is not None:
            reraise(exc_type, exc_value, tb)

    def __repr__(self):
        return '<%s \'%s\' [%s] of %s>' % (
            self.__class__.__name__,
            self.request.url,
            self.request.method,
            self.app.name,
        )
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值