text: #!/usr/bin/env python
  #
  # Copyright 2007 Google LLC
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  
  
  """A request-local environment and logging stream."""
  
  
  
  
  
  
  
  
  import abc
  import cgi
  import collections
  import os
  import sys
  import threading
  
  import six
  
  _sys_stderr = sys.stderr
  
  
  class RequestEnvironment(threading.local):
    """A thread local request environment.
  
    A thread local request environment that provides an error stream errors and a
    dict of the request environment environ as would be found in os.environ. A
    single error stream is shared between threads of a single request, but each
    thread accesses an independent copy of environ created when
    CloneRequestEnvironment is called. A request environment of one thread can be
    installed in another thread as follows:
      1. Call CloneRequestEnvironment in the first thread.
      2. Call the returned callable from the other thread.
    """
  
    def __init__(self):
      super(RequestEnvironment, self).__init__()
      self.Reset()
  
    def Reset(self):
      """Resets the error stream and environment for this request."""
      self.errors = _sys_stderr
      self.environ = {}
      self.runtime_stats = {}
  
    def Init(self, errors, environ, runtime_stats=None):
      self.errors = errors
  
      if environ is not None:
        self.environ = environ
  
      if runtime_stats is None:
        self.runtime_stats = {}
      else:
        self.runtime_stats = runtime_stats
  
    def CloneRequestEnvironment(self):
      """Returns a callable that will install the environment in another thread.
  
      Returns:
        A callable that will duplicate the request environment of this thread in
        another thread that calls it.
      """
      errors = self.errors
      environ = dict(self.environ)
      runtime_stats = self.runtime_stats
      return lambda: self.Init(errors, environ, runtime_stats)
  
    def Clear(self):
      """Clears the thread locals."""
      self.__dict__.clear()
      self.Reset()
  
    def IncrementStat(self, metric, code):
      """Increments a tracked runtime statistic."""
      m = self.runtime_stats.get(metric)
      if m is None: return
      m[code] = m.get(code, 0) + 1
  
  
  class RequestLocalStream(object):
    """A stream that delegates to a RequestEnvironment stream."""
  
    def __init__(self, request):
      self._request = request
  
    def close(self):
      pass
  
    def flush(self):
      self._request.errors.flush()
  
    def write(self, data):
      self._request.errors.write(data)
  
    def writelines(self, data):
      self._request.errors.writelines(data)
  
    def isatty(self):
      return False
  
  
  class RequestLocalEnviron(collections.MutableMapping):
    """A MutableMapping that delegates to a RequestEnvironment environ."""
  
    def __init__(self, request):
      self._request = request
  
    def __len__(self):
      return len(self._request.environ)
  
    def __iter__(self):
      return iter(self._request.environ)
  
    def __getitem__(self, key):
      return self._request.environ[key]
  
    def __setitem__(self, key, value):
      self._request.environ[key] = value
  
    def __delitem__(self, key):
      del self._request.environ[key]
  
    def __repr__(self):
      return repr(self._request.environ)
  
    def has_key(self, key):
      return key in self._request.environ
  
    def copy(self):
      return dict(self._request.environ)
  
  
  
    def viewitems(self):
      return collections.ItemsView(self)
  
    def viewkeys(self):
      return collections.KeysView(self)
  
    def viewvalues(self):
      return collections.ValuesView(self)
  
  
  current_request = RequestEnvironment()
  
  
  
  
  
  def PatchOsEnviron(os_module=os):
    """Replace os.environ by a RequestLocalEnviron instance.
  
    This is called from init.py when it modifies the execution
    environment (in the wider sense of the word).
  
    Args:
      os_module: An optional module to patch. Defaults to os.
    """
    os_module.environ = RequestLocalEnviron(current_request)
  
  
    cached_class = cgi.FieldStorage
    six.moves.reload_module(cgi)
  
  
  
  
    class FieldStorage(six.with_metaclass(abc.ABCMeta, cgi.FieldStorage, object)):
      pass
  
    FieldStorage.register(cached_class)
  
    cgi.FieldStorage = FieldStorage
  