text: """:mod:`sassutils.wsgi` --- WSGI middleware for development purpose
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  """
  from __future__ import absolute_import, with_statement
  
  import collections
  import logging
  import os
  import os.path
  
  from pkg_resources import resource_filename
  
  from sass import CompileError
  from .builder import Manifest
  
  __all__ = 'SassMiddleware',
  
  
  class SassMiddleware(object):
      r"""WSGI middleware for development purpose.  Everytime a CSS file has
      requested it finds a matched Sass/SCSS source file and then compiled
      it into CSS.
  
      It shows syntax errors in three ways:
  
      Heading comment
          The result CSS includes detailed error message in the heading
          CSS comment e.g.:
  
          .. code-block:: css
  
              /*
              Error: invalid property name
              */
  
      Red text in ``body:before``
          The result CSS draws detailed error message in ``:before``
          pseudo-class of ``body`` element e.g.:
  
          .. code-block:: css
  
              body:before {
                  content: 'Error: invalid property name';
                  color: maroon;
                  background-color: white;
              }
  
          In most cases you could be aware of syntax error by refreshing your
          working document because it will removes all other styles and leaves
          only a red text.
  
      :mod:`logging`
          It logs syntax errors if exist during compilation to
          ``sassutils.wsgi.SassMiddleware`` logger with level ``ERROR``.
  
          To enable this::
  
              from logging import Formatter, StreamHandler, getLogger
              logger = getLogger('sassutils.wsgi.SassMiddleware')
              handler = StreamHandler(level=logging.ERROR)
              formatter = Formatter(fmt='*' * 80 + '\n%(message)s\n' + '*' * 80)
              handler.setFormatter(formatter)
              logger.addHandler(handler)
  
          Or simply::
  
              import logging
              logging.basicConfig()
  
      :param app: the WSGI application to wrap
      :type app: :class:`collections.abc.Callable`
      :param manifests: build settings.  the same format to
                        :file:`setup.py` script's ``sass_manifests``
                        option
      :type manifests: :class:`collections.abc.Mapping`
      :param package_dir: optional mapping of package names to directories.
                          the same format to :file:`setup.py` script's
                          ``package_dir`` option
      :type package_dir: :class:`collections.abc.Mapping`
  
      .. versionchanged:: 0.4.0
         It creates also source map files with filenames followed by
         :file:`.map` suffix.
  
      .. versionadded:: 0.8.0
         It logs syntax errors if exist during compilation to
         ``sassutils.wsgi.SassMiddleware`` logger with level ``ERROR``.
  
      """
  
      def __init__(
          self, app, manifests, package_dir={},
          error_status='200 OK',
      ):
          if not callable(app):
              raise TypeError('app must be a WSGI-compliant callable object, '
                              'not ' + repr(app))
          self.app = app
          self.manifests = Manifest.normalize_manifests(manifests)
          if not isinstance(package_dir, collections.Mapping):
              raise TypeError('package_dir must be a mapping object, not ' +
                              repr(package_dir))
          self.error_status = error_status
          self.package_dir = dict(package_dir)
          for package_name in self.manifests:
              if package_name in self.package_dir:
                  continue
              path = resource_filename(package_name, '')
              self.package_dir[package_name] = path
          self.paths = []
          for package_name, manifest in self.manifests.items():
              wsgi_path = manifest.wsgi_path
              if not wsgi_path.startswith('/'):
                  wsgi_path = '/' + wsgi_path
              if not wsgi_path.endswith('/'):
                  wsgi_path += '/'
              package_dir = self.package_dir[package_name]
              self.paths.append((wsgi_path, package_dir, manifest))
  
      def __call__(self, environ, start_response):
          path = environ.get('PATH_INFO', '/')
          if path.endswith('.css'):
              for prefix, package_dir, manifest in self.paths:
                  if not path.startswith(prefix):
                      continue
                  css_filename = path[len(prefix):]
                  sass_filename = css_filename[:-4]
                  try:
                      result = manifest.build_one(
                          package_dir,
                          sass_filename,
                          source_map=True,
                      )
                  except (IOError, OSError):
                      break
                  except CompileError as e:
                      logger = logging.getLogger(__name__ + '.SassMiddleware')
                      logger.error(str(e))
                      start_response(
                          self.error_status,
                          [('Content-Type', 'text/css; charset=utf-8')],
                      )
                      return [
                          b'/*\n', str(e).encode('utf-8'), b'\n*/\n\n',
                          b'body:before { content: ',
                          self.quote_css_string(str(e)).encode('utf-8'),
                          b'; color: maroon; background-color: white',
                          b'; white-space: pre-wrap; display: block',
                          b'; font-family: "Courier New", monospace'
                          b'; user-select: text; }',
                      ]
  
                  def read_file(path):
                      with open(path, 'rb') as in_:
                          while 1:
                              chunk = in_.read(4096)
                              if chunk:
                                  yield chunk
                              else:
                                  break
                  start_response('200 OK', [('Content-Type', 'text/css')])
                  return read_file(os.path.join(package_dir, result))
          return self.app(environ, start_response)
  
      @staticmethod
      def quote_css_string(s):
          """Quotes a string as CSS string literal."""
          return "'" + ''.join('\\%06x' % ord(c) for c in s) + "'"
  