Example #1
0
 def _do_product_add(self, prefix, owner, name):
     product = Product(self.env)
     product._data.update({'prefix': prefix, 'name': name, 'owner': owner})
     try:
         product.insert()
     except TracError, exc:
         raise AdminCommandError(to_unicode(exc))
Example #2
0
    def test_delete(self):
        """test that we are able to delete Products"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        post = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(0, len(post))
Example #3
0
 def test_delete(self):
     """test that we are able to delete Products"""
     product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     product.delete()
     
     post = list(Product.select(self.env, where={'prefix':'tp'}))
     self.assertEqual(0, len(post))
Example #4
0
 def _do_product_add(self, prefix, owner, name):
     product = Product(self.env)
     product._data.update({'prefix':prefix, 'name':name, 'owner':owner})
     try:
         product.insert()
     except TracError, exc:
         raise AdminCommandError(to_unicode(exc))
Example #5
0
    def test_get_tickets(self):
        for pdata in (
            {'prefix': 'p2', 'name':'product, too', 'description': ''},
            {'prefix': 'p3', 'name':'strike three', 'description': ''},
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [(t['product'], t['id']) for t in
                Product.get_tickets(self.global_env, product.prefix)]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id']) for t in
                Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Example #6
0
    def _do_save(self, req, product):
        """common processing for product save events"""
        req.perm.require('PRODUCT_VIEW')

        name = req.args.get('name')
        prefix = req.args.get('prefix')
        description = req.args.get('description', '')

        owner = req.args.get('owner') or req.authname
        keys = {'prefix': prefix}
        field_data = {'name': name,
                      'description': description,
                      'owner': owner,
                      }

        warnings = []
        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        if product._exists:
            if name != product.name and Product.select(self.env,
                                                       where={'name': name}):
                warn(_('A product with name "%(name)s" already exists, please '
                       'choose a different name.', name=name))
            elif not name:
                warn(_('You must provide a name for the product.'))
            else:
                req.perm.require('PRODUCT_MODIFY')
                product.update_field_dict(field_data)
                product.update(req.authname)
                add_notice(req, _('Your changes have been saved.'))
        else:
            req.perm.require('PRODUCT_CREATE')

            if not prefix:
                warn(_('You must provide a prefix for the product.'))
            elif Product.select(self.env, where={'prefix': prefix}):
                warn(_('Product "%(id)s" already exists, please choose another '
                       'prefix.', id=prefix))
            if not name:
                warn(_('You must provide a name for the product.'))
            elif Product.select(self.env, where={'name': name}):
                warn(_('A product with name "%(name)s" already exists, please '
                       'choose a different name.', name=name))

            if not warnings:
                prod = Product(self.env)
                prod.update_field_dict(keys)
                prod.update_field_dict(field_data)
                prod.insert()
                add_notice(req, _('The product "%(id)s" has been added.',
                                  id=prefix))

        if warnings:
            product.update_field_dict(keys)
            product.update_field_dict(field_data)
            return self._render_editor(req, product)
        req.redirect(req.href.products(prefix))
Example #7
0
 def _load_product_from_data(cls, env, prefix):
     r"""Ensure test product with prefix is loaded
     """
     # TODO: Use fixtures implemented in #314
     product_data = cls.PRODUCT_DATA[prefix]
     prefix = to_unicode(prefix)
     product = Product(env)
     product._data.update(product_data)
     product.insert()
Example #8
0
 def _load_product_from_data(cls, env, prefix):
     r"""Ensure test product with prefix is loaded
     """
     # TODO: Use fixtures implemented in #314
     product_data = cls.PRODUCT_DATA[prefix]
     prefix = to_unicode(prefix)
     product = Product(env)
     product._data.update(product_data)
     product.insert()
Example #9
0
    def test_creating_new_product_calls_environment_created(self):
        self._enable_component(DummyPlugin)
        self._enable_multiproduct()
        self.env.upgrade()

        prod = Product(self.env)
        prod.update_field_dict(dict(prefix='p1'))
        ProductEnvironment(self.env, prod, create=True)
        with self.env.db_direct_transaction as db:
            db('SELECT * FROM "p1_dummy_table"')
Example #10
0
    def test_creating_new_product_calls_environment_created(self):
        self._enable_component(DummyPlugin)
        self._enable_multiproduct()
        self.env.upgrade()

        prod = Product(self.env)
        prod.update_field_dict(dict(prefix='p1'))
        ProductEnvironment(self.env, prod, create=True)
        with self.env.db_direct_transaction as db:
            db('SELECT * FROM "p1_dummy_table"')
Example #11
0
    def test_select(self):
        """tests that select can search Products by fields"""

        p2_data = {'prefix':'tp2',
                   'name':'test project 2',
                   'description':'a different test project'}
        p3_data = {'prefix':'tp3',
                   'name':'test project 3',
                   'description':'test project'}

        product2 = Product(self.env)
        product2._data.update(p2_data)
        product3 = Product(self.env)
        product3._data.update(p3_data)

        product2.insert()
        product3.insert()

        products = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'name':'test project'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'prefix':'tp3', 'name':'test project 3'}))
        self.assertEqual(1, len(products))
Example #12
0
 def test_insert(self):
     """test saving new Product"""
     data = {'prefix':'new', 'name':'new', 'description':'new'}
     product = Product(self.env)
     product._data.update(data)
     product.insert()
     
     check_products = list(Product.select(self.env, where={'prefix':'new'}))
     
     self.assertEqual(product._data['prefix'],
                      check_products[0]._data['prefix'])
     self.assertEqual(1, len(check_products))
Example #13
0
    def test_insert(self):
        """test saving new Product"""
        data = {'prefix':'new', 'name':'new', 'description':'new'}
        product = Product(self.env)
        product._data.update(data)
        product.insert()

        check_products = list(Product.select(self.env, where={'prefix':'new'}))

        self.assertEqual(product._data['prefix'],
                         check_products[0]._data['prefix'])
        self.assertEqual(1, len(check_products))
Example #14
0
 def test_update(self):
     """tests that we can use update to push data to the database"""
     product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     self.assertEqual('test project', product._data['name'])
     
     new_data = {'prefix':'tp', 
                 'name':'updated', 
                 'description':'nothing'}
     product._data.update(new_data)
     product.update()
     
     comp_product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     self.assertEqual('updated', comp_product._data['name'])
Example #15
0
    def test_update(self):
        """tests that we can use update to push data to the database"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('test project', product._data['name'])

        new_data = {'prefix':'tp',
                    'name':'updated',
                    'description':'nothing'}
        product._data.update(new_data)
        product.update()

        comp_product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('updated', comp_product._data['name'])
