Example #1
0
 def abs_href(self):
     """The application URL"""
     if not self.base_url:
         urlpattern = MultiProductSystem(self.parent).product_base_url
         if not urlpattern:
             self.log.warn("product_base_url option not set in "
                           "configuration, generated links may be "
                           "incorrect")
             urlpattern = 'products/$(prefix)s'
         envname = os.path.basename(self.parent.path)
         prefix = unicode_quote(self.product.prefix, safe="")
         name = unicode_quote(self.product.name, safe="")
         url = urlpattern.replace('$(', '%(') \
                         .replace('%(envname)s', envname) \
                         .replace('%(prefix)s', prefix) \
                         .replace('%(name)s', name)
         if urlsplit(url).netloc:
             #  Absolute URLs
             _abs_href = Href(url)
         else:
             # Relative URLs
             parent_href = Href(self.parent.abs_href(),
                                path_safe="/!~*'()%",
                                query_safe="!~*'()%")
             _abs_href = Href(parent_href(url))
     else:
         _abs_href = Href(self.base_url)
     return _abs_href
Example #2
0
    def test_missing_product(self):
        spy = self.global_env[TestRequestSpy]
        self.assertIsNot(None, spy)

        mps = MultiProductSystem(self.global_env)

        def assert_product_list(req, template, data, content_type):
            self.assertEquals('product_list.html', template)
            self.assertIs(None, content_type)
            self.assertEquals(
                [mps.default_product_prefix, self.default_product],
                [p.prefix for p in data.get('products')])
            self.assertTrue('context' in data)
            ctx = data['context']
            self.assertEquals('product', ctx.resource.realm)
            self.assertEquals(None, ctx.resource.id)

        spy.testProcessing = assert_product_list

        # Missing product
        req = self._get_request_obj(self.global_env)
        req.authname = 'testuser'
        req.environ['PATH_INFO'] = '/products/missing'

        self.expectedPrefix = 'missing'
        self.expectedPathInfo = ''
        with self.assertRaises(RequestDone):
            self._dispatch(req, self.global_env)
        self.assertEqual(1, len(req.chrome['warnings']))
        self.assertEqual('Product missing not found',
                         req.chrome['warnings'][0].unescape())
Example #3
0
 def _setup_multiproduct(self):
     try:
         MultiProductSystem(self.env)\
             .upgrade_environment(self.env.db_transaction)
     except self.env.db_exc.OperationalError:
         # table remains but content is deleted
         self._add_products('@')
     self.env.enable_multiproduct_schema()
Example #4
0
    def _default_product(self, envname=None):
        """Default product configured for a given environment

        @raise LookupError: if no environment matching `envname` can be found
        """
        if envname not in ('trac', None):
            raise LookupError('Unable to open environment ' + envname)
        env = self.get_trac_environment()
        return MultiProductSystem(env).default_product_prefix
Example #5
0
    def setup_config(self):
        """Load the configuration object.
        """
        import trac.config

        parent_path = MultiProductSystem(self.parent).product_config_parent
        if parent_path and os.path.isfile(parent_path):
            parents = [trac.config.Configuration(parent_path)]
        else:
            parents = [self.parent.config]
        self.config = Configuration(self.parent, self.product.prefix, parents)
        self.setup_log()
Example #6
0
    def test_can_upgrade_multi_product_from_v1(self):
        mp = MultiProductSystem(self.env)
        with self.env.db_direct_transaction as db:
            mp._add_column_product_to_ticket(db)
            mp._create_multiproduct_tables(db)
            mp._update_db_version(db, 1)

            db("""INSERT INTO bloodhound_product (prefix, name)
                       VALUES ('p1', 'Product 1')""")
            db("""INSERT INTO ticket (id, product)
                       VALUES (1, 'Product 1')""")

        self._enable_multiproduct()
        self.env.upgrade()

        with self.product('p1'):
            Ticket(self.env, 1)
Example #7
0
    def _upgrade_mp(cls, env):
        r"""Apply multi product upgrades
        """
        # Do not break wiki parser ( see #373 )
        env.disable_component(TicketModule)
        env.disable_component(ReportModule)

        mpsystem = MultiProductSystem(env)
        try:
            mpsystem.upgrade_environment(env.db_transaction)
        except OperationalError:
            # Database is upgraded, but database version was deleted.
            # Complete the upgrade by inserting default product.
            mpsystem._insert_default_product(env.db_transaction)
        # assume that the database schema has been upgraded, enable
        # multi-product schema support in environment
        env.enable_multiproduct_schema(True)
