# HG changeset patch # User cmlenz # Date 1186480148 0 # Node ID 7930cdd83d133350f5f0b8b27909550bbd5bea4f # Parent 5786700df0c765cfccf0e2e0fc9fe6150dcba25f More restructuring: got rid of the `trac_ext` subpackage, which makes no sense now that the master is also coupled to Trac. diff --git a/bitten/api.py b/bitten/api.py new file mode 100644 --- /dev/null +++ b/bitten/api.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2005-2007 Christopher Lenz +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://bitten.edgewall.org/wiki/License. + +"""Interfaces of extension points provided by the Bitten Trac plugin.""" + +from trac.core import * + + +class IBuildListener(Interface): + """Extension point interface for components that need to be notified of + build events. + + Note that these will be notified in the process running the build master, + not the web interface. + """ + + def build_started(build): + """Called when a build slave has accepted a build initiation. + + @param build: the build that was started + @type build: an instance of L{bitten.model.Build} + """ + + def build_aborted(build): + """Called when a build slave cancels a build or disconnects. + + @param build: the build that was aborted + @type build: an instance of L{bitten.model.Build} + """ + + def build_completed(build): + """Called when a build slave has completed a build, regardless of the + outcome. + + @param build: the build that was aborted + @type build: an instance of L{bitten.model.Build} + """ + + +class ILogFormatter(Interface): + """Extension point interface for components that format build log + messages.""" + + def get_formatter(req, build): + """Return a function that gets called for every log message. + + The function must take four positional arguments, C{step}, + C{generator}, C{level} and C{message}, and return the formatted + message as a string. + + @param req: the request object + @param build: the build to which the logs belong that should be + formatted + @type build: an instance of L{bitten.model.Build} + """ + + +class IReportSummarizer(Interface): + """Extension point interface for components that render a summary of reports + of some kind.""" + + def get_supported_categories(): + """Return a list of strings identifying the types of reports this + component supports.""" + + def render_summary(req, config, build, step, category): + """Render a summary for the given report and return the resulting HTML + as string. + + @param req: the request object + @param config: the build configuration + @type config: an instance of L{bitten.model.BuildConfig} + @param build: the build + @type build: an instance of L{bitten.model.Build} + @param step: the build step + @type step: an instance of L{bitten.model.BuildStep} + @param category: the category of the report that should be summarized + """ + + +class IReportChartGenerator(Interface): + """Extension point interface for components that generator a chart for a + set of reports.""" + + def get_supported_categories(): + """Return a list of strings identifying the types of reports this + component supports.""" + + def generate_chart_data(req, config, category): + """Generate the data for a report chart. + + This method should store the data in the HDF of the request and return + the name of the template that should process the data. + + @param req: the request object + @param config: the build configuration + @type config: an instance of L{bitten.model.BuildConfig} + @param category: the category of reports to include in the chart + """ diff --git a/bitten/trac_ext/htdocs/bitten.css b/bitten/htdocs/bitten.css rename from bitten/trac_ext/htdocs/bitten.css rename to bitten/htdocs/bitten.css diff --git a/bitten/trac_ext/htdocs/bitten_build.png b/bitten/htdocs/bitten_build.png rename from bitten/trac_ext/htdocs/bitten_build.png rename to bitten/htdocs/bitten_build.png diff --git a/bitten/trac_ext/htdocs/bitten_buildf.png b/bitten/htdocs/bitten_buildf.png rename from bitten/trac_ext/htdocs/bitten_buildf.png rename to bitten/htdocs/bitten_buildf.png diff --git a/bitten/trac_ext/htdocs/charts.swf b/bitten/htdocs/charts.swf rename from bitten/trac_ext/htdocs/charts.swf rename to bitten/htdocs/charts.swf diff --git a/bitten/trac_ext/htdocs/charts_library/arno.swf b/bitten/htdocs/charts_library/arno.swf rename from bitten/trac_ext/htdocs/charts_library/arno.swf rename to bitten/htdocs/charts_library/arno.swf diff --git a/bitten/trac_ext/htdocs/charts_library/arst.swf b/bitten/htdocs/charts_library/arst.swf rename from bitten/trac_ext/htdocs/charts_library/arst.swf rename to bitten/htdocs/charts_library/arst.swf diff --git a/bitten/trac_ext/htdocs/charts_library/brfl.swf b/bitten/htdocs/charts_library/brfl.swf rename from bitten/trac_ext/htdocs/charts_library/brfl.swf rename to bitten/htdocs/charts_library/brfl.swf diff --git a/bitten/trac_ext/htdocs/charts_library/brno.swf b/bitten/htdocs/charts_library/brno.swf rename from bitten/trac_ext/htdocs/charts_library/brno.swf rename to bitten/htdocs/charts_library/brno.swf diff --git a/bitten/trac_ext/htdocs/charts_library/brst.swf b/bitten/htdocs/charts_library/brst.swf rename from bitten/trac_ext/htdocs/charts_library/brst.swf rename to bitten/htdocs/charts_library/brst.swf diff --git a/bitten/trac_ext/htdocs/charts_library/cl3d.swf b/bitten/htdocs/charts_library/cl3d.swf rename from bitten/trac_ext/htdocs/charts_library/cl3d.swf rename to bitten/htdocs/charts_library/cl3d.swf diff --git a/bitten/trac_ext/htdocs/charts_library/clfl.swf b/bitten/htdocs/charts_library/clfl.swf rename from bitten/trac_ext/htdocs/charts_library/clfl.swf rename to bitten/htdocs/charts_library/clfl.swf diff --git a/bitten/trac_ext/htdocs/charts_library/clno.swf b/bitten/htdocs/charts_library/clno.swf rename from bitten/trac_ext/htdocs/charts_library/clno.swf rename to bitten/htdocs/charts_library/clno.swf diff --git a/bitten/trac_ext/htdocs/charts_library/clp3.swf b/bitten/htdocs/charts_library/clp3.swf rename from bitten/trac_ext/htdocs/charts_library/clp3.swf rename to bitten/htdocs/charts_library/clp3.swf diff --git a/bitten/trac_ext/htdocs/charts_library/cls3.swf b/bitten/htdocs/charts_library/cls3.swf rename from bitten/trac_ext/htdocs/charts_library/cls3.swf rename to bitten/htdocs/charts_library/cls3.swf diff --git a/bitten/trac_ext/htdocs/charts_library/clst.swf b/bitten/htdocs/charts_library/clst.swf rename from bitten/trac_ext/htdocs/charts_library/clst.swf rename to bitten/htdocs/charts_library/clst.swf diff --git a/bitten/trac_ext/htdocs/charts_library/cnno.swf b/bitten/htdocs/charts_library/cnno.swf rename from bitten/trac_ext/htdocs/charts_library/cnno.swf rename to bitten/htdocs/charts_library/cnno.swf diff --git a/bitten/trac_ext/htdocs/charts_library/lnno.swf b/bitten/htdocs/charts_library/lnno.swf rename from bitten/trac_ext/htdocs/charts_library/lnno.swf rename to bitten/htdocs/charts_library/lnno.swf diff --git a/bitten/trac_ext/htdocs/charts_library/mxno.swf b/bitten/htdocs/charts_library/mxno.swf rename from bitten/trac_ext/htdocs/charts_library/mxno.swf rename to bitten/htdocs/charts_library/mxno.swf diff --git a/bitten/trac_ext/htdocs/charts_library/pi3d.swf b/bitten/htdocs/charts_library/pi3d.swf rename from bitten/trac_ext/htdocs/charts_library/pi3d.swf rename to bitten/htdocs/charts_library/pi3d.swf diff --git a/bitten/trac_ext/htdocs/charts_library/pino.swf b/bitten/htdocs/charts_library/pino.swf rename from bitten/trac_ext/htdocs/charts_library/pino.swf rename to bitten/htdocs/charts_library/pino.swf diff --git a/bitten/trac_ext/htdocs/charts_library/scno.swf b/bitten/htdocs/charts_library/scno.swf rename from bitten/trac_ext/htdocs/charts_library/scno.swf rename to bitten/htdocs/charts_library/scno.swf diff --git a/bitten/trac_ext/htdocs/failure.png b/bitten/htdocs/failure.png rename from bitten/trac_ext/htdocs/failure.png rename to bitten/htdocs/failure.png diff --git a/bitten/trac_ext/htdocs/tabset.js b/bitten/htdocs/tabset.js rename from bitten/trac_ext/htdocs/tabset.js rename to bitten/htdocs/tabset.js diff --git a/bitten/main.py b/bitten/main.py new file mode 100644 --- /dev/null +++ b/bitten/main.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2005-2007 Christopher Lenz +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://bitten.edgewall.org/wiki/License. + +import inspect +import os +import textwrap + +from trac.core import * +from trac.db import DatabaseManager +from trac.env import IEnvironmentSetupParticipant +from trac.perm import IPermissionRequestor +from trac.wiki import IWikiSyntaxProvider +from bitten.api import IBuildListener +from bitten.model import schema, schema_version, Build, BuildConfig + + +class BuildSystem(Component): + + implements(IEnvironmentSetupParticipant, IPermissionRequestor, + IWikiSyntaxProvider) + + listeners = ExtensionPoint(IBuildListener) + + # IEnvironmentSetupParticipant methods + + def environment_created(self): + # Create the required tables + db = self.env.get_db_cnx() + connector, _ = DatabaseManager(self.env)._get_connector() + cursor = db.cursor() + for table in schema: + for stmt in connector.to_sql(table): + cursor.execute(stmt) + + # Insert a global version flag + cursor.execute("INSERT INTO system (name,value) " + "VALUES ('bitten_version',%s)", (schema_version,)) + + # Create the directory for storing snapshot archives + snapshots_dir = os.path.join(self.env.path, 'snapshots') + os.mkdir(snapshots_dir) + + db.commit() + + def environment_needs_upgrade(self, db): + cursor = db.cursor() + cursor.execute("SELECT value FROM system WHERE name='bitten_version'") + row = cursor.fetchone() + if not row or int(row[0]) < schema_version: + return True + + def upgrade_environment(self, db): + cursor = db.cursor() + cursor.execute("SELECT value FROM system WHERE name='bitten_version'") + row = cursor.fetchone() + if not row: + self.environment_created() + else: + current_version = int(row[0]) + from bitten import upgrades + for version in range(current_version + 1, schema_version + 1): + for function in upgrades.map.get(version): + print textwrap.fill(inspect.getdoc(function)) + function(self.env, db) + print 'Done.' + cursor.execute("UPDATE system SET value=%s WHERE " + "name='bitten_version'", (schema_version,)) + self.log.info('Upgraded Bitten tables from version %d to %d', + current_version, schema_version) + + # IPermissionRequestor methods + + def get_permission_actions(self): + actions = ['BUILD_VIEW', 'BUILD_CREATE', 'BUILD_MODIFY', 'BUILD_DELETE', + 'BUILD_EXEC'] + return actions + [('BUILD_ADMIN', actions)] + + # IWikiSyntaxProvider methods + + def get_wiki_syntax(self): + return [] + + def get_link_resolvers(self): + def _format_link(formatter, ns, name, label): + build = Build.fetch(self.env, int(name)) + if build: + config = BuildConfig.fetch(self.env, build.config) + title = 'Build %d ([%s] of %s) by %s' % (build.id, build.rev, + config.label, build.slave) + return '%s' \ + % (formatter.href.build(build.config, build.id), title, + label) + return label + yield 'build', _format_link diff --git a/bitten/master.py b/bitten/master.py --- a/bitten/master.py +++ b/bitten/master.py @@ -30,9 +30,9 @@ RequestDone from bitten.model import BuildConfig, Build, BuildStep, BuildLog, Report +from bitten.main import BuildSystem from bitten.queue import BuildQueue from bitten.recipe import Recipe -from bitten.trac_ext.main import BuildSystem from bitten.util import xmlio diff --git a/bitten/report/coverage.py b/bitten/report/coverage.py --- a/bitten/report/coverage.py +++ b/bitten/report/coverage.py @@ -11,7 +11,7 @@ from trac.core import * from trac.web.chrome import Chrome from trac.web.clearsilver import HDFWrapper -from bitten.trac_ext.api import IReportChartGenerator, IReportSummarizer +from bitten.api import IReportChartGenerator, IReportSummarizer class TestCoverageChartGenerator(Component): diff --git a/bitten/report/testing.py b/bitten/report/testing.py --- a/bitten/report/testing.py +++ b/bitten/report/testing.py @@ -11,7 +11,7 @@ from trac.core import * from trac.web.chrome import Chrome from trac.web.clearsilver import HDFWrapper -from bitten.trac_ext.api import IReportChartGenerator, IReportSummarizer +from bitten.api import IReportChartGenerator, IReportSummarizer class TestResultsChartGenerator(Component): diff --git a/bitten/report/tests/coverage.py b/bitten/report/tests/coverage.py --- a/bitten/report/tests/coverage.py +++ b/bitten/report/tests/coverage.py @@ -10,11 +10,11 @@ import unittest +from trac.db import DatabaseManager from trac.test import EnvironmentStub, Mock from trac.web.clearsilver import HDFWrapper from bitten.model import * from bitten.report.coverage import TestCoverageChartGenerator -from bitten.trac_ext.compat import schema_to_sql class TestCoverageChartGeneratorTestCase(unittest.TestCase): @@ -24,8 +24,10 @@ self.env.path = '' db = self.env.get_db_cnx() cursor = db.cursor() + + connector, _ = DatabaseManager(self.env)._get_connector() for table in schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) def test_supported_categories(self): diff --git a/bitten/report/tests/testing.py b/bitten/report/tests/testing.py --- a/bitten/report/tests/testing.py +++ b/bitten/report/tests/testing.py @@ -10,11 +10,11 @@ import unittest +from trac.db import DatabaseManager from trac.test import EnvironmentStub, Mock from trac.web.clearsilver import HDFWrapper from bitten.model import * from bitten.report.testing import TestResultsChartGenerator -from bitten.trac_ext.compat import schema_to_sql class TestResultsChartGeneratorTestCase(unittest.TestCase): @@ -22,10 +22,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) def test_supported_categories(self): diff --git a/bitten/trac_ext/templates/bitten_build.cs b/bitten/templates/bitten_build.cs rename from bitten/trac_ext/templates/bitten_build.cs rename to bitten/templates/bitten_build.cs diff --git a/bitten/trac_ext/templates/bitten_chart_coverage.cs b/bitten/templates/bitten_chart_coverage.cs rename from bitten/trac_ext/templates/bitten_chart_coverage.cs rename to bitten/templates/bitten_chart_coverage.cs diff --git a/bitten/trac_ext/templates/bitten_chart_tests.cs b/bitten/templates/bitten_chart_tests.cs rename from bitten/trac_ext/templates/bitten_chart_tests.cs rename to bitten/templates/bitten_chart_tests.cs diff --git a/bitten/trac_ext/templates/bitten_config.cs b/bitten/templates/bitten_config.cs rename from bitten/trac_ext/templates/bitten_config.cs rename to bitten/templates/bitten_config.cs diff --git a/bitten/trac_ext/templates/bitten_summary_coverage.cs b/bitten/templates/bitten_summary_coverage.cs rename from bitten/trac_ext/templates/bitten_summary_coverage.cs rename to bitten/templates/bitten_summary_coverage.cs diff --git a/bitten/trac_ext/templates/bitten_summary_tests.cs b/bitten/templates/bitten_summary_tests.cs rename from bitten/trac_ext/templates/bitten_summary_tests.cs rename to bitten/templates/bitten_summary_tests.cs diff --git a/bitten/tests/__init__.py b/bitten/tests/__init__.py --- a/bitten/tests/__init__.py +++ b/bitten/tests/__init__.py @@ -10,10 +10,9 @@ import unittest -from bitten.tests import master, model, recipe, queue, slave +from bitten.tests import master, model, recipe, queue, slave, web_ui from bitten.build import tests as build from bitten.report import tests as report -from bitten.trac_ext import tests as trac_ext from bitten.util import tests as util def suite(): @@ -23,9 +22,9 @@ suite.addTest(recipe.suite()) suite.addTest(queue.suite()) suite.addTest(slave.suite()) + suite.addTest(web_ui.suite()) suite.addTest(build.suite()) suite.addTest(report.suite()) - suite.addTest(trac_ext.suite()) suite.addTest(util.suite()) return suite diff --git a/bitten/tests/master.py b/bitten/tests/master.py --- a/bitten/tests/master.py +++ b/bitten/tests/master.py @@ -15,17 +15,17 @@ import tempfile import unittest +from trac.db import DatabaseManager from trac.perm import PermissionCache, PermissionSystem from trac.test import EnvironmentStub, Mock from trac.web.api import HTTPBadRequest, HTTPMethodNotAllowed, HTTPNotFound, \ RequestDone from trac.web.href import Href +from bitten.main import BuildSystem from bitten.master import BuildMaster from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, \ BuildLog, Report, schema -from bitten.trac_ext.compat import schema_to_sql -from bitten.trac_ext.main import BuildSystem class BuildMasterTestCase(unittest.TestCase): @@ -39,8 +39,9 @@ # Create tables db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) self.repos = Mock() diff --git a/bitten/tests/model.py b/bitten/tests/model.py --- a/bitten/tests/model.py +++ b/bitten/tests/model.py @@ -10,10 +10,10 @@ import unittest +from trac.db import DatabaseManager from trac.test import EnvironmentStub from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, \ BuildLog, Report, schema -from bitten.trac_ext.compat import schema_to_sql class BuildConfigTestCase(unittest.TestCase): @@ -21,10 +21,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() @@ -157,10 +159,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in TargetPlatform._schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() @@ -212,10 +216,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in Build._schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() @@ -319,10 +325,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in BuildStep._schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() @@ -419,10 +427,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in BuildLog._schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() @@ -549,10 +559,12 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = '' + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in Report._schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() diff --git a/bitten/tests/queue.py b/bitten/tests/queue.py --- a/bitten/tests/queue.py +++ b/bitten/tests/queue.py @@ -13,10 +13,10 @@ import tempfile import unittest +from trac.db import DatabaseManager from trac.test import EnvironmentStub, Mock from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, schema from bitten.queue import BuildQueue, collect_changes -from bitten.trac_ext.compat import schema_to_sql class CollectChangesTestCase(unittest.TestCase): @@ -27,11 +27,14 @@ def setUp(self): self.env = EnvironmentStub() self.env.path = tempfile.mkdtemp() + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) + self.config = BuildConfig(self.env, name='test', path='somepath') self.config.insert(db=db) self.platform = TargetPlatform(self.env, config='test', name='Foo') @@ -123,10 +126,12 @@ self.env = EnvironmentStub() self.env.path = tempfile.mkdtemp() os.mkdir(os.path.join(self.env.path, 'snapshots')) + db = self.env.get_db_cnx() cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() for table in schema: - for stmt in schema_to_sql(self.env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) db.commit() diff --git a/bitten/tests/web_ui.py b/bitten/tests/web_ui.py new file mode 100644 --- /dev/null +++ b/bitten/tests/web_ui.py @@ -0,0 +1,553 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2005-2007 Christopher Lenz +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://bitten.edgewall.org/wiki/License. + +import shutil +import tempfile +import unittest + +from trac.core import TracError +from trac.db import DatabaseManager +from trac.perm import PermissionCache, PermissionSystem +from trac.test import EnvironmentStub, Mock +from trac.versioncontrol import Repository +from trac.web.clearsilver import HDFWrapper +from trac.web.href import Href +from trac.web.main import Request, RequestDone +from bitten.main import BuildSystem +from bitten.model import BuildConfig, TargetPlatform, Build, schema +from bitten.web_ui import BuildConfigController + + +class BuildConfigControllerTestCase(unittest.TestCase): + + def setUp(self): + self.env = EnvironmentStub() + self.env.path = tempfile.mkdtemp() + + # Create tables + db = self.env.get_db_cnx() + cursor = db.cursor() + connector, _ = DatabaseManager(self.env)._get_connector() + for table in schema: + for stmt in connector.to_sql(table): + cursor.execute(stmt) + + # Set up permissions + self.env.config.set('trac', 'permission_store', + 'DefaultPermissionStore') + + # Hook up a dummy repository + self.repos = Mock( + get_node=lambda path, rev=None: Mock(get_history=lambda: [], + isdir=True), + normalize_path=lambda path: path, + sync=lambda: None + ) + self.env.get_repository = lambda authname=None: self.repos + + def tearDown(self): + shutil.rmtree(self.env.path) + + def test_overview(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), args={}, chrome={}, + hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe')) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('overview', req.hdf['page.mode']) + self.assertEqual('0', req.hdf.get('build.can_create', '0')) + + def test_overview_admin(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), args={}, chrome={}, + hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe')) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('1', req.hdf.get('config.can_create')) + + def test_view_config(self): + config = BuildConfig(self.env, name='test', path='trunk') + config.insert() + platform = TargetPlatform(self.env, config='test', name='any') + platform.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), args={}, + chrome={}, hdf=HDFWrapper(), authname='joe', + perm=PermissionCache(self.env, 'joe')) + + root = Mock(get_entries=lambda: ['foo'], + get_history=lambda: [('trunk', rev, 'edit') for rev in + range(123, 111, -1)]) + self.repos = Mock(get_node=lambda path, rev=None: root, + sync=lambda: None, normalize_path=lambda path: path) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('view_config', req.hdf['page.mode']) + self.assertEqual('0', req.hdf.get('build.config.can_delete', '0')) + self.assertEqual('0', req.hdf.get('build.config.can_modify', '0')) + self.assertEqual(None, req.hdf.get('chrome.links.next.0.href')) + + def test_view_config_paging(self): + config = BuildConfig(self.env, name='test', path='trunk') + config.insert() + platform = TargetPlatform(self.env, config='test', name='any') + platform.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), args={}, + chrome={}, hdf=HDFWrapper(), authname='joe', + perm=PermissionCache(self.env, 'joe')) + + root = Mock(get_entries=lambda: ['foo'], + get_history=lambda: [('trunk', rev, 'edit') for rev in + range(123, 110, -1)]) + self.repos = Mock(get_node=lambda path, rev=None: root, + sync=lambda: None, normalize_path=lambda path: path) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + if req.chrome: # Trac 0.11 + self.assertEqual('/trac/build/test?page=2', + req.chrome['links']['next'][0]['href']) + else: + self.assertEqual('/trac/build/test?page=2', + req.hdf.get('chrome.links.next.0.href')) + + def test_view_config_admin(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), args={}, + chrome={}, hdf=HDFWrapper(), authname='joe', + perm=PermissionCache(self.env, 'joe')) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('1', req.hdf.get('config.can_delete')) + self.assertEqual('1', req.hdf.get('config.can_modify')) + + def test_new_config(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build', args={'action': 'new'}, hdf=HDFWrapper(), + href=Href('/trac'), chrome={}, + perm=PermissionCache(self.env, 'joe')) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('edit_config', req.hdf['page.mode']) + + def test_new_config_submit(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), redirect=redirect, + hdf=HDFWrapper(), authname='joe', + perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': 'test', 'path': 'test/trunk', + 'label': 'Test', 'description': 'Bla bla'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test', redirected_to[0]) + + config = BuildConfig.fetch(self.env, 'test') + assert config.exists + assert not config.active + self.assertEqual('Test', config.label) + self.assertEqual('test/trunk', config.path) + self.assertEqual('Bla bla', config.description) + + def test_new_config_submit_without_name(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': '', 'path': 'test/trunk', + 'label': 'Test', 'description': 'Bla bla'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(TracError, module.process_request, req) + + def test_new_config_submit_with_invalid_name(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': 'Foo bar', + 'path': 'test/trunk', 'label': 'Test', + 'description': 'Bla bla'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(TracError, module.process_request, req) + + def test_new_config_submit_invalid_path(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), + authname='joe', perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': 'test', 'path': 'test/trunk', + 'label': 'Test', 'description': 'Bla bla'}) + + def get_node(path, rev=None): + raise TracError('No such node') + self.repos = Mock(get_node=get_node) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(TracError, module.process_request, req) + + def test_new_config_submit_with_non_wellformed_recipe(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), + authname='joe', perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': 'test', 'path': 'test/trunk', + 'label': 'Test', 'description': 'Bla bla', + 'recipe': ''}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(TracError, module.process_request, req) + + def test_new_config_submit_with_invalid_recipe(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), + authname='joe', perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': 'test', 'path': 'test/trunk', + 'label': 'Test', 'description': 'Bla bla', + 'recipe': ''}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(TracError, module.process_request, req) + + def test_new_config_cancel(self): + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build', href=Href('/trac'), redirect=redirect, + hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'cancel': '1', 'name': 'test'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build', redirected_to[0]) + + self.assertEqual(None, BuildConfig.fetch(self.env, 'test')) + + def test_delete_config(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), chrome={}, + hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe'), + args={'action': 'delete'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('delete_config', req.hdf['page.mode']) + + def test_delete_config_submit(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'delete'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build', redirected_to[0]) + + self.assertEqual(None, BuildConfig.fetch(self.env, 'test')) + + def test_edit_config_cancel(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'delete', 'cancel': ''}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test', redirected_to[0]) + + self.assertEqual(True, BuildConfig.fetch(self.env, 'test').exists) + + def test_edit_config(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', hdf=HDFWrapper(), + href=Href('/build/test'), chrome={}, + perm=PermissionCache(self.env, 'joe'), + args={'action': 'edit'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('edit_config', req.hdf['page.mode']) + + def test_edit_config_submit(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + authname='joe', perm=PermissionCache(self.env, 'joe'), + args={'action': 'edit', 'name': 'foo', 'path': 'test/trunk', + 'label': 'Test', 'description': 'Bla bla'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/foo', redirected_to[0]) + + self.assertEqual(None, BuildConfig.fetch(self.env, 'test')) + + config = BuildConfig.fetch(self.env, 'foo') + assert config.exists + self.assertEqual('Test', config.label) + self.assertEqual('test/trunk', config.path) + self.assertEqual('Bla bla', config.description) + + def test_edit_config_cancel(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'edit', 'cancel': ''}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test', redirected_to[0]) + + def test_new_platform(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', hdf=HDFWrapper(), href=Href('trac'), + chrome={}, perm=PermissionCache(self.env, 'joe'), + args={'action': 'edit', 'new': '1'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('edit_platform', req.hdf['page.mode']) + + def test_new_platform_submit(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'name': 'Test'}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) + + def test_new_platform_cancel(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + perm=PermissionCache(self.env, 'joe'), + args={'action': 'new', 'cancel': ''}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) + + def test_edit_platform(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + platform = TargetPlatform(self.env) + platform.config = 'test' + platform.name = 'linux' + platform.rules.append(('os', 'linux?')) + platform.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + req = Mock(method='GET', base_path='', cgi_location='', + path_info='/build/test', hdf=HDFWrapper(), + href=Href('/trac'), chrome={}, + perm=PermissionCache(self.env, 'joe'), + args={'action': 'edit', 'platform': platform.id}) + + module = BuildConfigController(self.env) + assert module.match_request(req) + module.process_request(req) + + self.assertEqual('edit_platform', req.hdf['page.mode']) + + def test_edit_platform_submit(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + platform = TargetPlatform(self.env) + platform.config = 'test' + platform.name = 'linux' + platform.rules.append(('os', 'linux?')) + platform.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + args={'action': 'edit', 'platform': platform.id, + 'name': 'Test'}, + perm=PermissionCache(self.env, 'joe')) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) + + def test_edit_platform_cancel(self): + config = BuildConfig(self.env) + config.name = 'test' + config.insert() + platform = TargetPlatform(self.env) + platform.config = 'test' + platform.name = 'linux' + platform.rules.append(('os', 'linux')) + platform.insert() + + PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') + redirected_to = [] + def redirect(url): + redirected_to.append(url) + raise RequestDone + req = Mock(method='POST', base_path='', cgi_location='', + path_info='/build/test', href=Href('/trac'), + redirect=redirect, hdf=HDFWrapper(), + args={'action': 'edit', 'platform': platform.id, + 'cancel': ''}, + perm=PermissionCache(self.env, 'joe')) + + module = BuildConfigController(self.env) + assert module.match_request(req) + self.assertRaises(RequestDone, module.process_request, req) + self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) + + +def suite(): + return unittest.makeSuite(BuildConfigControllerTestCase, 'test') + +if __name__ == '__main__': + unittest.main(defaultTest='suite') diff --git a/bitten/trac_ext/__init__.py b/bitten/trac_ext/__init__.py deleted file mode 100644 --- a/bitten/trac_ext/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005-2007 Christopher Lenz -# Copyright (C) 2007 Edgewall Software -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://bitten.edgewall.org/wiki/License. - -"""Implementation of the Bitten plugin for Trac.""" - -from bitten.trac_ext.api import * diff --git a/bitten/trac_ext/api.py b/bitten/trac_ext/api.py deleted file mode 100644 --- a/bitten/trac_ext/api.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005-2007 Christopher Lenz -# Copyright (C) 2007 Edgewall Software -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://bitten.edgewall.org/wiki/License. - -"""Interfaces of extension points provided by the Bitten Trac plugin.""" - -from trac.core import * - - -class IBuildListener(Interface): - """Extension point interface for components that need to be notified of - build events. - - Note that these will be notified in the process running the build master, - not the web interface. - """ - - def build_started(build): - """Called when a build slave has accepted a build initiation. - - @param build: the build that was started - @type build: an instance of L{bitten.model.Build} - """ - - def build_aborted(build): - """Called when a build slave cancels a build or disconnects. - - @param build: the build that was aborted - @type build: an instance of L{bitten.model.Build} - """ - - def build_completed(build): - """Called when a build slave has completed a build, regardless of the - outcome. - - @param build: the build that was aborted - @type build: an instance of L{bitten.model.Build} - """ - - -class ILogFormatter(Interface): - """Extension point interface for components that format build log - messages.""" - - def get_formatter(req, build): - """Return a function that gets called for every log message. - - The function must take four positional arguments, C{step}, - C{generator}, C{level} and C{message}, and return the formatted - message as a string. - - @param req: the request object - @param build: the build to which the logs belong that should be - formatted - @type build: an instance of L{bitten.model.Build} - """ - - -class IReportSummarizer(Interface): - """Extension point interface for components that render a summary of reports - of some kind.""" - - def get_supported_categories(): - """Return a list of strings identifying the types of reports this - component supports.""" - - def render_summary(req, config, build, step, category): - """Render a summary for the given report and return the resulting HTML - as string. - - @param req: the request object - @param config: the build configuration - @type config: an instance of L{bitten.model.BuildConfig} - @param build: the build - @type build: an instance of L{bitten.model.Build} - @param step: the build step - @type step: an instance of L{bitten.model.BuildStep} - @param category: the category of the report that should be summarized - """ - - -class IReportChartGenerator(Interface): - """Extension point interface for components that generator a chart for a - set of reports.""" - - def get_supported_categories(): - """Return a list of strings identifying the types of reports this - component supports.""" - - def generate_chart_data(req, config, category): - """Generate the data for a report chart. - - This method should store the data in the HDF of the request and return - the name of the template that should process the data. - - @param req: the request object - @param config: the build configuration - @type config: an instance of L{bitten.model.BuildConfig} - @param category: the category of reports to include in the chart - """ diff --git a/bitten/trac_ext/compat.py b/bitten/trac_ext/compat.py deleted file mode 100644 --- a/bitten/trac_ext/compat.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2006-2007 Christopher Lenz -# Copyright (C) 2007 Edgewall Software -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://bitten.edgewall.org/wiki/License. - -"""Various methods for backwards compatibility with older Trac versions.""" - -def schema_to_sql(env, db, table): - try: - # Trac >= 0.10 - from trac.db import DatabaseManager - connector, _ = DatabaseManager(env)._get_connector() - return connector.to_sql(table) - except ImportError: - # Trac 0.9.x - return db.to_sql(table) diff --git a/bitten/trac_ext/main.py b/bitten/trac_ext/main.py deleted file mode 100644 --- a/bitten/trac_ext/main.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005-2007 Christopher Lenz -# Copyright (C) 2007 Edgewall Software -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://bitten.edgewall.org/wiki/License. - -import inspect -import os -import textwrap - -from trac.core import * -from trac.env import IEnvironmentSetupParticipant -from trac.perm import IPermissionRequestor -from trac.wiki import IWikiSyntaxProvider -from bitten.trac_ext.api import IBuildListener -from bitten.trac_ext.compat import schema_to_sql -from bitten.model import schema, schema_version, Build, BuildConfig - - -class BuildSystem(Component): - - implements(IEnvironmentSetupParticipant, IPermissionRequestor, - IWikiSyntaxProvider) - - listeners = ExtensionPoint(IBuildListener) - - # IEnvironmentSetupParticipant methods - - def environment_created(self): - # Create the required tables - db = self.env.get_db_cnx() - cursor = db.cursor() - for table in schema: - for stmt in schema_to_sql(self.env, db, table): - cursor.execute(stmt) - - # Insert a global version flag - cursor.execute("INSERT INTO system (name,value) " - "VALUES ('bitten_version',%s)", (schema_version,)) - - # Create the directory for storing snapshot archives - snapshots_dir = os.path.join(self.env.path, 'snapshots') - os.mkdir(snapshots_dir) - - db.commit() - - def environment_needs_upgrade(self, db): - cursor = db.cursor() - cursor.execute("SELECT value FROM system WHERE name='bitten_version'") - row = cursor.fetchone() - if not row or int(row[0]) < schema_version: - return True - - def upgrade_environment(self, db): - cursor = db.cursor() - cursor.execute("SELECT value FROM system WHERE name='bitten_version'") - row = cursor.fetchone() - if not row: - self.environment_created() - else: - current_version = int(row[0]) - from bitten import upgrades - for version in range(current_version + 1, schema_version + 1): - for function in upgrades.map.get(version): - print textwrap.fill(inspect.getdoc(function)) - function(self.env, db) - print 'Done.' - cursor.execute("UPDATE system SET value=%s WHERE " - "name='bitten_version'", (schema_version,)) - self.log.info('Upgraded Bitten tables from version %d to %d', - current_version, schema_version) - - # IPermissionRequestor methods - - def get_permission_actions(self): - actions = ['BUILD_VIEW', 'BUILD_CREATE', 'BUILD_MODIFY', 'BUILD_DELETE', - 'BUILD_EXEC'] - return actions + [('BUILD_ADMIN', actions)] - - # IWikiSyntaxProvider methods - - def get_wiki_syntax(self): - return [] - - def get_link_resolvers(self): - def _format_link(formatter, ns, name, label): - build = Build.fetch(self.env, int(name)) - if build: - config = BuildConfig.fetch(self.env, build.config) - title = 'Build %d ([%s] of %s) by %s' % (build.id, build.rev, - config.label, build.slave) - return '%s' \ - % (formatter.href.build(build.config, build.id), title, - label) - return label - yield 'build', _format_link diff --git a/bitten/trac_ext/tests/__init__.py b/bitten/trac_ext/tests/__init__.py deleted file mode 100644 --- a/bitten/trac_ext/tests/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005-2007 Christopher Lenz -# Copyright (C) 2007 Edgewall Software -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://bitten.edgewall.org/wiki/License. - -import unittest - -from bitten.trac_ext.tests import web_ui - -def suite(): - suite = unittest.TestSuite() - suite.addTest(web_ui.suite()) - return suite - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/bitten/trac_ext/tests/web_ui.py b/bitten/trac_ext/tests/web_ui.py deleted file mode 100644 --- a/bitten/trac_ext/tests/web_ui.py +++ /dev/null @@ -1,552 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005-2007 Christopher Lenz -# Copyright (C) 2007 Edgewall Software -# All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://bitten.edgewall.org/wiki/License. - -import shutil -import tempfile -import unittest - -from trac.core import TracError -from trac.perm import PermissionCache, PermissionSystem -from trac.test import EnvironmentStub, Mock -from trac.versioncontrol import Repository -from trac.web.clearsilver import HDFWrapper -from trac.web.href import Href -from trac.web.main import Request, RequestDone -from bitten.model import BuildConfig, TargetPlatform, Build, schema -from bitten.trac_ext.compat import schema_to_sql -from bitten.trac_ext.main import BuildSystem -from bitten.trac_ext.web_ui import BuildConfigController - - -class BuildConfigControllerTestCase(unittest.TestCase): - - def setUp(self): - self.env = EnvironmentStub() - self.env.path = tempfile.mkdtemp() - - # Create tables - db = self.env.get_db_cnx() - cursor = db.cursor() - for table in schema: - for stmt in schema_to_sql(self.env, db, table): - cursor.execute(stmt) - - # Set up permissions - self.env.config.set('trac', 'permission_store', - 'DefaultPermissionStore') - - # Hook up a dummy repository - self.repos = Mock( - get_node=lambda path, rev=None: Mock(get_history=lambda: [], - isdir=True), - normalize_path=lambda path: path, - sync=lambda: None - ) - self.env.get_repository = lambda authname=None: self.repos - - def tearDown(self): - shutil.rmtree(self.env.path) - - def test_overview(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), args={}, chrome={}, - hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe')) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('overview', req.hdf['page.mode']) - self.assertEqual('0', req.hdf.get('build.can_create', '0')) - - def test_overview_admin(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), args={}, chrome={}, - hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe')) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('1', req.hdf.get('config.can_create')) - - def test_view_config(self): - config = BuildConfig(self.env, name='test', path='trunk') - config.insert() - platform = TargetPlatform(self.env, config='test', name='any') - platform.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), args={}, - chrome={}, hdf=HDFWrapper(), authname='joe', - perm=PermissionCache(self.env, 'joe')) - - root = Mock(get_entries=lambda: ['foo'], - get_history=lambda: [('trunk', rev, 'edit') for rev in - range(123, 111, -1)]) - self.repos = Mock(get_node=lambda path, rev=None: root, - sync=lambda: None, normalize_path=lambda path: path) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('view_config', req.hdf['page.mode']) - self.assertEqual('0', req.hdf.get('build.config.can_delete', '0')) - self.assertEqual('0', req.hdf.get('build.config.can_modify', '0')) - self.assertEqual(None, req.hdf.get('chrome.links.next.0.href')) - - def test_view_config_paging(self): - config = BuildConfig(self.env, name='test', path='trunk') - config.insert() - platform = TargetPlatform(self.env, config='test', name='any') - platform.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_VIEW') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), args={}, - chrome={}, hdf=HDFWrapper(), authname='joe', - perm=PermissionCache(self.env, 'joe')) - - root = Mock(get_entries=lambda: ['foo'], - get_history=lambda: [('trunk', rev, 'edit') for rev in - range(123, 110, -1)]) - self.repos = Mock(get_node=lambda path, rev=None: root, - sync=lambda: None, normalize_path=lambda path: path) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - if req.chrome: # Trac 0.11 - self.assertEqual('/trac/build/test?page=2', - req.chrome['links']['next'][0]['href']) - else: - self.assertEqual('/trac/build/test?page=2', - req.hdf.get('chrome.links.next.0.href')) - - def test_view_config_admin(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), args={}, - chrome={}, hdf=HDFWrapper(), authname='joe', - perm=PermissionCache(self.env, 'joe')) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('1', req.hdf.get('config.can_delete')) - self.assertEqual('1', req.hdf.get('config.can_modify')) - - def test_new_config(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build', args={'action': 'new'}, hdf=HDFWrapper(), - href=Href('/trac'), chrome={}, - perm=PermissionCache(self.env, 'joe')) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('edit_config', req.hdf['page.mode']) - - def test_new_config_submit(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), redirect=redirect, - hdf=HDFWrapper(), authname='joe', - perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': 'test', 'path': 'test/trunk', - 'label': 'Test', 'description': 'Bla bla'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test', redirected_to[0]) - - config = BuildConfig.fetch(self.env, 'test') - assert config.exists - assert not config.active - self.assertEqual('Test', config.label) - self.assertEqual('test/trunk', config.path) - self.assertEqual('Bla bla', config.description) - - def test_new_config_submit_without_name(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': '', 'path': 'test/trunk', - 'label': 'Test', 'description': 'Bla bla'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(TracError, module.process_request, req) - - def test_new_config_submit_with_invalid_name(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': 'Foo bar', - 'path': 'test/trunk', 'label': 'Test', - 'description': 'Bla bla'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(TracError, module.process_request, req) - - def test_new_config_submit_invalid_path(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), - authname='joe', perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': 'test', 'path': 'test/trunk', - 'label': 'Test', 'description': 'Bla bla'}) - - def get_node(path, rev=None): - raise TracError('No such node') - self.repos = Mock(get_node=get_node) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(TracError, module.process_request, req) - - def test_new_config_submit_with_non_wellformed_recipe(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), - authname='joe', perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': 'test', 'path': 'test/trunk', - 'label': 'Test', 'description': 'Bla bla', - 'recipe': ''}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(TracError, module.process_request, req) - - def test_new_config_submit_with_invalid_recipe(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), hdf=HDFWrapper(), - authname='joe', perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': 'test', 'path': 'test/trunk', - 'label': 'Test', 'description': 'Bla bla', - 'recipe': ''}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(TracError, module.process_request, req) - - def test_new_config_cancel(self): - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build', href=Href('/trac'), redirect=redirect, - hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'cancel': '1', 'name': 'test'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build', redirected_to[0]) - - self.assertEqual(None, BuildConfig.fetch(self.env, 'test')) - - def test_delete_config(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), chrome={}, - hdf=HDFWrapper(), perm=PermissionCache(self.env, 'joe'), - args={'action': 'delete'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('delete_config', req.hdf['page.mode']) - - def test_delete_config_submit(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'delete'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build', redirected_to[0]) - - self.assertEqual(None, BuildConfig.fetch(self.env, 'test')) - - def test_edit_config_cancel(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'delete', 'cancel': ''}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test', redirected_to[0]) - - self.assertEqual(True, BuildConfig.fetch(self.env, 'test').exists) - - def test_edit_config(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', hdf=HDFWrapper(), - href=Href('/build/test'), chrome={}, - perm=PermissionCache(self.env, 'joe'), - args={'action': 'edit'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('edit_config', req.hdf['page.mode']) - - def test_edit_config_submit(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - authname='joe', perm=PermissionCache(self.env, 'joe'), - args={'action': 'edit', 'name': 'foo', 'path': 'test/trunk', - 'label': 'Test', 'description': 'Bla bla'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/foo', redirected_to[0]) - - self.assertEqual(None, BuildConfig.fetch(self.env, 'test')) - - config = BuildConfig.fetch(self.env, 'foo') - assert config.exists - self.assertEqual('Test', config.label) - self.assertEqual('test/trunk', config.path) - self.assertEqual('Bla bla', config.description) - - def test_edit_config_cancel(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'edit', 'cancel': ''}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test', redirected_to[0]) - - def test_new_platform(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', hdf=HDFWrapper(), href=Href('trac'), - chrome={}, perm=PermissionCache(self.env, 'joe'), - args={'action': 'edit', 'new': '1'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('edit_platform', req.hdf['page.mode']) - - def test_new_platform_submit(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'name': 'Test'}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) - - def test_new_platform_cancel(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - perm=PermissionCache(self.env, 'joe'), - args={'action': 'new', 'cancel': ''}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) - - def test_edit_platform(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - platform = TargetPlatform(self.env) - platform.config = 'test' - platform.name = 'linux' - platform.rules.append(('os', 'linux?')) - platform.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - req = Mock(method='GET', base_path='', cgi_location='', - path_info='/build/test', hdf=HDFWrapper(), - href=Href('/trac'), chrome={}, - perm=PermissionCache(self.env, 'joe'), - args={'action': 'edit', 'platform': platform.id}) - - module = BuildConfigController(self.env) - assert module.match_request(req) - module.process_request(req) - - self.assertEqual('edit_platform', req.hdf['page.mode']) - - def test_edit_platform_submit(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - platform = TargetPlatform(self.env) - platform.config = 'test' - platform.name = 'linux' - platform.rules.append(('os', 'linux?')) - platform.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - args={'action': 'edit', 'platform': platform.id, - 'name': 'Test'}, - perm=PermissionCache(self.env, 'joe')) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) - - def test_edit_platform_cancel(self): - config = BuildConfig(self.env) - config.name = 'test' - config.insert() - platform = TargetPlatform(self.env) - platform.config = 'test' - platform.name = 'linux' - platform.rules.append(('os', 'linux')) - platform.insert() - - PermissionSystem(self.env).grant_permission('joe', 'BUILD_ADMIN') - redirected_to = [] - def redirect(url): - redirected_to.append(url) - raise RequestDone - req = Mock(method='POST', base_path='', cgi_location='', - path_info='/build/test', href=Href('/trac'), - redirect=redirect, hdf=HDFWrapper(), - args={'action': 'edit', 'platform': platform.id, - 'cancel': ''}, - perm=PermissionCache(self.env, 'joe')) - - module = BuildConfigController(self.env) - assert module.match_request(req) - self.assertRaises(RequestDone, module.process_request, req) - self.assertEqual('/trac/build/test?action=edit', redirected_to[0]) - - -def suite(): - return unittest.makeSuite(BuildConfigControllerTestCase, 'test') - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/bitten/upgrades.py b/bitten/upgrades.py --- a/bitten/upgrades.py +++ b/bitten/upgrades.py @@ -14,15 +14,16 @@ import os import sys -from bitten.trac_ext.compat import schema_to_sql +from trac.db import DatabaseManager def add_log_table(env, db): """Add a table for storing the builds logs.""" from bitten.model import BuildLog, BuildStep cursor = db.cursor() + connector, _ = DatabaseManager(env)._get_connector() for table in BuildLog._schema: - for stmt in schema_to_sql(env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) cursor.execute("SELECT build,name,log FROM bitten_step " @@ -35,7 +36,7 @@ cursor.execute("CREATE TEMP TABLE old_step AS SELECT * FROM bitten_step") cursor.execute("DROP TABLE bitten_step") for table in BuildStep._schema: - for stmt in schema_to_sql(env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) cursor.execute("INSERT INTO bitten_step (build,name,description,status," "started,stopped) SELECT build,name,description,status," @@ -44,16 +45,18 @@ def add_recipe_to_config(env, db): """Add a column for storing the build recipe to the build configuration table.""" - from bitten.model import BuildConfig cursor = db.cursor() cursor.execute("CREATE TEMP TABLE old_config AS " "SELECT * FROM bitten_config") cursor.execute("DROP TABLE bitten_config") + + connector, _ = DatabaseManager(env)._get_connector() for table in BuildConfig._schema: - for stmt in schema_to_sql(env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) + cursor.execute("INSERT INTO bitten_config (name,path,active,recipe,min_rev," "max_rev,label,description) SELECT name,path,0,'',NULL," "NULL,label,description FROM old_config") @@ -112,8 +115,11 @@ cursor.execute("CREATE TEMP TABLE old_log AS " "SELECT * FROM bitten_log") cursor.execute("DROP TABLE bitten_log") - for stmt in schema_to_sql(env, db, BuildLog._schema[0]): + + connector, _ = DatabaseManager(env)._get_connector() + for stmt in connector.to_sql(BuildLog._schema[0]): cursor.execute(stmt) + cursor.execute("INSERT INTO bitten_log (id,build,step,generator,orderno) " "SELECT id,build,step,type,0 FROM old_log") @@ -122,8 +128,9 @@ from bitten.model import Report cursor = db.cursor() + connector, _ = DatabaseManager(env)._get_connector() for table in Report._schema: - for stmt in schema_to_sql(env, db, table): + for stmt in connector.to_sql(table): cursor.execute(stmt) def xmldb_to_db(env, db): @@ -267,7 +274,9 @@ Column('orderno', type='int') ] cursor = db.cursor() - for stmt in schema_to_sql(env, db, table): + + connector, _ = DatabaseManager(env)._get_connector() + for stmt in connector.to_sql(table): cursor.execute(stmt) map = { diff --git a/bitten/trac_ext/web_ui.py b/bitten/web_ui.py rename from bitten/trac_ext/web_ui.py rename to bitten/web_ui.py --- a/bitten/trac_ext/web_ui.py +++ b/bitten/web_ui.py @@ -31,12 +31,11 @@ from trac.web.chrome import INavigationContributor, ITemplateProvider, \ add_link, add_stylesheet from trac.wiki import wiki_to_html, wiki_to_oneliner +from bitten.api import ILogFormatter, IReportChartGenerator, IReportSummarizer from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, \ BuildLog, Report from bitten.queue import collect_changes from bitten.recipe import Recipe, InvalidRecipeError -from bitten.trac_ext.api import ILogFormatter, IReportChartGenerator, \ - IReportSummarizer from bitten.util import xmlio _status_label = {Build.PENDING: 'pending', diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -30,9 +30,9 @@ packages=find_packages(exclude=['*.tests*']), package_data={ - 'bitten.trac_ext': ['htdocs/*.*', - 'htdocs/charts_library/*.swf', - 'templates/*.cs'] + 'bitten': ['htdocs/*.*', + 'htdocs/charts_library/*.swf', + 'templates/*.cs'] }, test_suite='bitten.tests.suite', entry_points = { @@ -43,9 +43,9 @@ 'unittest = bitten.util.testrunner:unittest' ], 'trac.plugins': [ - 'bitten.main = bitten.trac_ext.main', + 'bitten.main = bitten.main', 'bitten.master = bitten.master', - 'bitten.web_ui = bitten.trac_ext.web_ui', + 'bitten.web_ui = bitten.web_ui', 'bitten.testing = bitten.report.testing', 'bitten.coverage = bitten.report.coverage' ],