예제 #1
0
파일: svn_fs.py 프로젝트: t2y/trac
 def tearDown(self):
     self.repos.close()
     self.repos = None
     # clear cached repositories to avoid TypeError on termination (#11505)
     RepositoryManager(self.env).reload_repositories()
     self.env.reset_db()
     # needed to avoid issue with 'WindowsError: The process cannot access
     # the file ... being used by another process: ...\rep-cache.db'
     self.env.shutdown(get_thread_id())
예제 #2
0
파일: main.py 프로젝트: wataash/trac
def dispatch_request(environ, start_response):
    """Main entry point for the Trac web interface.

    :param environ: the WSGI environment dict
    :param start_response: the WSGI callback for starting the response
    """

    global _warn_setuptools
    if _warn_setuptools is False:
        _warn_setuptools = True
        warn_setuptools_issue(out=environ.get('wsgi.errors'))

    # SCRIPT_URL is an Apache var containing the URL before URL rewriting
    # has been applied, so we can use it to reconstruct logical SCRIPT_NAME
    script_url = environ.get('SCRIPT_URL')
    if script_url is not None:
        path_info = environ.get('PATH_INFO')
        if not path_info:
            environ['SCRIPT_NAME'] = script_url
        else:
            # mod_wsgi squashes slashes in PATH_INFO (!)
            script_url = _slashes_re.sub('/', script_url)
            path_info = _slashes_re.sub('/', path_info)
            if script_url.endswith(path_info):
                environ['SCRIPT_NAME'] = script_url[:-len(path_info)]

    # If the expected configuration keys aren't found in the WSGI environment,
    # try looking them up in the process environment variables
    environ.setdefault('trac.env_path', os.getenv('TRAC_ENV'))
    environ.setdefault('trac.env_parent_dir',
                       os.getenv('TRAC_ENV_PARENT_DIR'))
    environ.setdefault('trac.env_index_template',
                       os.getenv('TRAC_ENV_INDEX_TEMPLATE'))
    environ.setdefault('trac.template_vars',
                       os.getenv('TRAC_TEMPLATE_VARS'))
    environ.setdefault('trac.locale', '')
    environ.setdefault('trac.base_url',
                       os.getenv('TRAC_BASE_URL'))

    locale.setlocale(locale.LC_ALL, environ['trac.locale'])

    # Determine the environment
    env_path = environ.get('trac.env_path')
    if not env_path:
        env_parent_dir = environ.get('trac.env_parent_dir')
        env_paths = environ.get('trac.env_paths')
        if env_parent_dir or env_paths:
            # The first component of the path is the base name of the
            # environment
            path_info = environ.get('PATH_INFO', '').lstrip('/').split('/')
            env_name = path_info.pop(0)

            if not env_name:
                # No specific environment requested, so render an environment
                # index page
                send_project_index(environ, start_response, env_parent_dir,
                                   env_paths)
                return []

            errmsg = None

            # To make the matching patterns of request handlers work, we append
            # the environment name to the `SCRIPT_NAME` variable, and keep only
            # the remaining path in the `PATH_INFO` variable.
            script_name = environ.get('SCRIPT_NAME', '')
            try:
                script_name = unicode(script_name, 'utf-8')
            except UnicodeDecodeError:
                errmsg = 'Invalid URL encoding (was %r)' % script_name
            else:
                # (as Href expects unicode parameters)
                environ['SCRIPT_NAME'] = Href(script_name)(env_name)
                environ['PATH_INFO'] = '/' + '/'.join(path_info)

                if env_parent_dir:
                    env_path = os.path.join(env_parent_dir, env_name)
                else:
                    env_path = get_environments(environ).get(env_name)

                if not env_path or not os.path.isdir(env_path):
                    errmsg = 'Environment not found'

            if errmsg:
                start_response('404 Not Found',
                               [('Content-Type', 'text/plain'),
                                ('Content-Length', str(len(errmsg)))])
                return [errmsg]

    if not env_path:
        raise EnvironmentError('The environment options "TRAC_ENV" or '
                               '"TRAC_ENV_PARENT_DIR" or the mod_python '
                               'options "TracEnv" or "TracEnvParentDir" are '
                               'missing. Trac requires one of these options '
                               'to locate the Trac environment(s).')
    run_once = environ['wsgi.run_once']

    env = env_error = None
    try:
        env = open_environment(env_path, use_cache=not run_once)
    except Exception as e:
        env_error = e
    else:
        if env.base_url_for_redirect:
            environ['trac.base_url'] = env.base_url

        # Web front-end type and version information
        if not hasattr(env, 'webfrontend'):
            mod_wsgi_version = environ.get('mod_wsgi.version')
            if mod_wsgi_version:
                mod_wsgi_version = (
                        "%s (WSGIProcessGroup %s WSGIApplicationGroup %s)" %
                        ('.'.join(str(x) for x in mod_wsgi_version),
                         environ.get('mod_wsgi.process_group'),
                         environ.get('mod_wsgi.application_group') or
                         '%{GLOBAL}'))
                environ.update({
                    'trac.web.frontend': 'mod_wsgi',
                    'trac.web.version': mod_wsgi_version})
            env.webfrontend = environ.get('trac.web.frontend')
            if env.webfrontend:
                env.webfrontend_version = environ['trac.web.version']

    req = RequestWithSession(environ, start_response)
    # fixup env.abs_href if `[trac] base_url` was not specified
    if env and not env.abs_href.base:
        env.abs_href = req.abs_href
    translation.make_activable(lambda: req.locale, env.path if env else None)
    resp = []
    try:
        if env_error:
            raise HTTPInternalServerError(env_error)
        dispatcher = RequestDispatcher(env)
        dispatcher.set_default_callbacks(req)
        try:
            dispatcher.dispatch(req)
        except RequestDone as req_done:
            resp = req_done.iterable
    except HTTPException as e:
        if not req.response_started:
            _send_user_error(req, env, e)
    except Exception:
        if not req.response_started:
            send_internal_error(env, req, sys.exc_info())
    else:
        resp = resp or req._response or []
    finally:
        translation.deactivate()
        if env and not run_once:
            env.shutdown(get_thread_id())
            # Now it's a good time to do some clean-ups
            #
            # Note: enable the '##' lines as soon as there's a suspicion
            #       of memory leak due to uncollectable objects (typically
            #       objects with a __del__ method caught in a cycle)
            #
            ##gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
            unreachable = gc.collect()
            ##env.log.debug("%d unreachable objects found.", unreachable)
            ##uncollectable = len(gc.garbage)
            ##if uncollectable:
            ##    del gc.garbage[:]
            ##    env.log.warning("%d uncollectable objects found.",
            ##                    uncollectable)
        return resp