Example #16
0
    def process_request(self, req):
        """process request handler"""

        req.perm.require('PRODUCT_VIEW')
        pid = req.args.get('productid', None)
        if pid:
            req.perm('product', pid).require('PRODUCT_VIEW')

        try:
            product = Product(self.env, {'prefix': pid})
        except ResourceNotFound:
            product = Product(self.env)

        path_info = req.args.get('pathinfo')
        if path_info and path_info != '/':
            if not product._exists:
                # bh:ticket:561 - Display product list and warning message
                if pid:
                    add_warning(req, _("Product %(pid)s not found", pid=pid))
                return self._render_list(req)
            else:
                raise HTTPNotFound(
                    _('Unable to render product page. Wrong setup?'))

        if pid:
            add_link(req, 'up', req.href.products(), _('Products'))

        action = req.args.get('action', 'view')
        if req.method == 'POST':
            if 'cancel' in req.args:
                req.redirect(req.href.products(product.prefix))
            elif action == 'edit':
                return self._do_save(req, product)
            elif action == 'delete':
                raise TracError(_('Product removal is not allowed!'))
        elif action in ('new', 'edit'):
            return self._render_editor(req, product)
        elif action == 'delete':
            raise TracError(_('Product removal is not allowed!'))

        if not product._exists:
            if pid:
                # bh:ticket:561 - Display product list and warning message
                add_warning(req, _("Product %(pid)s not found", pid=pid))
            return self._render_list(req)

        data = {
            'product': product,
            'context': web_context(req, product.resource)
        }
        return 'product_view.html', data, None
Example #17
0
    def lookup_env(cls, env, prefix=None, name=None):
        """Instantiate environment according to product prefix or name

        @throws LookupError if no product matches neither prefix nor name
        """
        if isinstance(env, ProductEnvironment):
            global_env = env.parent
        else:
            global_env = env

        # FIXME: Update if multiproduct.dbcursor.GLOBAL_PRODUCT != ''
        if not prefix and not name:
            return global_env
        elif isinstance(env, ProductEnvironment) and \
                env.product.prefix == prefix:
            return env
        if prefix:
            try:
                return ProductEnvironment(global_env, prefix)
            except LookupError:
                if not name:
                    raise
        if name:
            # Lookup product by name
            products = Product.select(global_env, where={'name' : name})
            if products:
                return ProductEnvironment(global_env, products[0])
            else:
                raise LookupError("Missing product '%s'" % (name,))
        else:
            raise LookupError("Mising product '%s'" % (prefix or name,))
Example #18
0
    def test_product_edit(self):
        spy = self.global_env[TestRequestSpy]
        self.assertIsNot(None, spy)

        # HTTP GET
        req = self._get_request_obj(self.global_env)
        req.authname = 'testuser'
        req.environ['PATH_INFO'] = '/products/%s' % (self.default_product, )
        req.environ['QUERY_STRING'] = 'action=edit'

        real_prefix = self.default_product

        def assert_product_edit(req, template, data, content_type):
            self.assertEquals('product_edit.html', template)
            self.assertIs(None, content_type)
            self.assertFalse('products' in data)

            self.assertTrue('context' in data)
            ctx = data['context']
            self.assertEquals('product', ctx.resource.realm)
            self.assertEquals(real_prefix, ctx.resource.id)

            self.assertTrue('product' in data)
            self.assertEquals(real_prefix, data['product'].prefix)

        spy.testProcessing = assert_product_edit

        self.expectedPrefix = self.default_product
        self.expectedPathInfo = ''
        with self.assertRaises(RequestDone):
            self._dispatch(req, self.global_env)

        # HTTP POST
        req = self._get_request_obj(self.global_env)
        req.authname = 'testuser'
        req.environ['REQUEST_METHOD'] = 'POST'
        req.environ['PATH_INFO'] = '/products/%s' % (self.default_product, )
        req.args = dict(action='edit',
                        description='New description',
                        prefix=self.default_product,
                        name=self.env.product.name)

        spy.testProcessing = assert_product_edit

        self.expectedPrefix = self.default_product
        self.expectedPathInfo = ''
        self.record_response = True
        with self.assertRaises(RequestDone):
            self._dispatch(req, self.global_env)

        try:
            product = Product(self.global_env,
                              {'prefix': self.env.product.prefix})
        except ResourceNotFound:
            self.fail('Default test product deleted ?')
        else:
            self.assertEquals('New description', product.description)

        product_url = Href(req.base_path).products(self.default_product)
        self.assertRedirect(req, product_url)
Example #19
0
    def find_ticket(self, ticket_spec):
        ticket = None
        m = re.match(r'#?(?P<tid>\d+)', ticket_spec)
        if m:
            tid = m.group('tid')
            try:
                ticket = Ticket(self.env, tid)
            except ResourceNotFound:
                # ticket not found in current product, try all other products
                for p in Product.select(self.env):
                    if p.prefix != self.env.product.prefix:
                        # TODO: check for PRODUCT_VIEW permissions
                        penv = ProductEnvironment(self.env.parent, p.prefix)
                        try:
                            ticket = Ticket(penv, tid)
                        except ResourceNotFound:
                            pass
                        else:
                            break

        # ticket still not found, use fallback for <prefix>:ticket:<id> syntax
        if ticket is None:
            try:
                resource = ResourceIdSerializer.get_resource_by_id(ticket_spec)
                ticket = self._create_ticket_by_full_id(resource)
            except:
                raise NoSuchTicketError
        return ticket