Example #8
0
    def open_environment(self, environ, env_path, global_env, use_cache=False):
        environ.setdefault('SCRIPT_NAME', '')  # bh:ticket:594

        env = pid = None
        path_info = environ.get('PATH_INFO')
        if not path_info:
            return env
        m = PRODUCT_RE.match(path_info)
        if m:
            pid = m.group('pid')

        def create_product_env(product_prefix, script_name, path_info):
            if not global_env._abs_href:
                # make sure global environment absolute href is set before
                # instantiating product environment. This would normally
                # happen from within trac.web.main.dispatch_request
                req = RequestWithSession(environ, None)
                global_env._abs_href = req.abs_href
            try:
                env = multiproduct.env.ProductEnvironment(
                    global_env, product_prefix)
            except LookupError:
                # bh:ticket:561 - Display product list and warning message
                env = global_env
            else:
                # shift WSGI environment to the left
                environ['SCRIPT_NAME'] = script_name
                environ['PATH_INFO'] = path_info
            return env

        if pid:
            env = create_product_env(
                pid, environ['SCRIPT_NAME'] + '/products/' + pid,
                m.group('pathinfo') or '')
        else:
            redirect = REDIRECT_DEFAULT_RE.match(path_info)
            if redirect:
                from multiproduct.api import MultiProductSystem
                default_product_prefix = \
                    MultiProductSystem(global_env).default_product_prefix
                env = create_product_env(default_product_prefix,
                                         environ['SCRIPT_NAME'],
                                         environ['PATH_INFO'])
        return env
Example #9
0
    def _upgrade_mp(cls, env):
        r"""Apply multi product upgrades
        """
        # Do not break wiki parser ( see #373 )
        EnvironmentStub.disable_component_in_config(env, TicketModule)
        EnvironmentStub.disable_component_in_config(env, ReportModule)

        mpsystem = MultiProductSystem(env)
        with env.db_transaction as db:
            try:
                mpsystem.upgrade_environment(db)
            except env.db_exc.OperationalError:
                # Database is upgraded, but database version was deleted.
                # Complete the upgrade by inserting default product.
                mpsystem._insert_default_product(db)
            finally:
                # Ensure that multiproduct DB version is set to latest value
                mpsystem._update_db_version(db, DB_VERSION)
        # assume that the database schema has been upgraded, enable
        # multi-product schema support in environment
        env.enable_multiproduct_schema(True)
Example #10
0
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
        self.env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')

        self.mpsystem = MultiProductSystem(self.env)
        try:
            self.mpsystem.upgrade_environment(self.env.db_transaction)
        except self.env.db_exc.OperationalError:
            # table remains but database version is deleted
            pass

        self.listener = self._enable_resource_change_listener()
        self.default_data = {
            'prefix': self.INITIAL_PREFIX,
            'name': self.INITIAL_NAME,
            'description': self.INITIAL_DESCRIPTION
        }

        self.global_env = self.env
        self.product = Product(self.env)
        self.product._data.update(self.default_data)
        self.product.insert()
Example #11
0
    def test_upgrade_copies_content_of_system_tables_to_all_products(self):
        mp = MultiProductSystem(self.env)
        with self.env.db_direct_transaction as db:
            mp._add_column_product_to_ticket(db)
            mp._create_multiproduct_tables(db)
            mp._update_db_version(db, 1)
            for i in range(1, 6):
                db("""INSERT INTO bloodhound_product (prefix, name)
                           VALUES ('p%d', 'Product 1')""" % i)
            for table in ('component', 'milestone', 'enum', 'version',
                          'permission', 'report'):
                db("""DELETE FROM %s""" % table)
            db("""INSERT INTO component (name) VALUES ('foobar')""")
            db("""INSERT INTO milestone (name) VALUES ('foobar')""")
            db("""INSERT INTO version (name) VALUES ('foobar')""")
            db("""INSERT INTO enum (type, name) VALUES ('a', 'b')""")
            db("""INSERT INTO permission VALUES ('x', 'TICKET_VIEW')""")
            db("""INSERT INTO report (title) VALUES ('x')""")

        self._enable_multiproduct()
        self.env.upgrade()

        with self.env.db_direct_transaction as db:
            for table in ('component', 'milestone', 'version', 'enum',
                          'report'):
                rows = db("SELECT * FROM %s" % table)
                self.assertEqual(
                    len(rows), 6,
                    "Wrong number of lines in %s (%d instead of %d)\n%s" %
                    (table, len(rows), 6, rows))
            for table in ('permission', ):
                # Permissions also hold rows for global product.
                rows = db("SELECT * FROM %s WHERE username='******'" % table)
                self.assertEqual(
                    len(rows), 7,
                    "Wrong number of lines in %s (%d instead of %d)\n%s" %
                    (table, len(rows), 7, rows))
Example #12
0
    def test_product_list(self):
        spy = self.global_env[TestRequestSpy]
        self.assertIsNot(None, spy)

        req = self._get_request_obj(self.global_env)
        req.authname = 'testuser'
        req.environ['PATH_INFO'] = '/products'

        mps = MultiProductSystem(self.global_env)

        def assert_product_list(req, template, data, content_type):
            self.assertEquals('product_list.html', template)
            self.assertIs(None, content_type)
            self.assertEquals(
                [mps.default_product_prefix, self.default_product],
                [p.prefix for p in data.get('products')])
            self.assertTrue('context' in data)
            ctx = data['context']
            self.assertEquals('product', ctx.resource.realm)
            self.assertEquals(None, ctx.resource.id)

        spy.testProcessing = assert_product_list
        with self.assertRaises(RequestDone):
            self._dispatch(req, self.global_env)