class InMemoryEnvironment(Environment): def get_db_cnx(self): if not hasattr(self, '_db'): self._db = InMemoryDatabase() return self._db def create(self, db_str=None): self.load_config() def verify(self): return True def setup_log(self): from trac.log import logger_factory self.log = logger_factory('null') def is_component_enabled(self, cls): return cls.__module__.startswith('trac.') and \ cls.__module__.find('.tests.') == -1 def load_config(self): self.config = Configuration(None) for section, name, value in default_config: self.config.setdefault(section, name, value) def save_config(self): pass
def getSettings(self, cls, store): if not isinstance(cls, basestring): mymodule = cls.__module__.lower() else: mymodule = cls.lower() # Do not add duplicates for object in store: if mymodule in object['module']: return mycount = len(mymodule.split('.')) prjconf = Configuration(conf.global_conf_path) rules = [(name.lower(), value.lower()) for name, value in prjconf.options('components')] rules.sort(lambda a, b:-cmp(len(a[0]), len(b[0]))) for pattern, value in rules: if pattern.startswith(mymodule + '.'): item = pattern.split(".") count = len(item) if count > mycount: header = item[mycount] if count > (mycount + 1): store.append({ 'module': mymodule, 'name': header + '.' + item[mycount + 1], 'default': self.parse_value(0, value), 'static': self.parse_boolean_value(1, value, True) })
def create(self): """Create a new test environment. This sets up Trac, calls :meth:`create_repo` and sets up authentication. """ os.mkdir(self.dirname) # testing.log gets any unused output from subprocesses self.logfile = open(os.path.join(self.dirname, 'testing.log'), 'w') self.create_repo() config_file = os.path.join(self.dirname, 'config.ini') config = Configuration(config_file) repo_path = self.repo_path_for_initenv() if repo_path: config.set('repositories', '.dir', repo_path) config.set('repositories', '.type', self.repotype) for component in self.get_enabled_components(): config.set('components', component, 'enabled') config.save() self._tracadmin('initenv', self.tracdir, self.dburi, '--config=%s' % config_file) if call([sys.executable, os.path.join(self.trac_src, 'contrib', 'htpasswd.py'), "-c", "-b", self.htpasswd, "admin", "admin"], close_fds=close_fds, cwd=self.command_cwd): raise Exception('Unable to setup admin password') self.adduser('user') self.adduser('joe') self.grant_perm('admin', 'TRAC_ADMIN') env = self.get_trac_environment() self.post_create(env)
def __init__(self, default_data=False, enable=None): ComponentManager.__init__(self) self.enabled_components = enable self.db = InMemoryDatabase() from trac.config import Configuration self.config = Configuration(None) from trac.log import logger_factory self.log = logger_factory('test') from trac.web.href import Href self.href = Href('/trac.cgi') self.abs_href = Href('http://example.org/trac.cgi') from trac import db_default for section, name, value in db_default.default_config: self.config.set(section, name, value) if default_data: cursor = self.db.cursor() for table, cols, vals in db_default.data: cursor.executemany( "INSERT INTO %s (%s) VALUES (%s)" % (table, ','.join(cols), ','.join(['%s' for c in cols])), vals) self.db.commit()
def cli_command(self, project, args): """Manipulate the trac environment for a project Supported arguments: - create: creates an environment - sync: Synchronizes the configuration with Cydra's requirements - addrepo <type> <name> [tracname]: adds the repository to trac, identified by tracname - updatedefaults <file>: Adds trac's default options to config""" if len(args) < 1 or args[0] not in ['create', 'addrepo', 'sync', 'updatedefaults']: print self.cli_command.__doc__ return if args[0] == 'create': if self.has_env(project): print "Project already has a Trac environment!" return if self.create(project): print "Environment created" else: print "Creation failed!" elif args[0] == 'sync': self.sync(project) print project.name, "synced" elif args[0] == 'addrepo': if len(args) < 3: print self.cli_command.__doc__ return repository = project.get_repository(args[1], args[2]) if not repository: print "Unknown repository" return ret = False if len(args) == 4: ret = self.register_repository(repository, args[3]) else: ret = self.register_repository(repository) if ret: print "Successfully added repository" else: print "Adding repository failed!" elif args[0] == 'updatedefaults': if len(args) < 2: print self.cli_command.__doc__ return config = Configuration(args[1]) # load defaults config.set_defaults() config.save()
def load_workflow_config_snippet(config, filename): """Loads the ticket-workflow section from the given file (expected to be in the 'workflows' tree) into the provided config. """ filename = resource_filename('trac.ticket', 'workflows/%s' % filename) new_config = Configuration(filename) for name, value in new_config.options('ticket-workflow'): config.set('ticket-workflow', name, value)
def test_sections(self): configfile = open(self.filename, 'w') configfile.writelines( ['[a]\n', 'option = x\n', '[b]\n', 'option = y\n']) configfile.close() config = Configuration(self.filename) self.assertEquals(['a', 'b'], config.sections())
def test_read_and_get(self): configfile = open(self.filename, 'w') configfile.writelines(['[a]\n', 'option = x\n', '\n']) configfile.close() config = Configuration(self.filename) self.assertEquals('x', config.get('a', 'option')) self.assertEquals('x', config.get('a', 'option', 'y'))
class SvnServePasswordStore(Component): """PasswordStore implementation for reading svnserve's password file format """ implements(IPasswordStore) filename = EnvRelativePathOption('account-manager', 'password_file', doc="""Path to the users file; leave blank to locate the users file by reading svnserve.conf from the default repository. """) _userconf = None @property def _config(self): filename = self.filename or self._get_password_file() if self._userconf is None or filename != self._userconf.filename: self._userconf = Configuration(filename) # Overwrite default with str class to preserve case. self._userconf.parser.optionxform = str self._userconf.parse_if_needed(force=True) else: self._userconf.parse_if_needed() return self._userconf def _get_password_file(self): repos = RepositoryManager(self.env).get_repository('') if not repos: return None if isinstance(repos, CachedRepository): repos = repos.repos if repos.params['type'] in ('svn', 'svnfs', 'direct-svnfs'): conf = Configuration(os.path.join(repos.path, 'conf', 'svnserve.conf')) return conf['general'].getpath('password-db') # IPasswordStore methods def get_users(self): return [user for (user, password) in self._config.options('users')] def has_user(self, user): return user in self._config['users'] def set_password(self, user, password, old_password=None): cfg = self._config cfg.set('users', user, password) cfg.save() def check_password(self, user, password): if self.has_user(user): return password == self._config.get('users', user) return None def delete_user(self, user): cfg = self._config cfg.remove('users', user) cfg.save()
def _config(self): filename = self.filename if not filename: self._svnserve_conf.parse_if_needed() filename = self._svnserve_conf['general'].getpath('password-db') if self._userconf is None or filename != self._userconf.filename: self._userconf = Configuration(filename) else: self._userconf.parse_if_needed() return self._userconf
def readconfig(filename): """Returns a list of raw config options""" config = Configuration(filename) rawactions = list(config.options('ticket-workflow')) debug("%s\n" % str(rawactions)) if not rawactions: sys.stderr.write("ERROR: You don't seem to have a [ticket-workflow] " "section.\n") sys.exit(1) return rawactions
def set_home_config(self, values): syspath = self.conf.getEnvironmentSysPath("home") setconf = Configuration(syspath + '/conf/trac.ini') try: for (main, sub, value) in values: setconf.set(main, sub, value) setconf.save() except: return False return True
def _config(self): filename = self.filename or self._get_password_file() if self._userconf is None or filename != self._userconf.filename: self._userconf = Configuration(filename) # Overwrite default with str class to preserve case. self._userconf.parser.optionxform = str self._userconf.parse_if_needed(force=True) else: self._userconf.parse_if_needed() return self._userconf
def test_options(self): configfile = open(self.filename, 'w') configfile.writelines( ['[a]\n', 'option = x\n', '[b]\n', 'option = y\n']) configfile.close() config = Configuration(self.filename) self.assertEquals(('option', 'x'), iter(config.options('a')).next()) self.assertEquals(('option', 'y'), iter(config.options('b')).next()) self.assertRaises(StopIteration, iter(config.options('c')).next)
class SvnServePasswordStore(Component): """PasswordStore implementation for reading svnserve's password file format """ implements(IPasswordStore) filename = EnvRelativePathOption( 'account-manager', 'password_file', doc=N_("""Path to the users file; leave blank to locate the users file by reading svnserve.conf""")) def __init__(self): repo_dir = RepositoryManager(self.env).repository_dir self._svnserve_conf = Configuration( os.path.join(os.path.join(repo_dir, 'conf'), 'svnserve.conf')) self._userconf = None def _config(self): filename = self.filename if not filename: self._svnserve_conf.parse_if_needed() filename = self._svnserve_conf['general'].getpath('password-db') if self._userconf is None or filename != self._userconf.filename: self._userconf = Configuration(filename) else: self._userconf.parse_if_needed() return self._userconf _config = property(_config) # IPasswordStore methods def get_users(self): return [user for (user, password) in self._config.options('users')] def has_user(self, user): return user in self._config['users'] def set_password(self, user, password, old_password=None): cfg = self._config cfg.set('users', user, password) cfg.save() def check_password(self, user, password): if self.has_user(user): return password == self._config.get('users', user) return None def delete_user(self, user): cfg = self._config cfg.remove('users', user) cfg.save()
def _config(self): filename = self.filename if not filename: self._svnserve_conf.parse_if_needed() filename = self._svnserve_conf['general'].getpath('password-db') if self._userconf is None or filename != self._userconf.filename: self._userconf = Configuration(filename) # Overwrite default with str class to preserve case. self._userconf.parser.optionxform = str self._userconf.parse_if_needed(force=True) else: self._userconf.parse_if_needed() return self._userconf
class SvnServePasswordStore(Component): """PasswordStore implementation for reading svnserve's password file format """ implements(IPasswordStore) filename = EnvRelativePathOption('account-manager', 'password_file', doc = N_("""Path to the users file; leave blank to locate the users file by reading svnserve.conf""")) def __init__(self): repo_dir = RepositoryManager(self.env).repository_dir self._svnserve_conf = Configuration(os.path.join(os.path.join( repo_dir, 'conf'), 'svnserve.conf')) self._userconf = None def _config(self): filename = self.filename if not filename: self._svnserve_conf.parse_if_needed() filename = self._svnserve_conf['general'].getpath('password-db') if self._userconf is None or filename != self._userconf.filename: self._userconf = Configuration(filename) else: self._userconf.parse_if_needed() return self._userconf _config = property(_config) # IPasswordStore methods def get_users(self): return [user for (user,password) in self._config.options('users')] def has_user(self, user): return user in self._config['users'] def set_password(self, user, password, old_password = None): cfg = self._config cfg.set('users', user, password) cfg.save() def check_password(self, user, password): if self.has_user(user): return password == self._config.get('users', user) return None def delete_user(self, user): cfg = self._config cfg.remove('users', user) cfg.save()
def _update_sample_config(self): filename = os.path.join(self.env.config_file_path + ".sample") if not os.path.isfile(filename): return config = Configuration(filename) for (section, name), option in Option.get_registry().iteritems(): config.set(section, name, option.dumps(option.default)) try: config.save() self.log.info( "Wrote sample configuration file with the new " "settings and their default values: %s", filename ) except IOError as e: self.log.warn("Couldn't write sample configuration file (%s)", e, exc_info=True)
def __init__(self, default_data=False, enable=None): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. """ ComponentManager.__init__(self) Component.__init__(self) self.systeminfo = [] import trac self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') if enable is not None: self.config.set('components', 'trac.*', 'disabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'enabled') # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory('test') # -- database self.dburi = get_dburi() if self.dburi.startswith('sqlite'): self.config.set('trac', 'database', 'sqlite::memory:') self.db = InMemoryDatabase() if default_data: self.reset_db(default_data) from trac.web.href import Href self.href = Href('/trac.cgi') self.abs_href = Href('http://example.org/trac.cgi') self.known_users = [] translation.activate(Locale and Locale('en', 'US'))
def setup_config(self): """Load the configuration file.""" self.config = Configuration(self.config_file_path, {'envname': os.path.basename(self.path)}) self.setup_log() plugins_dir = self.shared_plugins_dir load_components(self, plugins_dir and (plugins_dir,))
def __init__(self): ComponentManager.__init__(self) self.log = logger_factory('null') self.config = Configuration(None) self.href = Href('/') self.abs_href = Href('http://www.example.com/') self._wiki_pages = {} self.path = ''
def __init__(self, enable=[]): ComponentManager.__init__(self) from trac.config import Configuration from trac.log import logger_factory self.config = Configuration(None) self.log = logger_factory('test') self.href = Href('/trac.cgi') self.enabled_components = enable
def test_default(self): config = Configuration(self.filename) self.assertEquals('', config.get('a', 'option')) self.assertEquals('value', config.get('a', 'option', 'value')) config.setdefault('a', 'option', 'value') self.assertEquals('value', config.get('a', 'option'))
def setup_config(self): """Load the configuration file.""" self.config = Configuration(os.path.join(self.path, 'conf', 'trac.ini'), {'envname': os.path.basename(self.path)}) self.setup_log() from trac.loader import load_components plugins_dir = self.shared_plugins_dir load_components(self, plugins_dir and (plugins_dir,))
def post_process_request(self, req, template, content_type): global_scripts = Configuration.getlist(self.config, 'flexjs', 'global') for script in global_scripts: add_script(req, 'common/js/flex/'+script) ext_scripts = Configuration.getlist(self.config, 'flexjs', 'ext') idx = 0 js = req.hdf.get('chrome.scripts.%i.href' % idx) idx = len(js) for script in ext_scripts: req.hdf['chrome.scripts.%i' % idx] = {'href': script, 'type': 'text/javascript'} idx += 1 local_scripts = Configuration.getlist(self.config, 'flexjs', 'local') for script in local_scripts: add_script(req, 'site/js/'+script) return (template, content_type)
def setup_config(self): """Load the configuration file.""" self.config = Configuration(self.config_file_path, {'envname': self.name}) if not self.config.exists: raise TracError(_("The configuration file is not found at " "%(path)s", path=self.config_file_path)) self.setup_log() plugins_dir = self.shared_plugins_dir load_components(self, plugins_dir and (plugins_dir,))
def _get_password_file(self): repos = RepositoryManager(self.env).get_repository('') if not repos: return None if isinstance(repos, CachedRepository): repos = repos.repos if repos.params['type'] in ('svn', 'svnfs', 'direct-svnfs'): conf = Configuration(os.path.join(repos.path, 'conf', 'svnserve.conf')) return conf['general'].getpath('password-db')
class EnvironmentStub(ComponentManager): """A stub of the trac.env.Environment object for testing.""" def __init__(self, default_data=False, enable=None): ComponentManager.__init__(self) self.enabled_components = enable self.db = InMemoryDatabase() from trac.config import Configuration self.config = Configuration(None) from trac.log import logger_factory self.log = logger_factory('test') from trac.web.href import Href self.href = Href('/trac.cgi') self.abs_href = Href('http://example.org/trac.cgi') from trac import db_default for section, name, value in db_default.default_config: self.config.set(section, name, value) if default_data: cursor = self.db.cursor() for table, cols, vals in db_default.data: cursor.executemany( "INSERT INTO %s (%s) VALUES (%s)" % (table, ','.join(cols), ','.join(['%s' for c in cols])), vals) self.db.commit() def component_activated(self, component): component.env = self component.config = self.config component.log = self.log def is_component_enabled(self, cls): if self.enabled_components is None: return True return cls in self.enabled_components def get_db_cnx(self): return self.db
def post_process_request(self, req, template, content_type): global_scripts = Configuration.getlist(self.config, 'flexjs', 'global') for script in global_scripts: add_script(req, 'common/js/flex/' + script) ext_scripts = Configuration.getlist(self.config, 'flexjs', 'ext') idx = 0 js = req.hdf.get('chrome.scripts.%i.href' % idx) idx = len(js) for script in ext_scripts: req.hdf['chrome.scripts.%i' % idx] = { 'href': script, 'type': 'text/javascript' } idx += 1 local_scripts = Configuration.getlist(self.config, 'flexjs', 'local') for script in local_scripts: add_script(req, 'site/js/' + script) return (template, content_type)
def diff(file1, file2, ignored_sections=None, ignore_absent=False): """ :param file1: Filename :param file2: Filename :param list ignored_sections: List of ignored sections :param bool ignore_absent: Disables absent key reporting """ if ignored_sections is None: ignored_sections = [] if not os.path.exists(file1): raise ValueError('file %s does not exists' % file1) if not os.path.exists(file2): raise ValueError('file %s does not exists' % file2) conf1 = Configuration(file1) conf2 = Configuration(file2) fn1 = os.path.split(file1)[1] fn2 = os.path.split(file2)[1] conf1_sections = set(conf1.sections()) - set(ignored_sections) conf2_sections = set(conf2.sections()) - set(ignored_sections) for section in conf1.sections(): if section not in conf2_sections: print 'SECTION: %s not in %s' % (section, fn2) default = object() for section in conf1_sections: for key, value1 in conf1.options(section): if not conf2.has_option(section, key): if not ignore_absent: print '[%s] %s = %s is ABSENT from %s (but exists in %s)' % ( section, key, value1, fn2, fn1) else: value2 = conf2.get(section, key, default) if value2 != value1 and value2 is not default: print '[%s] %s = %s -> %s (%s -> %s)' % ( section, key, value1, value2, fn1, fn2)
def create(self, options=[], default_data=True): """Create the basic directory structure of the environment, initialize the database and populate the configuration file with default values. If options contains ('inherit', 'file'), default values will not be loaded; they are expected to be provided by that file or other options. :raises TracError: if the base directory of `path` does not exist. :raises TracError: if `path` exists and is not empty. """ base_dir = os.path.dirname(self.path) if not os.path.exists(base_dir): raise TracError( _( "Base directory '%(env)s' does not exist. Please create it " "and retry.", env=base_dir)) if os.path.exists(self.path) and os.listdir(self.path): raise TracError(_("Directory exists and is not empty.")) # Create the directory structure if not os.path.exists(self.path): os.mkdir(self.path) os.mkdir(self.htdocs_dir) os.mkdir(self.log_dir) os.mkdir(self.plugins_dir) os.mkdir(self.templates_dir) # Create a few files create_file(os.path.join(self.path, 'VERSION'), _VERSION + '\n') create_file( os.path.join(self.path, 'README'), 'This directory contains a Trac environment.\n' 'Visit https://trac.edgewall.org/ for more information.\n') # Setup the default configuration os.mkdir(self.conf_dir) config = Configuration(self.config_file_path) for section, name, value in options: config.set(section, name, value) config.save() self.setup_config() if not any((section, option) == ('inherit', 'file') for section, option, value in options): self.config.set_defaults(self) self.config.save() # Create the sample configuration create_file(self.config_file_path + '.sample') self._update_sample_config() # Create the database dbm = DatabaseManager(self) dbm.init_db() if default_data: dbm.insert_default_data()
def create(self, options=[]): """Create the basic directory structure of the environment, initialize the database and populate the configuration file with default values. If options contains ('inherit', 'file'), default values will not be loaded; they are expected to be provided by that file or other options. """ # Create the directory structure if not os.path.exists(self.path): os.mkdir(self.path) os.mkdir(self.get_log_dir()) os.mkdir(self.get_htdocs_dir()) os.mkdir(os.path.join(self.path, 'plugins')) # Create a few files create_file(os.path.join(self.path, 'VERSION'), _VERSION + '\n') create_file(os.path.join(self.path, 'README'), 'This directory contains a Trac environment.\n' 'Visit http://trac.edgewall.org/ for more information.\n') # Setup the default configuration os.mkdir(os.path.join(self.path, 'conf')) create_file(self.config_file_path + '.sample') config = Configuration(self.config_file_path) for section, name, value in options: config.set(section, name, value) config.save() self.setup_config() if not any((section, option) == ('inherit', 'file') for section, option, value in options): self.config.set_defaults(self) self.config.save() # Create the database DatabaseManager(self).init_db()
def test_set_and_save(self): configfile = open(self.filename, 'w') configfile.close() config = Configuration(self.filename) config.set('a', 'option', 'x') self.assertEquals('x', config.get('a', 'option')) config.save() configfile = open(self.filename, 'r') self.assertEquals(['[a]\n', 'option = x\n', '\n'], configfile.readlines()) configfile.close()
def getSettings(self, cls, store): if not isinstance(cls, basestring): mymodule = cls.__module__.lower() else: mymodule = cls.lower() # Do not add duplicates for object in store: if mymodule in object['module']: return mycount = len(mymodule.split('.')) prjconf = Configuration(conf.global_conf_path) rules = [(name.lower(), value.lower()) for name, value in prjconf.options('components')] rules.sort(lambda a, b: -cmp(len(a[0]), len(b[0]))) for pattern, value in rules: if pattern.startswith(mymodule + '.'): item = pattern.split(".") count = len(item) if count > mycount: header = item[mycount] if count > (mycount + 1): store.append({ 'module': mymodule, 'name': header + '.' + item[mycount + 1], 'default': self.parse_value(0, value), 'static': self.parse_boolean_value(1, value, True) })
def __init__(self, default_data=False, enable=None): """Construct a new Environment stub object. default_data: If True, populate the database with some defaults. enable: A list of component classes or name globs to activate in the stub environment. """ ComponentManager.__init__(self) Component.__init__(self) self.enabled_components = enable or ['trac.*'] self.systeminfo = [('Python', sys.version)] import trac self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') # -- logging from trac.log import logger_factory self.log = logger_factory('test') # -- database self.dburi = get_dburi() if self.dburi.startswith('sqlite'): self.db = InMemoryDatabase() if default_data: self.reset_db(default_data) from trac.web.href import Href self.href = Href('/trac.cgi') self.abs_href = Href('http://example.org/trac.cgi') self.known_users = []
def test_reparse(self): configfile = open(self.filename, 'w') configfile.writelines(['[a]\n', 'option = x\n', '\n']) configfile.close() config = Configuration(self.filename) self.assertEquals('x', config.get('a', 'option')) time.sleep(1) # needed because of low mtime granularity configfile = open(self.filename, 'w') configfile.write('[a]\noption = y') configfile.close() config.parse_if_needed() self.assertEquals('y', config.get('a', 'option'))
def _update_sample_config(self): filename = os.path.join(self.config_file_path + '.sample') if not os.path.isfile(filename): return config = Configuration(filename) config.set_defaults() try: config.save() except EnvironmentError as e: self.log.warning("Couldn't write sample configuration file (%s)%s", e, exception_to_unicode(e, traceback=True)) else: self.log.info( "Wrote sample configuration file with the new " "settings and their default values: %s", filename)
def diff(file1, file2, ignored_sections=None, ignore_absent=False): """ :param file1: Filename :param file2: Filename :param list ignored_sections: List of ignored sections :param bool ignore_absent: Disables absent key reporting """ if ignored_sections is None: ignored_sections = [] if not os.path.exists(file1): raise ValueError("file %s does not exists" % file1) if not os.path.exists(file2): raise ValueError("file %s does not exists" % file2) conf1 = Configuration(file1) conf2 = Configuration(file2) fn1 = os.path.split(file1)[1] fn2 = os.path.split(file2)[1] conf1_sections = set(conf1.sections()) - set(ignored_sections) conf2_sections = set(conf2.sections()) - set(ignored_sections) for section in conf1.sections(): if section not in conf2_sections: print "SECTION: %s not in %s" % (section, fn2) default = object() for section in conf1_sections: for key, value1 in conf1.options(section): if not conf2.has_option(section, key): if not ignore_absent: print "[%s] %s = %s is ABSENT from %s (but exists in %s)" % (section, key, value1, fn2, fn1) else: value2 = conf2.get(section, key, default) if value2 != value1 and value2 is not default: print "[%s] %s = %s -> %s (%s -> %s)" % (section, key, value1, value2, fn1, fn2)
def writeconfig(self, filepath, dicts=[]): """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. """ config = Configuration(filepath) file_changed = False for data in dicts: for section, options in data.iteritems(): for key, value in options.iteritems(): if config.get(section, key, None) != value: # This should be expected to generate a false positive # when two dictionaries update the same option file_changed = True config.set(section, key, value) if file_changed: if os.path.exists(filepath): backupfile(filepath) config.save()
def __init__(self, default_data=False, enable=None, disable=None, path=None, destroying=False): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. :param disable: A list of component classes or name globs to deactivate in the stub environment. :param path: The location of the environment in the file system. No files or directories are created when specifying this parameter. :param destroying: If True, the database will not be reset. This is useful for cases when the object is being constructed in order to call `destroy_db`. """ if enable is not None and not isinstance(enable, (list, tuple)): raise TypeError('Keyword argument "enable" must be a list') if disable is not None and not isinstance(disable, (list, tuple)): raise TypeError('Keyword argument "disable" must be a list') ComponentManager.__init__(self) self.systeminfo = [] import trac self.path = path if self.path is None: self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') if enable is not None: self.config.set('components', 'trac.*', 'disabled') else: self.config.set('components', 'tracopt.versioncontrol.*', 'enabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'enabled') for name_or_class in disable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'disabled') # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory('test') # -- database self.config.set('components', 'trac.db.*', 'enabled') self.dburi = get_dburi() init_global = False if self.global_databasemanager: self.components[DatabaseManager] = self.global_databasemanager else: self.config.set('trac', 'database', self.dburi) self.global_databasemanager = DatabaseManager(self) self.config.set('trac', 'debug_sql', True) init_global = not destroying if default_data or init_global: self.reset_db(default_data) self.config.set('trac', 'base_url', 'http://example.org/trac.cgi') self.known_users = [] translation.activate(locale_en)
class EnvironmentStub(Environment): """A stub of the trac.env.Environment object for testing.""" global_databasemanager = None required = False def __init__(self, default_data=False, enable=None, disable=None, path=None, destroying=False): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. :param disable: A list of component classes or name globs to deactivate in the stub environment. :param path: The location of the environment in the file system. No files or directories are created when specifying this parameter. :param destroying: If True, the database will not be reset. This is useful for cases when the object is being constructed in order to call `destroy_db`. """ if enable is not None and not isinstance(enable, (list, tuple)): raise TypeError('Keyword argument "enable" must be a list') if disable is not None and not isinstance(disable, (list, tuple)): raise TypeError('Keyword argument "disable" must be a list') ComponentManager.__init__(self) self.systeminfo = [] import trac self.path = path if self.path is None: self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') if enable is not None: self.config.set('components', 'trac.*', 'disabled') else: self.config.set('components', 'tracopt.versioncontrol.*', 'enabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'enabled') for name_or_class in disable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'disabled') # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory('test') # -- database self.config.set('components', 'trac.db.*', 'enabled') self.dburi = get_dburi() init_global = False if self.global_databasemanager: self.components[DatabaseManager] = self.global_databasemanager else: self.config.set('trac', 'database', self.dburi) self.global_databasemanager = DatabaseManager(self) self.config.set('trac', 'debug_sql', True) init_global = not destroying if default_data or init_global: self.reset_db(default_data) self.config.set('trac', 'base_url', 'http://example.org/trac.cgi') self.known_users = [] translation.activate(locale_en) def reset_db(self, default_data=None): """Remove all data from Trac tables, keeping the tables themselves. :param default_data: after clean-up, initialize with default data :return: True upon success """ from trac import db_default scheme, db_prop = _parse_db_str(self.dburi) tables = [] remove_sqlite_db = False try: with self.db_transaction as db: db.rollback() # make sure there's no transaction in progress # check the database version database_version = self.get_version() except Exception: # "Database not found ...", # "OperationalError: no such table: system" or the like pass else: if database_version == db_default.db_version: # same version, simply clear the tables (faster) m = sys.modules[__name__] reset_fn = 'reset_%s_db' % scheme if hasattr(m, reset_fn): tables = getattr(m, reset_fn)(self, db_prop) else: # different version or version unknown, drop the tables remove_sqlite_db = True self.destroy_db(scheme, db_prop) if scheme == 'sqlite' and remove_sqlite_db: path = db_prop['path'] if path != ':memory:': if not os.path.isabs(path): path = os.path.join(self.path, path) self.global_databasemanager.shutdown() os.remove(path) if not tables: self.global_databasemanager.init_db() # we need to make sure the next get_db_cnx() will re-create # a new connection aware of the new data model - see #8518. if self.dburi != 'sqlite::memory:': self.global_databasemanager.shutdown() with self.db_transaction as db: if default_data: for table, cols, vals in db_default.get_data(db): db.executemany("INSERT INTO %s (%s) VALUES (%s)" % (table, ','.join(cols), ','.join(['%s'] * len(cols))), vals) else: db("INSERT INTO system (name, value) VALUES (%s, %s)", ('database_version', str(db_default.db_version))) def destroy_db(self, scheme=None, db_prop=None): if not (scheme and db_prop): scheme, db_prop = _parse_db_str(self.dburi) try: with self.db_transaction as db: if scheme == 'postgres' and db.schema: db('DROP SCHEMA %s CASCADE' % db.quote(db.schema)) elif scheme == 'mysql': for table in db.get_table_names(): db("DROP TABLE IF EXISTS `%s`" % table) except Exception: # "TracError: Database not found...", # psycopg2.ProgrammingError: schema "tractest" does not exist pass return False # overridden def is_component_enabled(self, cls): if self._component_name(cls).startswith('__main__.'): return True return Environment.is_component_enabled(self, cls) def get_known_users(self, cnx=None): return self.known_users
def __init__(self): repo_dir = RepositoryManager(self.env).repository_dir self._svnserve_conf = Configuration(os.path.join(os.path.join( repo_dir, 'conf'), 'svnserve.conf')) self._userconf = None
class EnvironmentStub(Environment): """A stub of the trac.env.Environment object for testing.""" href = abs_href = None dbenv = db = None def __init__(self, default_data=False, enable=None): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. """ ComponentManager.__init__(self) Component.__init__(self) self.systeminfo = [] import trac self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') if enable is not None: self.config.set('components', 'trac.*', 'disabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'enabled') # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory('test') # -- database self.dburi = get_dburi() if self.dburi.startswith('sqlite'): self.config.set('trac', 'database', 'sqlite::memory:') self.db = InMemoryDatabase() if default_data: self.reset_db(default_data) from trac.web.href import Href self.href = Href('/trac.cgi') self.abs_href = Href('http://example.org/trac.cgi') self.known_users = [] translation.activate(Locale and Locale('en', 'US')) def get_read_db(self): return self.get_db_cnx() def get_db_cnx(self, destroying=False): if self.db: return self.db # in-memory SQLite # As most of the EnvironmentStubs are built at startup during # the test suite formation and the creation of test cases, we can't # afford to create a real db connection for each instance. # So we create a special EnvironmentStub instance in charge of # getting the db connections for all the other instances. dbenv = EnvironmentStub.dbenv if not dbenv: dbenv = EnvironmentStub.dbenv = EnvironmentStub() dbenv.config.set('trac', 'database', self.dburi) if not destroying: self.reset_db() # make sure we get rid of previous garbage return DatabaseManager(dbenv).get_connection() def reset_db(self, default_data=None): """Remove all data from Trac tables, keeping the tables themselves. :param default_data: after clean-up, initialize with default data :return: True upon success """ from trac import db_default if EnvironmentStub.dbenv: db = self.get_db_cnx() scheme, db_prop = _parse_db_str(self.dburi) tables = [] db.rollback() # make sure there's no transaction in progress try: # check the database version cursor = db.cursor() cursor.execute("SELECT value FROM system " "WHERE name='database_version'") database_version = cursor.fetchone() if database_version: database_version = int(database_version[0]) if database_version == db_default.db_version: # same version, simply clear the tables (faster) m = sys.modules[__name__] reset_fn = 'reset_%s_db' % scheme if hasattr(m, reset_fn): tables = getattr(m, reset_fn)(db, db_prop) else: # different version or version unknown, drop the tables self.destroy_db(scheme, db_prop) except: db.rollback() # tables are likely missing if not tables: del db dm = DatabaseManager(EnvironmentStub.dbenv) dm.init_db() # we need to make sure the next get_db_cnx() will re-create # a new connection aware of the new data model - see #8518. dm.shutdown() db = self.get_db_cnx() cursor = db.cursor() if default_data: for table, cols, vals in db_default.get_data(db): cursor.executemany("INSERT INTO %s (%s) VALUES (%s)" % (table, ','.join(cols), ','.join(['%s' for c in cols])), vals) elif EnvironmentStub.dbenv: cursor.execute("INSERT INTO system (name, value) " "VALUES (%s, %s)", ('database_version', str(db_default.db_version))) db.commit() def destroy_db(self, scheme=None, db_prop=None): if not (scheme and db_prop): scheme, db_prop = _parse_db_str(self.dburi) db = self.get_db_cnx(destroying=True) cursor = db.cursor() try: if scheme == 'postgres' and db.schema: cursor.execute('DROP SCHEMA "%s" CASCADE' % db.schema) elif scheme == 'mysql': dbname = os.path.basename(db_prop['path']) cursor = db.cursor() cursor.execute('SELECT table_name FROM ' ' information_schema.tables ' 'WHERE table_schema=%s', (dbname,)) tables = cursor.fetchall() for t in tables: cursor.execute('DROP TABLE IF EXISTS `%s`' % t) db.commit() except Exception: db.rollback() # overriden def is_component_enabled(self, cls): if self._component_name(cls).startswith('__main__.'): return True return Environment.is_component_enabled(self, cls) def get_known_users(self, cnx=None): return self.known_users
class EnvironmentStub(Environment): """A stub of the trac.env.Environment class for testing.""" global_databasemanager = None required = False abstract = True def __init__(self, default_data=False, enable=None, disable=None, path=None, destroying=False): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. :param disable: A list of component classes or name globs to deactivate in the stub environment. :param path: The location of the environment in the file system. No files or directories are created when specifying this parameter. :param destroying: If True, the database will not be reset. This is useful for cases when the object is being constructed in order to call `destroy_db`. """ if enable is not None and not isinstance(enable, (list, tuple)): raise TypeError('Keyword argument "enable" must be a list') if disable is not None and not isinstance(disable, (list, tuple)): raise TypeError('Keyword argument "disable" must be a list') ComponentManager.__init__(self) self.systeminfo = [] import trac self.path = path if self.path is None: self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') if enable is not None: self.config.set('components', 'trac.*', 'disabled') else: self.config.set('components', 'tracopt.versioncontrol.*', 'enabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'enabled') for name_or_class in disable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'disabled') # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory('test') # -- database self.config.set('components', 'trac.db.*', 'enabled') self.dburi = get_dburi() init_global = False if self.global_databasemanager: self.components[DatabaseManager] = self.global_databasemanager else: self.config.set('trac', 'database', self.dburi) self.global_databasemanager = DatabaseManager(self) self.config.set('trac', 'debug_sql', True) init_global = not destroying if default_data or init_global: self.reset_db(default_data) self.config.set('trac', 'base_url', 'http://example.org/trac.cgi') translation.activate(locale_en) def reset_db(self, default_data=None): """Remove all data from Trac tables, keeping the tables themselves. :param default_data: after clean-up, initialize with default data :return: True upon success """ from trac import db_default tables = [] dbm = self.global_databasemanager try: with self.db_transaction as db: db.rollback() # make sure there's no transaction in progress # check the database version db_version = dbm.get_database_version() except (TracError, self.env.db_exc.DatabaseError): pass else: if db_version == db_default.db_version: # same version, simply clear the tables (faster) tables = dbm.reset_tables() else: # different version or version unknown, drop the tables self.destroy_db() if not tables: dbm.init_db() # we need to make sure the next get_db_cnx() will re-create # a new connection aware of the new data model - see #8518. if self.dburi != 'sqlite::memory:': dbm.shutdown() if default_data: dbm.insert_into_tables(db_default.get_data) else: dbm.set_database_version(db_default.db_version) def destroy_db(self, scheme=None, db_prop=None): """Destroy the database. :since 1.1.5: the `scheme` and `db_prop` parameters are deprecated and will be removed in 1.3.1. """ try: self.global_databasemanager.destroy_db() except (TracError, self.db_exc.DatabaseError): pass return False def insert_known_users(self, users): with self.env.db_transaction as db: for username, name, email in users: db("INSERT INTO session VALUES (%s, %s, %s)", (username, 1, int(time.time()))) db("INSERT INTO session_attribute VALUES (%s,%s,'name',%s)", (username, 1, name)) db("INSERT INTO session_attribute VALUES (%s,%s,'email',%s)", (username, 1, email)) # overridden def is_component_enabled(self, cls): if self._component_name(cls).startswith('__main__.'): return True return Environment.is_component_enabled(self, cls)
def __init__(self, default_data=False, enable=None, disable=None, path=None, destroying=False): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. """ ComponentManager.__init__(self) Component.__init__(self) self.systeminfo = [] import trac self.path = path if self.path is None: self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, "basic-workflow.ini") self.config.set("logging", "log_level", "DEBUG") self.config.set("logging", "log_type", "stderr") if enable is not None: self.config.set("components", "trac.*", "disabled") else: self.config.set("components", "tracopt.versioncontrol.*", "enabled") for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set("components", config_key, "enabled") for name_or_class in disable or (): config_key = self._component_name(name_or_class) self.config.set("components", config_key, "disabled") # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory("test") # -- database self.config.set("components", "trac.db.*", "enabled") self.dburi = get_dburi() init_global = False if self.global_databasemanager: self.components[DatabaseManager] = global_databasemanager else: self.config.set("trac", "database", self.dburi) self.global_databasemanager = DatabaseManager(self) self.config.set("trac", "debug_sql", True) self.config.set("logging", "log_type", "stderr") self.config.set("logging", "log_level", "DEBUG") init_global = not destroying if default_data or init_global: self.reset_db(default_data) from trac.web.href import Href self.href = Href("/trac.cgi") self.abs_href = Href("http://example.org/trac.cgi") self.known_users = [] translation.activate(locale_en)
def do(self): # Make backup of trac.ini before configuring it try: shutil.copy(self.conf_file, self.conf_file_back) except Exception: conf.log.exception("Could not create trac.ini backup") return False # Open trac.ini for configuration config = None try: config = Configuration(self.conf_file) except Exception: conf.log.exception("Error while reading config file!") return False # Enable correct plugin for repository try: vcs_plugin = self.__vcs_plugin() if vcs_plugin: config.set('components', vcs_plugin, 'enabled') config.set('trac', 'repository_type', self.vcs_type) except Exception: conf.log.exception("Could not set static settings for trac") return False try: config.set('project', 'descr', self.project.description) except Exception: conf.log.exception("Couldn't set description") return False # Remove attachment size (to enable global setting) try: config.remove("attachment", "max_size") except Exception: conf.log.exception("Could not remove attachment config property for a new project") # Save configuration try: config.save() except Exception: conf.log.exception("Failed to save configuration") return False self.success = True return True
def do_initenv(self, line): def initenv_error(msg): printerr(_("Initenv for '%(env)s' failed.", env=self.envname), "\n%s" % msg) if self.env_check(): initenv_error(_("Does an environment already exist?")) return 2 if os.path.exists(self.envname) and os.listdir(self.envname): initenv_error(_("Directory exists and is not empty.")) return 2 if not os.path.exists(os.path.dirname(self.envname)): initenv_error(_("Base directory '%(env)s' does not exist. Please " "create it manually and retry.", env=os.path.dirname(self.envname))) return 2 arg = self.arg_tokenize(line) inherit_paths = [] config_file_path = None i = 0 while i < len(arg): item = arg[i] if item.startswith('--inherit='): inherit_paths.append(arg.pop(i)[10:]) elif item.startswith('--config='): config_file_path = arg.pop(i)[9:] else: i += 1 config = None if config_file_path: if not os.path.exists(config_file_path): initenv_error(_("The file specified in the --config argument " "does not exist: %(path)s.", path=config_file_path)) return 2 try: config = Configuration(config_file_path) except TracError as e: initenv_error(e) return 2 arg = arg or [''] # Reset to usual empty in case we popped the only one project_name = None db_str = None repository_type = None repository_dir = None if len(arg) == 1 and not arg[0]: project_name, db_str = self.get_initenv_args() elif len(arg) == 2: project_name, db_str = arg elif len(arg) == 4: project_name, db_str, repository_type, repository_dir = arg else: initenv_error('Wrong number of arguments: %d' % len(arg)) return 2 try: printout(_("Creating and Initializing Project")) options = [] if config: for section in config.sections(defaults=False): options.extend((section, option, value) for option, value in config.options(section)) options.extend([ ('project', 'name', project_name), ('trac', 'database', db_str), ]) def add_nav_order_options(section, default): for i, name in enumerate(default, 1): options.append((section, name + '.order', float(i))) add_nav_order_options('mainnav', default_mainnav_order) add_nav_order_options('metanav', default_metanav_order) if repository_dir: options.extend([ ('repositories', '.type', repository_type), ('repositories', '.dir', repository_dir), ]) if inherit_paths: options.append(('inherit', 'file', ",\n ".join(inherit_paths))) try: self.__env = Environment(self.envname, create=True, options=options) except Exception as e: initenv_error(_('Failed to create environment.')) printerr(e) traceback.print_exc() sys.exit(1) # Add a few default wiki pages printout(_(" Installing default wiki pages")) pages_dir = pkg_resources.resource_filename('trac.wiki', 'default-pages') WikiAdmin(self.__env).load_pages(pages_dir) if repository_dir: try: repos = RepositoryManager(self.__env).get_repository('') if repos: printout(_(" Indexing default repository")) repos.sync(self._resync_feedback) except TracError as e: printerr(_(""" --------------------------------------------------------------------- Warning: couldn't index the default repository. This can happen for a variety of reasons: wrong repository type, no appropriate third party library for this repository type, no actual repository at the specified repository path... You can nevertheless start using your Trac environment, but you'll need to check again your trac.ini file and the [trac] repository_type and repository_path settings. """)) except Exception as e: initenv_error(to_unicode(e)) traceback.print_exc() return 2 printout(_(""" --------------------------------------------------------------------- Project environment for '%(project_name)s' created. You may now configure the environment by editing the file: %(config_path)s If you'd like to take this new project environment for a test drive, try running the Trac standalone web server `tracd`: tracd --port 8000 %(project_path)s Then point your browser to http://localhost:8000/%(project_dir)s. There you can also browse the documentation for your installed version of Trac, including information on further setup (such as deploying Trac to a real web server). The latest documentation can also always be found on the project website: http://trac.edgewall.org/ Congratulations! """, project_name=project_name, project_path=self.envname, project_dir=os.path.basename(self.envname), config_path=os.path.join(self.envname, 'conf', 'trac.ini')))
def _do_update(self, req): """Update component enablement.""" components = req.args.getlist('component') oenabled = req.args.getlist('enable') penabled = req.args.getlist('prjenable') changes = False changed = {} # Set global project configuration prjconf = Configuration(conf.global_conf_path) for component in components: c_state = self.get_project_component_state(component, self.config) c_activated = (component in oenabled) if self.is_plugin_changed(c_state, c_activated): self.config.set('components', component, c_activated and 'enabled' or 'disabled') self.log.info('%sabling component %s', c_activated and 'En' or 'Dis', component) changes = True if prjconf: cip_state = self.get_project_component_state(component, prjconf) cip_activated = (component in penabled) if self.is_plugin_changed(cip_state, cip_activated): self.log.info('%sabling project component %s', cip_activated and 'En' or 'Dis', component) changed[component] = cip_activated and 'enabled' or 'disabled' changes = True if prjconf: scomponents = req.args.getlist('setting') static_items = req.args.getlist('static_setting') for scomponent in scomponents: values = self.get_project_component_value(scomponent, None, prjconf) saved_value = self.parse_value(0, values) saved_static = self.parse_value(1, values) current_value = req.args.get(scomponent + '.value').replace('|', '') current_static = (scomponent in static_items) if saved_value != current_value or saved_static != current_static: if current_static: final_value = current_value else: final_value = current_value + '|no' prjconf.set('settings', scomponent, final_value) changes = True if changes: self.config.save() if prjconf: for key in changed.keys(): prjconf.set('components', key, changed[key]) prjconf.save()
class EnvironmentStub(Environment): """A stub of the trac.env.Environment object for testing.""" href = abs_href = None global_databasemanager = None def __init__(self, default_data=False, enable=None, disable=None, path=None, destroying=False): """Construct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. """ ComponentManager.__init__(self) Component.__init__(self) self.systeminfo = [] import trac self.path = path if self.path is None: self.path = os.path.dirname(trac.__file__) if not os.path.isabs(self.path): self.path = os.path.join(os.getcwd(), self.path) # -- configuration self.config = Configuration(None) # We have to have a ticket-workflow config for ''lots'' of things to # work. So insert the basic-workflow config here. There may be a # better solution than this. load_workflow_config_snippet(self.config, 'basic-workflow.ini') self.config.set('logging', 'log_level', 'DEBUG') self.config.set('logging', 'log_type', 'stderr') if enable is not None: self.config.set('components', 'trac.*', 'disabled') else: self.config.set('components', 'tracopt.versioncontrol.svn.*', 'enabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'enabled') for name_or_class in disable or (): config_key = self._component_name(name_or_class) self.config.set('components', config_key, 'disabled') # -- logging from trac.log import logger_handler_factory self.log, self._log_handler = logger_handler_factory('test') # -- database self.config.set('components', 'trac.db.*', 'enabled') self.dburi = get_dburi() init_global = False if self.global_databasemanager: self.components[DatabaseManager] = self.global_databasemanager else: self.config.set('trac', 'database', self.dburi) self.global_databasemanager = DatabaseManager(self) self.config.set('trac', 'debug_sql', True) self.config.set('logging', 'log_type', 'stderr') self.config.set('logging', 'log_level', 'DEBUG') init_global = not destroying if default_data or init_global: self.reset_db(default_data) from trac.web.href import Href self.href = Href('/trac.cgi') self.abs_href = Href('http://example.org/trac.cgi') self.known_users = [] translation.activate(locale_en) def reset_db(self, default_data=None): """Remove all data from Trac tables, keeping the tables themselves. :param default_data: after clean-up, initialize with default data :return: True upon success """ from trac import db_default scheme, db_prop = _parse_db_str(self.dburi) tables = [] remove_sqlite_db = False try: with self.db_transaction as db: db.rollback() # make sure there's no transaction in progress # check the database version database_version = db( "SELECT value FROM system WHERE name='database_version'") if database_version: database_version = int(database_version[0][0]) if database_version == db_default.db_version: # same version, simply clear the tables (faster) m = sys.modules[__name__] reset_fn = 'reset_%s_db' % scheme if hasattr(m, reset_fn): tables = getattr(m, reset_fn)(self, db_prop) else: # different version or version unknown, drop the tables remove_sqlite_db = True self.destroy_db(scheme, db_prop) except Exception, e: # "Database not found ...", # "OperationalError: no such table: system" or the like pass db = None # as we might shutdown the pool FIXME no longer needed! if scheme == 'sqlite' and remove_sqlite_db: path = db_prop['path'] if path != ':memory:': if not os.path.isabs(path): path = os.path.join(self.path, path) self.global_databasemanager.shutdown() os.remove(path) if not tables: self.global_databasemanager.init_db() # we need to make sure the next get_db_cnx() will re-create # a new connection aware of the new data model - see #8518. if self.dburi != 'sqlite::memory:': self.global_databasemanager.shutdown() with self.db_transaction as db: if default_data: for table, cols, vals in db_default.get_data(db): db.executemany("INSERT INTO %s (%s) VALUES (%s)" % (table, ','.join(cols), ','.join(['%s' for c in cols])), vals) else: db("INSERT INTO system (name, value) VALUES (%s, %s)", ('database_version', str(db_default.db_version)))
def __init__(self): self.port = str(Configuration.get(self.config, "trachat", "port", "8081")) t = TraChatPlugin.thread() t.port(self.port) t.start()
def sync(self, project): """Sync the trac environment with cydra This sets the options returned by ``get_default_options`` and adds Trac's own defaults if necessary""" if not self.has_env(project): logger.warning('Project %s has no Trac Environment to sync', project.name) return tracini = os.path.join(self.get_env_path(project), 'conf', 'trac.ini') options = self.get_default_options(project) # if inherit is enabled, the default values are supposed to be in # the inherited file. Thus, we can truncate the config file to get a bare minimum if 'inherit_config' in self.component_config: options.append(('inherit', 'file', self.component_config['inherit_config'])) with open(tracini, 'w') as f: f.truncate() # re-create the configuration file config = Configuration(tracini) for section, name, value in options: config.set(section, name, value) config.save() # load defaults if not any((section, option) == ('inherit', 'file') for section, option, value in options): config.set_defaults() config.save() # check if repositories in cydra match repositories in trac env = Environment(self.get_env_path(project)) rm = RepositoryManager(env) trac_repos = rm.get_real_repositories() trac_repo_names = [r.reponame for r in trac_repos] for repotype, repos in project.data.get('plugins', {}).get('trac', {}).items(): for repo, tracname in (repos or {}).items(): if tracname not in trac_repo_names: logger.warning("Removing trac mapping from cydra for %s repo %s", repo, tracname) del repos[repo] if not repos: del project.data.get('plugins', {}).get('trac', {})[repotype] # Now do the reverse revmap = dict([(y, x) for (x, y) in self.typemap.items()]) for repo in trac_repos: logger.debug('Looking at trac repo %s', repo.reponame) try: baseparts = repo.get_base().split(':') # This is extremely naiive and possibly breaks some time repotype, path = baseparts[0], baseparts[-1] except: logger.error("Unable to parse: " + repo.get_base()) reponame = os.path.basename(path) if repotype == 'git': reponame = reponame[:-4] try: repository = project.get_repository(revmap[repotype], reponame) except: logger.error("Unable to locate %s %s (%s)", repotype, reponame, path) repository = None logger.debug('Cydra repo %r', repository) if repository: # set this mapping if not there already project.data.setdefault('plugins', {}).setdefault('trac', {}).setdefault(repository.type, {})[repository.name] = repo.reponame logger.info('Setting trac mapping for %s %s -> %s', repository.type, repository.name, repo.reponame) else: logger.error("Unable to load %s %s (%s)", revmap[repotype], reponame, path) project.save()
class MockEnvironment(Environment): """ An mock Environment object which does not need real environment. Useful for when needing real environment like access to loaded plugins etc but no environment is at hand. Looks like normal project by default but can be made to look like home project environment or hybrid of both. .. WARNING:: Be careful when using this! """ def __init__(self, config_file=None, enabled_plugins=None, path=None): """ :param str config_file: path to the main configuration file. Defaults to ``/etc/trac/project.ini`` which is normal project configuration. :param list enabled_plugins: An explicit list of plugins to load, instead of reading enabled [components] from ``config_file``. If empty list is given no plugins are loaded. However plugins can be still listed via ``extra_plugins`` arg. :param str path: path to the imaginary trac location. """ if config_file is None: # TODO: switch to some constant when can be done without conf from multiproject.core.configuration import conf config_file = conf.config_file # From Environment.setup_config: self.config = Configuration(config_file) if path is None: path = os.path.join(self.config.get('multiproject', 'sys_projects_root'), '__mock_environment__') if enabled_plugins is not None: # explicit list given, disable all from configuration for key, val in self.config.options('components'): self.config.remove('components', key) # and replace with the given list for plugin in enabled_plugins: self.config.set('components', plugin, u'enabled') # We override the Environment.__init__ here. # Environment.__init__ is as follows: # ComponentManager.__init__(self) # # self.path = path # self.systeminfo = [] # self._href = self._abs_href = None # # if create: # self.create(options) # else: # self.verify() # self.setup_config() # # if create: # for setup_participant in self.setup_participants: # setup_participant.environment_created() # The Environment.setup_config is as follows: # self.config = Configuration(os.path.join(self.path, 'conf', # 'trac.ini')) # self.setup_log() # from trac.loader import load_components # plugins_dir = self.shared_plugins_dir # load_components(self, plugins_dir and (plugins_dir,)) # We use suitable lines from these as follows: # From Environment.__init__: ComponentManager.__init__(self) self.path = path self.systeminfo = [] self._href = self._abs_href = None # Our own plugin hack ends here, and setup_config lines continue here self.setup_log() from trac.loader import load_components load_components(self)