Example #20
0
    def lookup_env(cls, env, prefix=None, name=None):
        """Instantiate environment according to product prefix or name

        @throws LookupError if no product matches neither prefix nor name 
        """
        if isinstance(env, ProductEnvironment):
            global_env = env.parent
        else:
            global_env = env

        # FIXME: Update if multiproduct.dbcursor.GLOBAL_PRODUCT != ''
        if not prefix and not name:
            return global_env
        elif isinstance(env, ProductEnvironment) and \
                env.product.prefix == prefix:
            return env
        if prefix:
            try:
                return ProductEnvironment(global_env, prefix)
            except LookupError:
                if not name:
                    raise
        if name:
            # Lookup product by name
            products = Product.select(global_env, where={'name': name})
            if products:
                return ProductEnvironment(global_env, products[0])
            else:
                raise LookupError("Missing product '%s'" % (name, ))
        else:
            raise LookupError("Mising product '%s'" % (prefix or name, ))
Example #21
0
    def test_set_table_field(self):
        """tests that table.field style update works"""
        test = {'prefix': 'td',
                'name': 'test field access',
                'description': 'product to test field setting'}

        product = Product(self.env)

        # attempt to set the fields from the data
        product.prefix = test['prefix']
        product.name = test['name']
        product.description = test['description']

        self.assertEqual(product._data['prefix'], test['prefix'])
        self.assertEqual(product._data['name'], test['name'])
        self.assertEqual(product._data['description'], test['description'])
Example #22
0
    def find_ticket(self, ticket_spec):
        ticket = None
        m = re.match(r'#?(?P<tid>\d+)', ticket_spec)
        if m:
            tid = m.group('tid')
            try:
                ticket = Ticket(self.env, tid)
            except ResourceNotFound:
                # ticket not found in current product, try all other products
                for p in Product.select(self.env):
                    if p.prefix != self.env.product.prefix:
                        # TODO: check for PRODUCT_VIEW permissions
                        penv = ProductEnvironment(self.env.parent, p.prefix)
                        try:
                            ticket = Ticket(penv, tid)
                        except ResourceNotFound:
                            pass
                        else:
                            break

        # ticket still not found, use fallback for <prefix>:ticket:<id> syntax
        if ticket is None:
            try:
                resource = ResourceIdSerializer.get_resource_by_id(ticket_spec)
                ticket = self._create_ticket_by_full_id(resource)
            except:
                raise NoSuchTicketError
        return ticket
Example #23
0
 def test_insert_duplicate_key(self):
     """test attempted saving of Product with existing key fails"""
     dupe_key_data = {'prefix':'tp',
                      'name':'dupe',
                      'description':'dupe primary key'}
     product2 = Product(self.env)
     product2._data.update(dupe_key_data)
     self.assertRaises(TracError, product2.insert)
Example #24
0
 def test_field_set(self):
     """tests that we can use table.field = something to set field data"""
     prefix = self.default_data['prefix']
     product = list(Product.select(self.env, where={'prefix':prefix}))[0]
     
     new_description = 'test change of description'
     product.description = new_description
     self.assertEqual(new_description, product.description)
Example #25
0
 def test_update_key_change(self):
     """tests that we raise an error for attempting to update key fields"""
     bad_data = {'prefix':'tp0', 
                 'name':'update', 
                 'description':'nothing'}
     product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     product._data.update(bad_data)
     self.assertRaises(TracError, product.update)
Example #26
0
    def test_field_set(self):
        """tests that we can use table.field = something to set field data"""
        prefix = self.default_data['prefix']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]

        new_description = 'test change of description'
        product.description = new_description
        self.assertEqual(new_description, product.description)
Example #27
0
 def test_update_key_change(self):
     """tests that we raise an error for attempting to update key fields"""
     bad_data = {'prefix':'tp0',
                 'name':'update',
                 'description':'nothing'}
     product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
     product._data.update(bad_data)
     self.assertRaises(TracError, product.update)
Example #28
0
 def _render_list(self, req):
     """products list"""
     products = [p for p in Product.select(self.env)
                 if 'PRODUCT_VIEW' in req.perm(Neighborhood('product',
                                                            p.prefix))]
     data = {'products': products,
             'context': web_context(req, Resource('product', None))}
     return 'product_list.html', data, None
Example #29
0
    def test_insert_into_multiple_products(self):
        # UIDs are global, autoincremented
        # IDs are product-scoped, incremented in the SQL translator
        self.env = ProductEnvironment(self.global_env, self.default_product)

        tid = self._insert_ticket('hello kitty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 1)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello kitteh', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 2)
        self.assertEqual(ticket.id, tid)

        p2 = Product(self.global_env)
        p2.prefix = 'p2'
        p2.name = 'product, too'
        p2.owner = 'admin'
        p2.insert()
        self.env = ProductEnvironment(self.global_env, p2)

        tid = self._insert_ticket('hello catty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 3)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello ocelot', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 4)
        self.assertEqual(ticket.id, tid)
Example #30
0
 def setUp(self):
     self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
     self.env.path = tempfile.mkdtemp('bh-product-tempenv')
     
     self.envprovider = MultiProductEnvironmentProvider(self.env)
     try:
         self.envprovider.upgrade_environment(self.env.db_transaction)
     except OperationalError:
         # table remains but database version is deleted
         pass
     
     self.default_data = {'prefix':'tp',
                          'name':'test project',
                          'description':'a test project'}
     
     product = Product(self.env)
     product._data.update(self.default_data)
     product.insert()
Example #31
0
    def test_set_table_field(self):
        """tests that table.field style update works"""
        test = {
            'prefix': 'td',
            'name': 'test field access',
            'description': 'product to test field setting'
        }

        product = Product(self.env)

        # attempt to set the fields from the data
        product.prefix = test['prefix']
        product.name = test['name']
        product.description = test['description']

        self.assertEqual(product._data['prefix'], test['prefix'])
        self.assertEqual(product._data['name'], test['name'])
        self.assertEqual(product._data['description'], test['description'])
Example #32
0
 def test_field_data_get(self):
     """tests that we can use table.field syntax to get to the field data"""
     prefix = self.default_data['prefix']
     name = self.default_data['name']
     description = self.default_data['description']
     product = list(Product.select(self.env, where={'prefix':prefix}))[0]
     self.assertEqual(prefix, product.prefix)
     self.assertEqual(name, product.name)
     self.assertEqual(description, product.description)
