# HG changeset patch # User Marcin Kuzminski # Date 1302340952 -7200 # Node ID 73434499fa7225f17ab221434143228ce7edda07 # Parent 2182a2005278a543aeaea7ceab0f2923e150a3cf merges for stable diff -r 2182a2005278 -r 73434499fa72 docs/changelog.rst --- a/docs/changelog.rst Fri Apr 08 00:47:20 2011 +0200 +++ b/docs/changelog.rst Sat Apr 09 11:22:32 2011 +0200 @@ -20,6 +20,9 @@ - fixes for issues #137 and #116 - fixes crashes on gravatar, when passed in email as unicode - fixed tooltip flickering problems +- fixed came_from redirection on windows +- fixed logging modules,and sql formatters +- windows fixes for os.kill and path spliting, issues #148 and #133 1.1.7 (**2011-03-23**) ====================== diff -r 2182a2005278 -r 73434499fa72 rhodecode/__init__.py --- a/rhodecode/__init__.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/__init__.py Sat Apr 09 11:22:32 2011 +0200 @@ -31,8 +31,8 @@ __platform__ = platform.system() __license__ = 'GPLv3' -PLATFORM_WIN = ('Windows',) -PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD',) +PLATFORM_WIN = ('Windows') +PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD') try: from rhodecode.lib.utils import get_current_revision @@ -52,5 +52,5 @@ BACKENDS = { 'hg': 'Mercurial repository', - #'git': 'Git repository', + #'git': 'Git repository', } diff -r 2182a2005278 -r 73434499fa72 rhodecode/lib/__init__.py --- a/rhodecode/lib/__init__.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/lib/__init__.py Sat Apr 09 11:22:32 2011 +0200 @@ -23,20 +23,33 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -def str2bool(s): - if s is None: + +def str2bool(_str): + """ + returs True/False value from given string, it tries to translate the + string into boolean + + :param _str: string value to translate into boolean + :rtype: boolean + :returns: boolean from given string + """ + if _str is None: return False - if s in (True, False): - return s - s = str(s).strip().lower() - return s in ('t', 'true', 'y', 'yes', 'on', '1') + if _str in (True, False): + return _str + _str = str(_str).strip().lower() + return _str in ('t', 'true', 'y', 'yes', 'on', '1') + def generate_api_key(username, salt=None): """ - Generates uniq API key for given username + Generates unique API key for given username,if salt is not given + it'll be generated from some random string :param username: username as string :param salt: salt to hash generate KEY + :rtype: str + :returns: sha1 hash from username+salt """ from tempfile import _RandomNameSequence import hashlib @@ -46,23 +59,23 @@ return hashlib.sha1(username + salt).hexdigest() -def safe_unicode(_str): + +def safe_unicode(_str, from_encoding='utf8'): """ safe unicode function. In case of UnicodeDecode error we try to return - unicode with errors replace, if this fails we return unicode with - string_escape decoding + unicode with errors replace + + :param _str: string to decode + :rtype: unicode + :returns: unicode object """ if isinstance(_str, unicode): return _str try: - u_str = unicode(_str) + u_str = unicode(_str, from_encoding) except UnicodeDecodeError: - try: - u_str = _str.decode('utf-8', 'replace') - except UnicodeDecodeError: - #incase we have a decode error just represent as byte string - u_str = unicode(_str.encode('string_escape')) + u_str = unicode(_str, from_encoding, 'replace') - return u_str \ No newline at end of file + return u_str diff -r 2182a2005278 -r 73434499fa72 rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/lib/auth.py Sat Apr 09 11:22:32 2011 +0200 @@ -354,14 +354,7 @@ return func(*fargs, **fkwargs) else: log.warn('user %s not authenticated', user.username) - - p = '' - if request.environ.get('SCRIPT_NAME') != '/': - p += request.environ.get('SCRIPT_NAME') - - p += request.environ.get('PATH_INFO') - if request.environ.get('QUERY_STRING'): - p += '?' + request.environ.get('QUERY_STRING') + p = url.current() log.debug('redirecting to login page with %s', p) return redirect(url('login_home', came_from=p)) diff -r 2182a2005278 -r 73434499fa72 rhodecode/lib/colored_formatter.py --- a/rhodecode/lib/colored_formatter.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/lib/colored_formatter.py Sat Apr 09 11:22:32 2011 +0200 @@ -3,7 +3,7 @@ BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38) -# Sequences +# Sequences RESET_SEQ = "\033[0m" COLOR_SEQ = "\033[1;%dm" BOLD_SEQ = "\033[1m" @@ -14,8 +14,35 @@ 'WARNING': CYAN, # level 30 'INFO': GREEN, # level 20 'DEBUG': BLUE, # level 10 + 'SQL' : YELLOW } +def one_space_trim(s): + if s.find(" ") == -1: + return s + else: + s = s.replace(' ', ' ') + return one_space_trim(s) + +def format_sql(sql): + sql = sql.replace('\n', '') + sql = one_space_trim(sql) + sql = sql\ + .replace(',', ',\n\t')\ + .replace('SELECT', '\n\tSELECT \n\t')\ + .replace('UPDATE', '\n\tUPDATE \n\t')\ + .replace('DELETE', '\n\tDELETE \n\t')\ + .replace('FROM', '\n\tFROM')\ + .replace('ORDER BY', '\n\tORDER BY')\ + .replace('LIMIT', '\n\tLIMIT')\ + .replace('WHERE', '\n\tWHERE')\ + .replace('AND', '\n\tAND')\ + .replace('LEFT', '\n\tLEFT')\ + .replace('INNER', '\n\tINNER')\ + .replace('INSERT', '\n\tINSERT')\ + .replace('DELETE', '\n\tDELETE') + return sql + class ColorFormatter(logging.Formatter): def __init__(self, *args, **kwargs): @@ -26,13 +53,30 @@ """ Changes record's levelname to use with COLORS enum """ - + levelname = record.levelname start = COLOR_SEQ % (COLORS[levelname]) def_record = logging.Formatter.format(self, record) end = RESET_SEQ - + colored_record = start + def_record + end return colored_record -logging.ColorFormatter = ColorFormatter + +class ColorFormatterSql(logging.Formatter): + + def __init__(self, *args, **kwargs): + # can't do super(...) here because Formatter is an old school class + logging.Formatter.__init__(self, *args, **kwargs) + + def format(self, record): + """ + Changes record's levelname to use with COLORS enum + """ + + start = COLOR_SEQ % (COLORS['SQL']) + def_record = format_sql(logging.Formatter.format(self, record)) + end = RESET_SEQ + + colored_record = start + def_record + end + return colored_record diff -r 2182a2005278 -r 73434499fa72 rhodecode/lib/exceptions.py --- a/rhodecode/lib/exceptions.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/lib/exceptions.py Sat Apr 09 11:22:32 2011 +0200 @@ -1,8 +1,15 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Custom Exceptions modules -# Copyright (C) 2009-2010 Marcin Kuzminski -# +# -*- coding: utf-8 -*- +""" + rhodecode.lib.exceptions + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Custom Exceptions modules + + :created_on: Apr 10, 2010 + :author: marcink + :copyright: (C) 2009-2011 Marcin Kuzminski + :license: GPLv3, see COPYING for more details. +""" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -15,16 +22,27 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -""" -Created on Nov 17, 2010 -Custom Exceptions modules -@author: marcink -""" + + +class LdapUsernameError(Exception): + pass + + +class LdapPasswordError(Exception): + pass + -class LdapUsernameError(Exception):pass -class LdapPasswordError(Exception):pass -class LdapConnectionError(Exception):pass -class LdapImportError(Exception):pass +class LdapConnectionError(Exception): + pass + + +class LdapImportError(Exception): + pass -class DefaultUserException(Exception):pass -class UserOwnsReposException(Exception):pass + +class DefaultUserException(Exception): + pass + + +class UserOwnsReposException(Exception): + pass diff -r 2182a2005278 -r 73434499fa72 rhodecode/lib/pidlock.py --- a/rhodecode/lib/pidlock.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/lib/pidlock.py Sat Apr 09 11:22:32 2011 +0200 @@ -4,6 +4,19 @@ from multiprocessing.util import Finalize import errno +from rhodecode import __platform__, PLATFORM_WIN + +if __platform__ in PLATFORM_WIN: + import ctypes + def kill(pid): + """kill function for Win32""" + kernel32 = ctypes.windll.kernel32 + handle = kernel32.OpenProcess(1, 0, pid) + return (0 != kernel32.TerminateProcess(handle, 0)) + +else: + kill = os.kill + class LockHeld(Exception):pass @@ -58,9 +71,9 @@ pidfile = open(self.pidfile, "r") pidfile.seek(0) running_pid = int(pidfile.readline()) - + pidfile.close() - + if self.debug: print 'lock file present running_pid: %s, checking for execution'\ % running_pid @@ -68,19 +81,19 @@ # process PID if running_pid: try: - os.kill(running_pid, 0) + kill(running_pid, 0) except OSError, exc: if exc.errno in (errno.ESRCH, errno.EPERM): print "Lock File is there but the program is not running" - print "Removing lock file for the: %s" % running_pid + print "Removing lock file for the: %s" % running_pid self.release() else: raise else: print "You already have an instance of the program running" - print "It is running as process %s" % running_pid + print "It is running as process %s" % running_pid raise LockHeld() - + except IOError, e: if e.errno != 2: raise @@ -90,7 +103,7 @@ """ if self.debug: print 'trying to release the pidlock' - + if self.callbackfn: #execute callback function on release if self.debug: diff -r 2182a2005278 -r 73434499fa72 rhodecode/lib/timerproxy.py --- a/rhodecode/lib/timerproxy.py Fri Apr 08 00:47:20 2011 +0200 +++ b/rhodecode/lib/timerproxy.py Sat Apr 09 11:22:32 2011 +0200 @@ -1,59 +1,28 @@ from sqlalchemy.interfaces import ConnectionProxy import time -from sqlalchemy import log +import logging +log = logging.getLogger('timerproxy') + BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38) def color_sql(sql): COLOR_SEQ = "\033[1;%dm" COLOR_SQL = YELLOW normal = '\x1b[0m' - return COLOR_SEQ % COLOR_SQL + sql + normal - -def one_space_trim(s): - if s.find(" ") == -1: - return s - else: - s = s.replace(' ', ' ') - return one_space_trim(s) - -def format_sql(sql): - sql = color_sql(sql) - sql = sql.replace('\n', '') - sql = one_space_trim(sql) - sql = sql\ - .replace(',', ',\n\t')\ - .replace('SELECT', '\n\tSELECT \n\t')\ - .replace('UPDATE', '\n\tUPDATE \n\t')\ - .replace('DELETE', '\n\tDELETE \n\t')\ - .replace('FROM', '\n\tFROM')\ - .replace('ORDER BY', '\n\tORDER BY')\ - .replace('LIMIT', '\n\tLIMIT')\ - .replace('WHERE', '\n\tWHERE')\ - .replace('AND', '\n\tAND')\ - .replace('LEFT', '\n\tLEFT')\ - .replace('INNER', '\n\tINNER')\ - .replace('INSERT', '\n\tINSERT')\ - .replace('DELETE', '\n\tDELETE') - return sql - + return COLOR_SEQ % COLOR_SQL + sql + normal class TimerProxy(ConnectionProxy): - + def __init__(self): super(TimerProxy, self).__init__() - self.logging_name = 'timerProxy' - self.log = log.instance_logger(self, True) - - def cursor_execute(self, execute, cursor, statement, parameters, context, executemany): - + + def cursor_execute(self, execute, cursor, statement, parameters, + context, executemany): + now = time.time() try: - self.log.info(">>>>> STARTING QUERY >>>>>") + log.info(color_sql(">>>>> STARTING QUERY >>>>>")) return execute(cursor, statement, parameters, context) finally: total = time.time() - now - try: - self.log.info(format_sql("Query: %s" % statement % parameters)) - except TypeError: - self.log.info(format_sql("Query: %s %s" % (statement, parameters))) - self.log.info("<<<<< TOTAL TIME: %f <<<<<" % total) + log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))