Modified: bloodhound/branches/bep_0007_embeddable_objects/installer/bloodhound_setup.py URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/installer/bloodhound_setup.py?rev=1604057&r1=1604056&r2=1604057&view=diff ============================================================================== --- bloodhound/branches/bep_0007_embeddable_objects/installer/bloodhound_setup.py (original) +++ bloodhound/branches/bep_0007_embeddable_objects/installer/bloodhound_setup.py Fri Jun 20 00:34:19 2014 @@ -20,29 +20,22 @@ import os import pkg_resources +import shutil import sys -import traceback - -import ConfigParser +from createdigest import htdigest_create from getpass import getpass from optparse import OptionParser -import shutil -import time - -from createdigest import htdigest_create - -LANG = os.environ.get('LANG') try: - from trac.util import translation - from trac.util.translation import _, get_negotiated_locale, has_babel from trac.admin.console import TracAdmin from trac.config import Configuration + from trac.util import translation + from trac.util.translation import _, get_negotiated_locale, has_babel except ImportError, e: - print ("Requirements should be installed before running bloodhound_setup.py.\n" - "You can install them with the following command:\n" - " pip install -r requirements.txt\n") - traceback.print_exc() + print("Requirements must be installed before running " + "bloodhound_setup.py.\n" + "You can install them with the following command:\n" + " pip install -r requirements.txt\n") sys.exit(1) try: @@ -50,8 +43,16 @@ try: except ImportError: psycopg2 = None +try: + import MySQLdb as mysqldb +except ImportError: + mysqldb = None + +LANG = os.environ.get('LANG') + MAXBACKUPNUMBER = 64 # Max attempts to create backup file +SUPPORTED_DBTYPES = ('sqlite', 'postgres', 'mysql') DEFAULT_DB_USER = 'bloodhound' DEFAULT_DB_NAME = 'bloodhound' DEFAULT_ADMIN_USER = 'admin' @@ -137,23 +138,27 @@ class BloodhoundSetup(object): def _generate_db_str(self, options): """Builds an appropriate db string for trac-admin for sqlite and - postgres options. Also allows for a user to provide their own db string - to allow database initialisation beyond these.""" - dbdata = {'user': options.get('dbuser'), + postgres options. Also allows for a user to provide their own db + string to allow database initialisation beyond these.""" + dbdata = {'type': options.get('dbtype', 'sqlite'), + 'user': options.get('dbuser'), 'pass': options.get('dbpass'), 'host': options.get('dbhost', 'localhost'), - 'port': options.get('dbport', '5432'), + 'port': options.get('dbport'), 'name': options.get('dbname', 'bloodhound'), } db = options.get('dbstring') if db is None: - dbtype = options.get('dbtype', 'sqlite') - if (dbtype == 'postgres' and dbdata['user'] is not None - and dbdata['pass'] is not None): - db = 'postgres://%(user)s:%(pass)s@%(host)s:%(port)s/%(name)s' + if dbdata['type'] in ('postgres', 'mysql') \ + and dbdata['user'] is not None \ + and dbdata['pass'] is not None: + if dbdata['port'] is not None: + db = '%(type)s://%(user)s:%(pass)s@%(host)s:%(port)s/%(name)s' + else: # no port specified = default port + db = '%(type)s://%(user)s:%(pass)s@%(host)s/%(name)s' else: - db = 'sqlite:%s' % os.path.join('db', '%(name)s.db') + db = '%%(type)s:%s' % os.path.join('db', '%(name)s.db') return db % dbdata def setup(self, **kwargs): @@ -174,6 +179,9 @@ class BloodhoundSetup(object): if psycopg2 is None and options.get('dbtype') == 'postgres': print "psycopg2 needs to be installed to initialise a postgresql db" return False + elif mysqldb is None and options.get('dbtype') == 'mysql': + print "MySQLdb needs to be installed to initialise a mysql db" + return False environments_path = options['envsdir'] if not os.path.exists(environments_path): @@ -304,7 +312,8 @@ And point your browser at http://localho """Writes or updates a config file. A list of dictionaries is used so that options for different aspects of the configuration can be kept separate while being able to update the same sections. Note that the - result is order dependent where two dictionaries update the same option. + result is order dependent where two dictionaries update the same + option. """ config = Configuration(filepath) file_changed = False @@ -355,7 +364,7 @@ def handle_options(): help='Set the directory to contain environments', default=os.path.join('bloodhound', 'environments')) parser.add_option('-d', '--database-type', dest='dbtype', - help="Specify as either 'postgres' or 'sqlite'", + help="Specify as either 'sqlite', 'postgres' or 'mysql'", default='') parser.add_option('--database-string', dest='dbstring', help=('Advanced: provide a custom database string, ' @@ -365,15 +374,15 @@ def handle_options(): help='Specify the database name', default='bloodhound') parser.add_option('-u', '--user', dest='dbuser', - help='Specify the db user (required for postgres)', + help='Specify the db user (required for postgres and mysql)', default='') parser.add_option('-p', '--password', dest='dbpass', - help='Specify the db password (option for postgres)') + help='Specify the db password (required for postgres and mysql)') parser.add_option('--database-host', dest='dbhost', - help='Specify the database host (optional for postgres)', + help='Specify the database host (optional for postgres and mysql)', default='localhost') parser.add_option('--database-port', dest='dbport', - help='Specify the database port (optional for postgres)', + help='Specify the database port (optional for postgres and mysql)', default='5432') # Account Manager Options @@ -420,28 +429,33 @@ def handle_options(): password2 = getpass('Please reenter the password: ') if password1 and password1 == password2: return password1 - print "Passwords did not match. Quitting." + print "Passwords did not match. Quiting." sys.exit(1) - if options.dbtype.lower() not in ['postgres','sqlite']: - answer = ask_question(''' -This installer is able to install Apache Bloodhound with either SQLite or -PostgreSQL databases. SQLite is an easier option for installing Bloodhound as -SQLite is usually built into Python and also requires no special permissions to -run. However, PostgreSQL is generally expected to be more robust for production -use. -Do you want to install to a PostgreSQL database [%s]: ''', default='Y/n') + if options.dbtype.lower() not in SUPPORTED_DBTYPES: + answer = ask_question(""" +This installer is able to install Apache Bloodhound with either SQLite, +PostgreSQL or MySQL databases. SQLite is an easier option for installing +Bloodhound as SQLite support is built into Python and requires no special +permissions to run. However, PostgreSQL and MySQL are generally expected to +be more robust for production use. +What type of database do you want to instant to (%s)? +[%%s]: """ % '/'.join(SUPPORTED_DBTYPES), default='sqlite') answer = answer.lower() - options.dbtype = 'postgres' if answer not in ['n','no'] else 'sqlite' + if answer in SUPPORTED_DBTYPES: + options.dbtype = answer + else: + print "Unrecognized dbtype \"%s\". Quiting." % answer + sys.exit(1) else: options.dbtype = options.dbtype.lower() - if options.dbtype == 'postgres': + if options.dbtype in ('postgres','mysql'): if not options.dbuser: options.dbuser = ask_question(""" -For PostgreSQL you need to have PostgreSQL installed and you need to have -created a database user to connect to the database with. Setting this up may -require admin access rights to the server. +For PostgreSQL/MySQL you need to have PostgreSQL/MySQL installed and you need +to have created a database user to connect to the database with. Setting this +up may require admin access rights to the server. DB user name [%s]: """, DEFAULT_DB_USER) if not options.dbpass: @@ -449,10 +463,9 @@ DB user name [%s]: """, DEFAULT_DB_USER) if not options.dbname: options.dbname = ask_question(""" -For PostgreSQL setup, you need to specify a database that you have created for -Bloodhound to use. This installer currently assumes that this database will be -empty. -DB name [%s]: """, DEFAULT_DB_NAME) +For PostgreSQL/MySQL setup, you need to specify a database that you have +created for Bloodhound to use. This installer currently assumes that this +database will be empty. DB name [%s]: """, DEFAULT_DB_NAME) if not options.adminuser: options.adminuser = ask_question(""" Please supply a username for the admin user [%s]: """, DEFAULT_ADMIN_USER) @@ -461,6 +474,7 @@ Please supply a username for the admin u return options + if __name__ == '__main__': options = handle_options() bsetup = BloodhoundSetup(options)
Propchange: bloodhound/branches/bep_0007_embeddable_objects/trac/ ------------------------------------------------------------------------------ Merged /bloodhound/trunk/trac:r1572403-1604056 Modified: bloodhound/branches/bep_0007_embeddable_objects/trac/trac/db/postgres_backend.py URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/trac/trac/db/postgres_backend.py?rev=1604057&r1=1604056&r2=1604057&view=diff ============================================================================== --- bloodhound/branches/bep_0007_embeddable_objects/trac/trac/db/postgres_backend.py (original) +++ bloodhound/branches/bep_0007_embeddable_objects/trac/trac/db/postgres_backend.py Fri Jun 20 00:34:19 2014 @@ -255,8 +255,8 @@ class PostgreSQLConnection(ConnectionWra def update_sequence(self, cursor, table, column='id'): cursor.execute(""" - SELECT setval('"%s_%s_seq"', (SELECT MAX(id) FROM %s)) - """ % (table, column, table)) + SELECT setval('"%s_%s_seq"', (SELECT MAX(%s) FROM %s)) + """ % (table, column, column, table)) def cursor(self): return IterableCursor(self.cnx.cursor(), self.log) Modified: bloodhound/branches/bep_0007_embeddable_objects/trac/trac/hooks.py URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/trac/trac/hooks.py?rev=1604057&r1=1604056&r2=1604057&view=diff ============================================================================== --- bloodhound/branches/bep_0007_embeddable_objects/trac/trac/hooks.py (original) +++ bloodhound/branches/bep_0007_embeddable_objects/trac/trac/hooks.py Fri Jun 20 00:34:19 2014 @@ -15,37 +15,41 @@ # specific language governing permissions and limitations # under the License. -import os import imp import inspect - +import os import pkg_resources from trac.config import Configuration from trac.env import open_environment +from trac.util import exception_to_unicode from trac.util.concurrency import threading from trac.web.api import RequestDone from trac.web.href import Href from trac.web.main import RequestWithSession - __all__ = ['environment_factory', 'install_global_hooks'] + class EnvironmentFactoryBase(object): def open_environment(self, environ, env_path, global_env, use_cache=False): raise NotImplementedError("Must override method 'open_environment'") + class RequestFactoryBase(object): def create_request(self, env, environ, start_response): raise NotImplementedError("Must override method 'create_request'") + def _get_plugins_dir(env_path): return os.path.normcase(os.path.realpath(os.path.join(env_path, 'plugins'))) + def _get_config(env_path): return Configuration(os.path.join(env_path, 'conf', 'trac.ini'), {'envname': os.path.basename(env_path)}) + def _hook_load(env_path, hook_path): hook_name = os.path.basename(hook_path[:-3]) plugins_dir = _get_plugins_dir(env_path) @@ -53,6 +57,7 @@ def _hook_load(env_path, hook_path): module = imp.load_source(hook_name, load_path) return module + def _get_hook_class(env_path, hook_path, class_type): module = _hook_load(env_path, hook_path) for (name, cls) in inspect.getmembers(module, inspect.isclass): @@ -64,6 +69,7 @@ def _get_hook_class(env_path, hook_path, _global_hooks_installed = False _global_hooks_lock = threading.Lock() + def install_global_hooks(): global _global_hooks_installed, _global_hooks_lock if _global_hooks_installed: @@ -72,7 +78,8 @@ def install_global_hooks(): try: if not _global_hooks_installed: try: - # TODO: this is currently hardcoded, maybe it could be made configurable in the future + # TODO: this is currently hardcoded, maybe it could be made + # configurable in the future import multiproduct.hooks except: pass @@ -81,13 +88,18 @@ def install_global_hooks(): _global_hooks_lock.release() return + def environment_factory(env): hook_path = env.config.get('trac', 'environment_factory', default=None) - return _get_hook_class(env.path, hook_path, EnvironmentFactoryBase) if hook_path else None + return _get_hook_class(env.path, hook_path, EnvironmentFactoryBase) \ + if hook_path else None + def request_factory(env): hook_path = env.config.get('trac', 'request_factory', default=None) - return _get_hook_class(env.path, hook_path, RequestFactoryBase) if hook_path else None + return _get_hook_class(env.path, hook_path, RequestFactoryBase) \ + if hook_path else None + class BootstrapHandlerBase(object): """Objects responsible for loading the target environment and @@ -137,8 +149,8 @@ class BootstrapHandlerBase(object): resulting environment object. This approach is generic but not efficient. Should be overridden whenever possible. """ - # If the expected configuration keys aren't found in the WSGI environment, - # try looking them up in the process environment variables + # 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')) @@ -206,8 +218,8 @@ class DefaultBootstrapHandler(BootstrapH env_name = path_info.pop(0) if not env_name: - # No specific environment requested, so render an environment - # index page + # No specific environment requested, so render an + # environment index page send_project_index(environ, start_response, env_parent_dir, env_paths) raise RequestDone @@ -215,9 +227,10 @@ class DefaultBootstrapHandler(BootstrapH environ['trac.env_name'] = env_name 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. + # 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') @@ -237,26 +250,31 @@ class DefaultBootstrapHandler(BootstrapH if errmsg: write = start_response('404 Not Found', - [('Content-Type', 'text/plain'), - ('Content-Length', str(len(errmsg)))]) + [('Content-Type', 'text/plain'), + ('Content-Length', + str(len(errmsg)))]) write(errmsg) raise RequestDone 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).') + '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 = None self.global_env = global_env = None try: - self.global_env = global_env = open_environment(env_path, use_cache=not run_once) + self.global_env = global_env = \ + open_environment(env_path, use_cache=not run_once) factory = environment_factory(global_env) - factory_env = factory().open_environment(environ, env_path, global_env, use_cache=not run_once) if factory \ - else None + factory_env = \ + factory().open_environment(environ, env_path, global_env, + use_cache=not run_once) \ + if factory else None env = factory_env if factory_env else global_env except Exception: raise @@ -268,11 +286,12 @@ class DefaultBootstrapHandler(BootstrapH factory = request_factory(self.global_env) except Exception: pass - return factory().create_request(env, environ, start_response) if factory \ - else RequestWithSession(environ, start_response) + return factory().create_request(env, environ, start_response) \ + if factory else RequestWithSession(environ, start_response) default_bootstrap_handler = DefaultBootstrapHandler() + def load_bootstrap_handler(bootstrap_ep, log=None): """Load handler for environment lookup and instantiation of request objects Modified: bloodhound/branches/bep_0007_embeddable_objects/trac/trac/resource.py URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/trac/trac/resource.py?rev=1604057&r1=1604056&r2=1604057&view=diff ============================================================================== --- bloodhound/branches/bep_0007_embeddable_objects/trac/trac/resource.py (original) +++ bloodhound/branches/bep_0007_embeddable_objects/trac/trac/resource.py Fri Jun 20 00:34:19 2014 @@ -518,7 +518,7 @@ class ResourceSystem(Component): """Return a list of all the realm names of neighborhoods.""" realms = [] for connector in self.resource_connectors: - for realm in manager.get_supported_neighborhoods() or []: + for realm in connector.get_supported_neighborhoods() or []: realms.append(realm) return realms Modified: bloodhound/branches/bep_0007_embeddable_objects/trac/trac/web/main.py URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/trac/trac/web/main.py?rev=1604057&r1=1604056&r2=1604057&view=diff ============================================================================== --- bloodhound/branches/bep_0007_embeddable_objects/trac/trac/web/main.py (original) +++ bloodhound/branches/bep_0007_embeddable_objects/trac/trac/web/main.py Fri Jun 20 00:34:19 2014 @@ -383,8 +383,8 @@ def dispatch_request(environ, start_resp # Load handler for environment lookup and instantiation of request objects from trac.hooks import load_bootstrap_handler - bootstrap = load_bootstrap_handler(environ['trac.bootstrap_handler'], - environ.get('wsgi.errors')) + bootstrap_ep = environ['trac.bootstrap_handler'] + bootstrap = load_bootstrap_handler(bootstrap_ep, environ.get('wsgi.errors')) # Determine the environment @@ -432,7 +432,7 @@ def dispatch_request(environ, start_resp try: req = bootstrap.create_request(env, environ, start_response) \ if env is not None else Request(environ, start_response) - except Exception: + except Exception, e: log = environ.get('wsgi.errors') if log: log.write("[FAIL] [Trac] Entry point '%s' "