Example #33
0
 def test_field_data_get(self):
     """tests that we can use table.field syntax to get to the field data"""
     prefix = self.default_data['prefix']
     name = self.default_data['name']
     description = self.default_data['description']
     product = list(Product.select(self.env, where={'prefix':prefix}))[0]
     self.assertEqual(prefix, product.prefix)
     self.assertEqual(name, product.name)
     self.assertEqual(description, product.description)
Example #34
0
    def test_migrating_to_multiproduct_with_custom_default_prefix(self):
        ticket = self.insert_ticket('ticket')

        self.env.config.set('multiproduct', 'default_product_prefix', 'xxx')
        self._enable_multiproduct()
        self.env.upgrade()

        products = Product.select(self.env)
        self.assertEqual(len(products), 1)
        self.assertEqual(products[0].prefix, 'xxx')
Example #35
0
    def test_migrating_to_multiproduct_with_custom_default_prefix(self):
        ticket = self.insert_ticket('ticket')

        self.env.config.set('multiproduct', 'default_product_prefix', 'xxx')
        self._enable_multiproduct()
        self.env.upgrade()

        products = Product.select(self.env)
        self.assertEqual(len(products), 1)
        self.assertEqual(products[0].prefix, 'xxx')
Example #36
0
 def _render_list(self, req):
     """products list"""
     products = [p for p in Product.select(self.env)
                 if 'PRODUCT_VIEW' in req.perm(Neighborhood('product',
                                                            p.prefix))]
     map(lambda p: setattr(p, 'href', resolve_product_href(
         lookup_product_env(self.env, p.prefix), self.env)), products)
     data = {'products': products,
             'context': web_context(req, Resource('product', None))}
     return 'product_list.html', data, None
Example #37
0
 def _render_list(self, req):
     """products list"""
     products = [
         p for p in Product.select(self.env)
         if 'PRODUCT_VIEW' in req.perm(Neighborhood('product', p.prefix))
     ]
     data = {
         'products': products,
         'context': web_context(req, Resource('product', None))
     }
     return 'product_list.html', data, None
Example #38
0
    def test_insert_into_multiple_products(self):
        # UIDs are global, autoincremented
        # IDs are product-scoped, incremented in the SQL translator
        self.env = ProductEnvironment(self.global_env, self.default_product)

        tid = self._insert_ticket('hello kitty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 1)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello kitteh', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 2)
        self.assertEqual(ticket.id, tid)

        p2 = Product(self.global_env)
        p2.prefix = 'p2'
        p2.name = 'product, too'
        p2.owner = 'admin'
        p2.insert()
        self.env = ProductEnvironment(self.global_env, p2)

        tid = self._insert_ticket('hello catty', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 1)
        self.assertEqual(self._get_ticket_uid(tid), 3)
        self.assertEqual(ticket.id, tid)
        tid = self._insert_ticket('hello ocelot', reporter='admin')
        ticket = Ticket(self.env, tid)
        self.assertEqual(tid, 2)
        self.assertEqual(self._get_ticket_uid(tid), 4)
        self.assertEqual(ticket.id, tid)
Example #39
0
 def get_product_list(cls, env, req, href_fcn=None):
     """Returns a list of products as (prefix, name, url) tuples
     """
     if href_fcn is None:
         href_fcn = req.href.products
     product_list = []
     for product in Product.select(env):
         if 'PRODUCT_VIEW' in req.perm(Neighborhood('product',
                                                    product.prefix).
                                       child(product.resource)):
             product_list.append((product.prefix, product.name,
                                  href_fcn(product.prefix)))
     return product_list
Example #40
0
 def manager_exists(self, neighborhood):
     """Check whether the target environment exists physically.
     """
     if neighborhood._realm == 'global':
         # Global environment
         return isinstance(self.env, (Environment, ProductEnvironment))
     elif neighborhood._realm == 'product':
         prefix = neighborhood._id
         if not prefix:
             # Global environment
             return True
         return Product(lookup_product_env(self.env, GLOBAL_PRODUCT),
                        {'prefix' : prefix})._exists
Example #41
0
 def get_product_list(cls, env, req, href_fcn=None):
     """Returns a list of products as (prefix, name, url) tuples
     """
     if href_fcn is None:
         href_fcn = req.href.products
     product_list = []
     for product in Product.select(env):
         if 'PRODUCT_VIEW' in req.perm(
                 Neighborhood('product',
                              product.prefix).child(product.resource)):
             product_list.append(
                 (product.prefix, product.name, href_fcn(product.prefix)))
     return product_list
Example #42
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 #43
0
 def _render_list(self, req):
     """products list"""
     products = [
         p for p in Product.select(self.env)
         if 'PRODUCT_VIEW' in req.perm(Neighborhood('product', p.prefix))
     ]
     map(
         lambda p: setattr(
             p, 'href',
             resolve_product_href(lookup_product_env(self.env, p.prefix),
                                  self.env)), products)
     data = {
         'products': products,
         'context': web_context(req, Resource('product', None))
     }
     return 'product_list.html', data, None
Example #44
0
    def pre_process_request(self, req, handler):
        """pre process request filter"""
        pid = None
        match = PRODUCT_RE.match(req.path_info)
        if match:
            dispatcher = self.env[RequestDispatcher]
            if dispatcher is None:
                raise TracError('Unable to load RequestDispatcher.')
            pid = match.group('pid')

        if pid:
            products = Product.select(self.env, where={'prefix': pid})
            if pid and len(products) == 1:
                req.args['productid'] = pid
                req.args['product'] = products[0].name
                if handler is self and match.group('pathinfo') not in ('',
                                                                       '/'):
                    # select a new handler
                    environ = req.environ.copy()
                    pathinfo = environ['PATH_INFO'].split('/')
                    pathinfo = '/'.join(pathinfo[:1] + pathinfo[3:])
                    environ['PATH_INFO'] = pathinfo
                    newreq = Request(environ, lambda *args, **kwds: None)

                    new_handler = None
                    for hndlr in dispatcher.handlers:
                        if hndlr is not self and hndlr.match_request(newreq):
                            new_handler = hndlr
                            req.args.update(newreq.args)
                            break
                    if new_handler is None:
                        if req.path_info.endswith('/'):
                            target = req.path_info.rstrip('/').encode('utf-8')
                            if req.query_string:
                                target += '?' + req.query_string
                            req.redirect(req.href + target, permanent=True)
                        raise HTTPNotFound('No handler matched request to %s',
                                           req.path_info)
                    handler = new_handler
            else:
                raise ResourceNotFound(
                    _("Product %(id)s does not exist.", id=pid),
                    _("Invalid product id"))

        return handler