예제 #3
0
 def tearDown(self):
     self.env.reset_db()
     # needed to avoid issue with 'WindowsError: The process cannot access
     # the file ... being used by another process: ...\rep-cache.db'
     self.env.shutdown(get_thread_id())
예제 #4
0
    def get_cnx(self, connector, kwargs, timeout=None):
        cnx = None
        log = kwargs.get('log')
        key = unicode(kwargs)
        start = time_now()
        tid = get_thread_id()
        # Get a Connection, either directly or a deferred one
        with self._available:
            # First choice: Return the same cnx already used by the thread
            if (tid, key) in self._active:
                cnx, num = self._active[(tid, key)]
                num += 1
            else:
                if self._waiters == 0:
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                if not cnx:
                    self._waiters += 1
                    self._available.wait()
                    self._waiters -= 1
                    cnx = self._take_cnx(connector, kwargs, key, tid)
                num = 1
            if cnx:
                self._active[(tid, key)] = (cnx, num)

        deferred = num == 1 and isinstance(cnx, tuple)
        exc_info = (None, None, None)
        if deferred:
            # Potentially lengthy operations must be done without lock held
            op, cnx = cnx
            try:
                if op == 'ping':
                    cnx.ping()
                elif op == 'close':
                    cnx.close()
                if op in ('close', 'create'):
                    cnx = connector.get_connection(**kwargs)
            except TracError:
                exc_info = sys.exc_info()
                cnx = None
            except Exception:
                exc_info = sys.exc_info()
                if log:
                    log.error('Exception caught on %s', op, exc_info=True)
                cnx = None

        if cnx and not isinstance(cnx, tuple):
            if deferred:
                # replace placeholder with real Connection
                with self._available:
                    self._active[(tid, key)] = (cnx, num)
            return PooledConnection(self, cnx, key, tid, log)

        if deferred:
            # cnx couldn't be reused, clear placeholder
            with self._available:
                del self._active[(tid, key)]
            if op == 'ping':  # retry
                return self.get_cnx(connector, kwargs)

        # if we didn't get a cnx after wait(), something's fishy...
        if isinstance(exc_info[1], TracError):
            raise exc_info[0], exc_info[1], exc_info[2]
        timeout = time_now() - start
        errmsg = _(
            "Unable to get database connection within %(time)d seconds.",
            time=timeout)
        if exc_info[1]:
            errmsg += " (%s)" % exception_to_unicode(exc_info[1])
        raise TimeoutError(errmsg)
예제 #5
0
 def tearDown(self):
     self.env.reset_db()
     # needed to avoid issue with 'WindowsError: The process cannot access
     # the file ... being used by another process: ...\rep-cache.db'
     self.env.shutdown(get_thread_id())