Example #45
0
 def pre_process_request(self, req, handler):
     """pre process request filter"""
     pid = None
     match = PRODUCT_RE.match(req.path_info)
     if match:
         dispatcher = self.env[RequestDispatcher]
         if dispatcher is None:
             raise TracError('Unable to load RequestDispatcher.')
         pid = match.group('pid')
     
     if pid:
         products = Product.select(self.env, where={'prefix': pid})
         if pid and len(products) == 1:
             req.args['productid'] = pid
             req.args['product'] = products[0].name
             if handler is self and match.group('pathinfo') not in ('', '/'):
                 # select a new handler
                 environ = req.environ.copy()
                 pathinfo = environ['PATH_INFO'].split('/')
                 pathinfo = '/'.join(pathinfo[:1] + pathinfo[3:])
                 environ['PATH_INFO'] = pathinfo
                 newreq = Request(environ, lambda *args, **kwds: None)
                 
                 new_handler = None
                 for hndlr in dispatcher.handlers:
                     if hndlr is not self and hndlr.match_request(newreq):
                         new_handler = hndlr
                         req.args.update(newreq.args)
                         break
                 if new_handler is None:
                     if req.path_info.endswith('/'):
                         target = req.path_info.rstrip('/').encode('utf-8')
                         if req.query_string:
                             target += '?' + req.query_string
                         req.redirect(req.href + target, permanent=True)
                     raise HTTPNotFound('No handler matched request to %s',
                                        req.path_info)
                 handler = new_handler
         else:
             raise ResourceNotFound(_("Product %(id)s does not exist.", 
                                      id=pid), _("Invalid product id"))
     
     return handler
Example #46
0
 def setUp(self):
     self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
     self.env.path = tempfile.mkdtemp('bh-product-tempenv')
     
     self.mpsystem = MultiProductSystem(self.env)
     try:
         self.mpsystem.upgrade_environment(self.env.db_transaction)
     except 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.product = Product(self.env)
     self.product._data.update(self.default_data)
     self.product.insert()
Example #47
0
    def process_request(self, req):
        """Override for TicketModule process_request"""
        ticketid = req.args.get('id')
        productid = req.args.get('productid', '')

        if not ticketid:
            # if /newticket is executed in global scope (from QCT), redirect
            # the request to /products/<first_product_in_DB>/newticket
            if not productid and \
                    not isinstance(self.env, ProductEnvironment):
                default_product = self.env.config.get('ticket',
                                                      'default_product')
                products = Product.select(self.env, {'fields': ['prefix']})
                prefixes = [prod.prefix for prod in products]
                if not default_product or default_product not in prefixes:
                    default_product = products[0].prefix
                req.redirect(req.href.products(default_product, 'newticket'))

            return self._process_newticket_request(req)

        if req.path_info in ('/newticket', '/products'):
            raise TracError(_("id can't be set for a new ticket request."))

        if isinstance(self.env, ProductEnvironment):
            ticket = Ticket(self.env, ticketid)
            if productid and ticket['product'] != productid:
                msg = "Ticket %(id)s in product '%(prod)s' does not exist."
                raise ResourceNotFound(_(msg, id=ticketid, prod=productid),
                                       _("Invalid ticket number"))
            return self._process_ticket_request(req)

        # executed in global scope -> assume ticketid=UID, redirect to product
        with self.env.db_direct_query as db:
            rows = db("""SELECT id,product FROM ticket WHERE uid=%s""",
                      (ticketid, ))
            if not rows:
                msg = "Ticket with uid %(uid)s does not exist."
                raise ResourceNotFound(_(msg, uid=ticketid),
                                       _("Invalid ticket number"))
            tid, prefix = rows[0]
            req.redirect(req.href.products(prefix, 'ticket', tid))
Example #48
0
    def process_request(self, req):
        """Override for TicketModule process_request"""
        ticketid = req.args.get('id')
        productid = req.args.get('productid', '')

        if not ticketid:
            # if /newticket is executed in global scope (from QCT), redirect
            # the request to /products/<first_product_in_DB>/newticket
            if not productid and \
                    not isinstance(self.env, ProductEnvironment):
                default_product = self.env.config.get('ticket',
                                                      'default_product')
                products = Product.select(self.env, {'fields': ['prefix']})
                prefixes = [prod.prefix for prod in products]
                if not default_product or default_product not in prefixes:
                    default_product = products[0].prefix
                req.redirect(req.href.products(default_product, 'newticket'))

            return self._process_newticket_request(req)

        if req.path_info in ('/newticket', '/products'):
            raise TracError(_("id can't be set for a new ticket request."))

        if isinstance(self.env, ProductEnvironment):
            ticket = Ticket(self.env, ticketid)
            if productid and ticket['product'] != productid:
                msg = "Ticket %(id)s in product '%(prod)s' does not exist."
                raise ResourceNotFound(_(msg, id=ticketid, prod=productid),
                                       _("Invalid ticket number"))
            return self._process_ticket_request(req)

        # executed in global scope -> assume ticketid=UID, redirect to product
        with self.env.db_direct_query as db:
            rows = db("""SELECT id,product FROM ticket WHERE uid=%s""",
                      (ticketid,))
            if not rows:
                msg = "Ticket with uid %(uid)s does not exist."
                raise ResourceNotFound(_(msg, uid=ticketid),
                                       _("Invalid ticket number"))
            tid, prefix = rows[0]
            req.redirect(req.href.products(prefix, 'ticket', tid))
Example #49
0
    def _render_link(self, context, name, label, extra='', prefix=None):
        """Render link to product page.
        """
        product_env = product = None
        env = self.env
        if isinstance(env, ProductEnvironment):
            if (prefix is not None and env.product.prefix == prefix) \
                    or (prefix is None and env.name == name):
                product_env = env
            env = env.parent
        try:
            if product_env is None:
                if prefix is not None:
                    product_env = ProductEnvironment(env, to_unicode(prefix))
                else:
                    product = Product.select(env,
                                             where={'name' : to_unicode(name)})
                    if not product:
                        raise LookupError("Missing product")
                    product_env = ProductEnvironment(env,
                                                     to_unicode(product[0]))
        except LookupError:
            pass

        if product_env is not None:
            product = product_env.product
            href = resolve_product_href(to_env=product_env, at_env=self.env)
            if 'PRODUCT_VIEW' in context.perm(product.resource):
                return tag.a(label, class_='product', href=href() + extra,
                             title=product.name)
        if 'PRODUCT_CREATE' in context.perm('product', name):
            params = [('action', 'new')]
            if prefix:
                params.append( ('prefix', prefix) )
            if name:
                params.append( ('name', name) )
            return tag.a(label, class_='missing product',
                    href=env.href('products', params),
                    rel='nofollow')
        return tag.a(label, class_='missing product')
Example #50
0
    def _render_link(self, context, name, label, extra='', prefix=None):
        """Render link to product page.
        """
        product_env = product = None
        env = self.env
        if isinstance(env, ProductEnvironment):
            if (prefix is not None and env.product.prefix == prefix) \
                    or (prefix is None and env.name == name):
                product_env = env
            env = env.parent
        try:
            if product_env is None:
                if prefix is not None:
                    product_env = ProductEnvironment(env, to_unicode(prefix))
                else:
                    product = Product.select(env,
                                             where={'name' : to_unicode(name)})
                    if not product:
                        raise LookupError("Missing product")
                    product_env = ProductEnvironment(env,
                                                     to_unicode(product[0]))
        except LookupError:
            pass

        if product_env is not None:
            product = product_env.product
            href = resolve_product_href(to_env=product_env, at_env=self.env)
            if 'PRODUCT_VIEW' in context.perm(product.resource):
                return tag.a(label, class_='product', href=href() + extra,
                             title=product.name)
        if 'PRODUCT_CREATE' in context.perm('product', name):
            params = [('action', 'new')]
            if prefix:
                params.append( ('prefix', prefix) )
            if name:
                params.append( ('name', name) )
            return tag.a(label, class_='missing product',
                    href=env.href('products', params),
                    rel='nofollow')
        return tag.a(label, class_='missing product')
Example #51
0
    def __init__(self, env, product, create=False):
        """Initialize the product environment.

        :param env:     the global Trac environment
        :param product: product prefix or an instance of
                        multiproduct.model.Product
        """
        if not isinstance(env, trac.env.Environment):
            cls = self.__class__
            raise TypeError("Initializer must be called with " \
                "trac.env.Environment instance as first argument " \
                "(got %s instance instead)" %
                         (cls.__module__ + '.' + cls.__name__, ))

        ComponentManager.__init__(self)

        if isinstance(product, Product):
            if product._env is not env:
                raise ValueError("Product's environment mismatch")
        elif isinstance(product, basestring):
            products = Product.select(env, where={'prefix': product})
            if len(products) == 1 :
                product = products[0]
            else:
                env.log.debug("Products for '%s' : %s",
                              product, products)
                raise LookupError("Missing product %s" % (product,))

        self.parent = env
        self.product = product
        self.systeminfo = []

        self.setup_config()

        # when creating product environment, invoke `IEnvironmentSetupParticipant.environment_created`
        # for all setup participants that don't support multi product environments
        if create:
            for participant in self.product_setup_participants:
                with ComponentEnvironmentContext(self, participant):
                    participant.environment_created()
Example #52
0
    def __init__(self, env, product, create=False):
        """Initialize the product environment.

        :param env:     the global Trac environment
        :param product: product prefix or an instance of
                        multiproduct.model.Product
        """
        if not isinstance(env, trac.env.Environment):
            cls = self.__class__
            raise TypeError("Initializer must be called with " \
                "trac.env.Environment instance as first argument " \
                "(got %s instance instead)" %
                         (cls.__module__ + '.' + cls.__name__, ))

        ComponentManager.__init__(self)

        if isinstance(product, Product):
            if product._env is not env:
                raise ValueError("Product's environment mismatch")
        elif isinstance(product, basestring):
            products = Product.select(env, where={'prefix': product})
            if len(products) == 1:
                product = products[0]
            else:
                env.log.debug("Products for '%s' : %s", product, products)
                raise LookupError("Missing product %s" % (product, ))

        self.parent = env
        self.product = product
        self.systeminfo = []

        self.setup_config()

        # when creating product environment, invoke `IEnvironmentSetupParticipant.environment_created`
        # for all setup participants that don't support multi product environments
        if create:
            for participant in self.product_setup_participants:
                with ComponentEnvironmentContext(self, participant):
                    participant.environment_created()
Example #53
0
    def _upgrade_system_tables(self, db, create_temp_table):
        # migrate system table (except wiki which is handled separately)
        # to a new schema
        # - create tables with the new schema
        # - populate system tables with global configuration for each product
        # - exception is permission table where permissions
        #   are also populated in global scope
        #
        # permission table specifics: 'anonymous' and 'authenticated' users
        # should by default have a PRODUCT_VIEW permission for all products
        self.log.info("Migrating system tables to a new schema")
        for table in self.MIGRATE_TABLES:
            if table == 'wiki':
                continue
            temp_table_name, cols = create_temp_table(table)
            for product in Product.select(self.env):
                self.log.info("Populating table '%s' for product '%s' ('%s')",
                              table, product.name, product.prefix)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, product.prefix, temp_table_name))
                if table == 'permission':
                    db.executemany(
                        """INSERT INTO permission (username, action, product)
                           VALUES (%s, %s, %s)""",
                        [('anonymous', 'PRODUCT_VIEW', product.prefix),
                         ('authenticated', 'PRODUCT_VIEW', product.prefix)])

            if table == 'permission':
                self.log.info("Populating table '%s' for global scope", table)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, '', temp_table_name))
            self._drop_temp_table(db, temp_table_name)
        db.executemany(
            """INSERT INTO permission (username, action, product)
                VALUES (%s, %s, %s)""",
            [('anonymous', 'PRODUCT_VIEW', ''),
             ('authenticated', 'PRODUCT_VIEW', '')])
Example #54
0
    def _upgrade_system_tables(self, db, create_temp_table):
        # migrate system table (except wiki which is handled separately)
        # to a new schema
        # - create tables with the new schema
        # - populate system tables with global configuration for each product
        # - exception is permission table where permissions
        #   are also populated in global scope
        #
        # permission table specifics: 'anonymous' and 'authenticated' users
        # should by default have a PRODUCT_VIEW permission for all products
        self.log.info("Migrating system tables to a new schema")
        for table in self.MIGRATE_TABLES:
            if table == 'wiki':
                continue
            temp_table_name, cols = create_temp_table(table)
            for product in Product.select(self.env):
                self.log.info("Populating table '%s' for product '%s' ('%s')",
                              table, product.name, product.prefix)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, product.prefix, temp_table_name))
                if table == 'permission':
                    db.executemany(
                        """INSERT INTO permission (username, action, product)
                           VALUES (%s, %s, %s)""",
                        [('anonymous', 'PRODUCT_VIEW', product.prefix),
                         ('authenticated', 'PRODUCT_VIEW', product.prefix)])

            if table == 'permission':
                self.log.info("Populating table '%s' for global scope", table)
                db("""INSERT INTO %s (%s, product) SELECT %s,'%s' FROM %s""" %
                   (table, cols, cols, '', temp_table_name))
            self._drop_temp_table(db, temp_table_name)
        db.executemany(
            """INSERT INTO permission (username, action, product)
                VALUES (%s, %s, %s)""",
            [('anonymous', 'PRODUCT_VIEW', ''),
             ('authenticated', 'PRODUCT_VIEW', '')])
Example #55
0
    def test_new_product_perm(self):
        """Only product owner and TRAC_ADMIN will access new product
        """
        newproduct = Product(self.global_env)
        newproduct.prefix = 'NEW'
        newproduct.name = 'New product'
        newproduct.owner = 'owneruser'
        newproduct.insert()

        env = ProductEnvironment(self.global_env, newproduct)
        self.global_perm_admin._do_add('adminuser', 'TRAC_ADMIN')
        admin_perm = perm.PermissionCache(env, 'adminuser')
        owner_perm = perm.PermissionCache(env, 'owneruser')
        user_perm = perm.PermissionCache(env, 'testuser')
        global_permsys = perm.PermissionSystem(self.global_env)
        permsys = perm.PermissionSystem(env)

        self.assertEquals({'EMAIL_VIEW': True, 'TEST_ADMIN': True,
                           'TEST_CREATE': True, 'TEST_DELETE': True,
                           'TEST_MODIFY': True, 'TRAC_ADMIN' : True},
                          global_permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, global_permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, global_permsys.get_user_permissions('testuser'))
        self.assertEquals({}, permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, permsys.get_user_permissions('testuser'))

        all_actions = self.permsys.get_actions()
        all_actions.remove('TRAC_ADMIN')
        for action in all_actions:
            self.assertTrue(admin_perm.has_permission(action))
            self.assertTrue(owner_perm.has_permission(action))
            self.assertFalse(user_perm.has_permission(action))

        self.assertTrue(admin_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(owner_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(user_perm.has_permission('TRAC_ADMIN'))
Example #56
0
    def test_new_product_perm(self):
        """Only product owner and TRAC_ADMIN will access new product
        """
        newproduct = Product(self.global_env)
        newproduct.prefix = 'NEW'
        newproduct.name = 'New product'
        newproduct.owner = 'owneruser'
        newproduct.insert()

        env = ProductEnvironment(self.global_env, newproduct)
        self.global_perm_admin._do_add('adminuser', 'TRAC_ADMIN')
        admin_perm = perm.PermissionCache(env, 'adminuser')
        owner_perm = perm.PermissionCache(env, 'owneruser')
        user_perm = perm.PermissionCache(env, 'testuser')
        global_permsys = perm.PermissionSystem(self.global_env)
        permsys = perm.PermissionSystem(env)

        self.assertEquals({'EMAIL_VIEW': True, 'TEST_ADMIN': True,
                           'TEST_CREATE': True, 'TEST_DELETE': True,
                           'TEST_MODIFY': True, 'TRAC_ADMIN' : True},
                          global_permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, global_permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, global_permsys.get_user_permissions('testuser'))
        self.assertEquals({}, permsys.get_user_permissions('adminuser'))
        self.assertEquals({}, permsys.get_user_permissions('owneruser'))
        self.assertEquals({}, permsys.get_user_permissions('testuser'))

        all_actions = self.permsys.get_actions()
        all_actions.remove('TRAC_ADMIN')
        for action in all_actions:
            self.assertTrue(admin_perm.has_permission(action))
            self.assertTrue(owner_perm.has_permission(action))
            self.assertFalse(user_perm.has_permission(action))

        self.assertTrue(admin_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(owner_perm.has_permission('TRAC_ADMIN'))
        self.assertFalse(user_perm.has_permission('TRAC_ADMIN'))
Example #57
0
    def test_get_tickets(self):
        for pdata in (
            {
                'prefix': 'p2',
                'name': 'product, too',
                'description': ''
            },
            {
                'prefix': 'p3',
                'name': 'strike three',
                'description': ''
            },
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [
                (t['product'], t['id'])
                for t in Product.get_tickets(self.global_env, product.prefix)
            ]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id'])
                                    for t in Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Example #58
0
class ProductTestCase(unittest.TestCase):
    """Unit tests covering the Product model"""
    INITIAL_PREFIX = 'tp'
    INITIAL_NAME = 'test project'
    INITIAL_DESCRIPTION = 'a test project'

    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()

    def tearDown(self):
        shutil.rmtree(self.env.path)
        self.env.reset_db()

    def _enable_resource_change_listener(self):
        listener = TestResourceChangeListener(self.env)
        listener.resource_type = Product
        listener.callback = self.listener_callback
        return listener

    def listener_callback(self, action, resource, context, old_values = None):
        # pylint: disable=unused-argument
        # pylint: disable=attribute-defined-outside-init
        self.prefix = resource.prefix
        self.name = resource.name
        self.description = resource.description

    def test_set_table_field(self):
        """tests that table.field style update works"""
        test = {'prefix': 'td',
                'name': 'test field access',
                'description': 'product to test field setting'}

        product = Product(self.env)

        # attempt to set the fields from the data
        product.prefix = test['prefix']
        product.name = test['name']
        product.description = test['description']

        self.assertEqual(product._data['prefix'], test['prefix'])
        self.assertEqual(product._data['name'], test['name'])
        self.assertEqual(product._data['description'], test['description'])

    def test_select(self):
        """tests that select can search Products by fields"""

        p2_data = {'prefix':'tp2',
                   'name':'test project 2',
                   'description':'a different test project'}
        p3_data = {'prefix':'tp3',
                   'name':'test project 3',
                   'description':'test project'}

        product2 = Product(self.env)
        product2._data.update(p2_data)
        product3 = Product(self.env)
        product3._data.update(p3_data)

        product2.insert()
        product3.insert()

        products = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'name':'test project'}))
        self.assertEqual(1, len(products))
        products = list(Product.select(self.env,
            where={'prefix':'tp3', 'name':'test project 3'}))
        self.assertEqual(1, len(products))

    def test_update(self):
        """tests that we can use update to push data to the database"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('test project', product._data['name'])

        new_data = {'prefix':'tp',
                    'name':'updated',
                    'description':'nothing'}
        product._data.update(new_data)
        product.update()

        comp_product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        self.assertEqual('updated', comp_product._data['name'])

    def test_update_key_change(self):
        """tests that we raise an error for attempting to update key fields"""
        bad_data = {'prefix':'tp0',
                    'name':'update',
                    'description':'nothing'}
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product._data.update(bad_data)
        self.assertRaises(TracError, product.update)

    def test_insert(self):
        """test saving new Product"""
        data = {'prefix':'new', 'name':'new', 'description':'new'}
        product = Product(self.env)
        product._data.update(data)
        product.insert()

        check_products = list(Product.select(self.env, where={'prefix':'new'}))

        self.assertEqual(product._data['prefix'],
                         check_products[0]._data['prefix'])
        self.assertEqual(1, len(check_products))

    def test_insert_duplicate_key(self):
        """test attempted saving of Product with existing key fails"""
        dupe_key_data = {'prefix':'tp',
                         'name':'dupe',
                         'description':'dupe primary key'}
        product2 = Product(self.env)
        product2._data.update(dupe_key_data)
        self.assertRaises(TracError, product2.insert)

    def test_delete(self):
        """test that we are able to delete Products"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        post = list(Product.select(self.env, where={'prefix':'tp'}))
        self.assertEqual(0, len(post))

    def test_delete_twice(self):
        """test that we error when deleting twice on the same key"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        self.assertRaises(TracError, product.delete)

    def test_field_data_get(self):
        """tests that we can use table.field syntax to get to the field data"""
        prefix = self.default_data['prefix']
        name = self.default_data['name']
        description = self.default_data['description']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]
        self.assertEqual(prefix, product.prefix)
        self.assertEqual(name, product.name)
        self.assertEqual(description, product.description)

    def test_field_set(self):
        """tests that we can use table.field = something to set field data"""
        prefix = self.default_data['prefix']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]

        new_description = 'test change of description'
        product.description = new_description
        self.assertEqual(new_description, product.description)

    def test_missing_unique_fields(self):
        """ensure that that insert method works when _meta does not specify
        unique fields when inserting more than one ProductResourceMap instances
        """
        class TestModel(ModelBase):
            """A test model with no unique_fields"""
            _meta = {'table_name': 'bloodhound_testmodel',
                     'object_name': 'TestModelObject',
                     'key_fields': ['id',],
                     'non_key_fields': ['value'],
                     'unique_fields': [],}

        from trac.db import DatabaseManager
        schema = [TestModel._get_schema(), ]
        with self.env.db_transaction as db:
            db_connector, dummy = DatabaseManager(self.env)._get_connector()
            for table in schema:
                for statement in db_connector.to_sql(table):
                    db(statement)

        structure =  dict([(table.name, [col.name for col in table.columns])
                           for table in schema])
        tm1 = TestModel(self.env)
        tm1._data.update({'id':1, 'value':'value1'})
        tm1.insert()
        tm2 = TestModel(self.env)
        tm2._data.update({'id':2, 'value':'value2'})
        tm2.insert()

    def test_change_listener_created(self):
        self.assertEqual('created', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)
        self.assertEqual(self.INITIAL_NAME, self.name)
        self.assertEqual(self.INITIAL_DESCRIPTION, self.description)

    def test_change_listener_changed(self):
        CHANGED_NAME = "changed name"
        self.product.name = CHANGED_NAME
        self.product.update()
        self.assertEqual('changed', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(CHANGED_NAME, self.name)
        self.assertEqual({"name":self.INITIAL_NAME}, self.listener.old_values)

    def test_change_listener_deleted(self):
        self.product.delete()
        self.assertEqual('deleted', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)

    def test_get_tickets(self):
        for pdata in (
            {'prefix': 'p2', 'name':'product, too', 'description': ''},
            {'prefix': 'p3', 'name':'strike three', 'description': ''},
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [(t['product'], t['id']) for t in
                Product.get_tickets(self.global_env, product.prefix)]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id']) for t in
                Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Example #59
0
 def resource_exists(self, resource):
     """Check whether product exists physically.
     """
     products = Product.select(self.env, where={'name' : resource.id})
     return bool(products)
Example #60
0
    def test_delete_twice(self):
        """test that we error when deleting twice on the same key"""
        product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
        product.delete()

        self.assertRaises(TracError, product.delete)