Commits

Olemis Lang  committed 5744ff3 Merge

BH Multiproduct #115 : Merge 12b3a2a104f5e377e26a103e incorporating patches for #333 .

Product environments patch enhanced in order to avoid copying api.py

  • Participants
  • Parent commits 3512cd0, e377e26
  • Branches t115_product_env

Comments (0)

Files changed (5)

+t333/t333_r1427886_schema_autoinc.diff
+t333/t333_r1427886_mp_gen_schema.diff
 t115/t115_r1427886_product_envs.diff
-t115_r1427886_product_config.diff
+t115/t115_r1427886_product_config.diff
 t115/t115_r1423431_product_envs_testing.diff

File t115/t115_r1427886_product_config.diff

 # HG changeset patch
-# Parent cbbe8130b4d14f7221cc35722e9a78057efdc414
+# Parent 0abbfaaeb2f726c35397fc56b998a5c6e401f70f
 BH Multiproduct #115 : Product-specific settings
 
-diff -r cbbe8130b4d1 bloodhound_multiproduct/multiproduct/model.py
---- a/bloodhound_multiproduct/multiproduct/model.py	Wed Jan 02 22:32:51 2013 -0500
-+++ b/bloodhound_multiproduct/multiproduct/model.py	Wed Jan 02 23:59:19 2013 -0500
+diff -r 0abbfaaeb2f7 bloodhound_multiproduct/multiproduct/model.py
+--- a/bloodhound_multiproduct/multiproduct/model.py	Thu Jan 03 01:11:58 2013 -0500
++++ b/bloodhound_multiproduct/multiproduct/model.py	Thu Jan 03 01:12:16 2013 -0500
 @@ -27,6 +27,10 @@
  
  from bhdashboard.model import ModelBase
      @classmethod
      def get_tickets(cls, env, product=''):
          """Retrieve all tickets associated with the product."""
-@@ -87,7 +91,7 @@
-             'no_change_fields':['id',],
+@@ -88,7 +92,7 @@
              'unique_fields':[],
+             'auto_inc':['id'],
              }
 -    
 +
      def reparent_resource(self, product=None):
          """a specific function to update a record when it is to move product"""
          if product is not None:
-@@ -100,3 +104,17 @@
+@@ -101,3 +105,17 @@
          self._data['product_id'] = product
          self.update()
  

File t115/t115_r1427886_product_envs.diff

 # HG changeset patch
-# Parent 818091ba4950f98af041fb73703e40acd792b59b
+# Parent d143652322b7ec13c6bd1f0b7aaf7fa01297ba6a
 BH Multiproduct #115 : Product environments
 
-diff --git a/bloodhound_multiproduct/multiproduct/api.py b/bloodhound_multiproduct/multiproduct/env.py
-copy from bloodhound_multiproduct/multiproduct/api.py
-copy to bloodhound_multiproduct/multiproduct/env.py
---- a/bloodhound_multiproduct/multiproduct/api.py
-+++ b/bloodhound_multiproduct/multiproduct/env.py
-@@ -16,167 +16,461 @@
- #  specific language governing permissions and limitations
- #  under the License.
- 
--"""Core components to support multi-product"""
--from datetime import datetime
+diff -r d143652322b7 bloodhound_multiproduct/multiproduct/env.py
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/bloodhound_multiproduct/multiproduct/env.py	Thu Jan 03 01:10:05 2013 -0500
+@@ -0,0 +1,476 @@
++
++#  Licensed to the Apache Software Foundation (ASF) under one
++#  or more contributor license agreements.  See the NOTICE file
++#  distributed with this work for additional information
++#  regarding copyright ownership.  The ASF licenses this file
++#  to you under the Apache License, Version 2.0 (the
++#  "License"); you may not use this file except in compliance
++#  with the License.  You may obtain a copy of the License at
++#
++#   http://www.apache.org/licenses/LICENSE-2.0
++#
++#  Unless required by applicable law or agreed to in writing,
++#  software distributed under the License is distributed on an
++#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++#  KIND, either express or implied.  See the License for the
++#  specific language governing permissions and limitations
++#  under the License.
++
 +"""Bloodhound product environment and related APIs"""
- 
--from genshi.builder import tag
++
 +import os.path
- 
--from pkg_resources import resource_filename
--from trac.core import Component, TracError, implements
--from trac.db import Table, Column, DatabaseManager
--from trac.env import IEnvironmentSetupParticipant
--from trac.perm import IPermissionRequestor
--from trac.resource import IResourceManager
--from trac.ticket.api import ITicketFieldProvider
--from trac.util.translation import _, N_
--from trac.web.chrome import ITemplateProvider
++
 +from trac.config import ConfigSection, Option
 +from trac.core import Component, ComponentManager, ExtensionPoint, \
 +        implements, TracError
 +from trac.env import Environment, ISystemInfoProvider
 +from trac.util import get_pkginfo, lazy
 +from trac.util.compat import sha1
- 
- from multiproduct.model import Product
- 
--DB_VERSION = 2
--DB_SYSTEM_KEY = 'bloodhound_multi_product_version'
--PLUGIN_NAME = 'Bloodhound multi product'
++
++from multiproduct.model import Product
++
 +class ProductEnvironment(Component, ComponentManager):
 +    """Bloodhound product-aware environment manager.
- 
--class MultiProductSystem(Component):
--    """Creates the database tables and template directories"""
--    
--    implements(IEnvironmentSetupParticipant, ITemplateProvider,
--            IPermissionRequestor, ITicketFieldProvider, IResourceManager)
--    
--    SCHEMA = [
--        Table('bloodhound_product', key = ['prefix', 'name']) [
--            Column('prefix'),
--            Column('name'),
--            Column('description'),
--            Column('owner'),
--            ],
--        Table('bloodhound_productresourcemap', key = 'id') [
--            Column('id', auto_increment=True),
--            Column('product_id'),
--            Column('resource_type'),
--            Column('resource_id'),
--            ]
--        ]
--    
--    def get_version(self):
--        """Finds the current version of the bloodhound database schema"""
--        rows = self.env.db_query("""
--            SELECT value FROM system WHERE name = %s
--            """, (DB_SYSTEM_KEY,))
--        return int(rows[0][0]) if rows else -1
--    
--    # IEnvironmentSetupParticipant methods
--    def environment_created(self):
--        """Insertion of any default data into the database."""
--        self.log.debug("creating environment for %s plugin." % PLUGIN_NAME)
--    
--    def environment_needs_upgrade(self, db_dummy=None):
--        """Detects if the installed db version matches the running system"""
--        db_installed_version = self.get_version()
--        
--        if db_installed_version > DB_VERSION:
--            raise TracError('''Current db version (%d) newer than supported by
--            this version of the %s (%d).''' % (db_installed_version,
--                                               PLUGIN_NAME,
--                                               DB_VERSION))
--        return db_installed_version < DB_VERSION
--    
--    def upgrade_environment(self, db_dummy=None):
--        """Installs or updates tables to current version"""
--        self.log.debug("upgrading existing environment for %s plugin." % 
--                       PLUGIN_NAME)
--        db_installed_version = self.get_version()
--        #cursor = db.cursor()
--        with self.env.db_transaction as db:
--            if db_installed_version < 0:
--                # Initial installation
--                db("""
--                    INSERT INTO system (name, value) VALUES ('%s','%s')
--                    """  % (DB_SYSTEM_KEY, DB_VERSION))
--                db("ALTER TABLE ticket ADD COLUMN product TEXT")
--                self.log.debug("creating initial db tables for %s plugin." % 
--                               PLUGIN_NAME)
--                
--                db_connector, dummy = DatabaseManager(self.env)._get_connector()
--                for table in self.SCHEMA:
--                    for statement in db_connector.to_sql(table):
--                        db(statement)
--                db_installed_version = self.get_version()
--            
--            if db_installed_version == 1:
--                from multiproduct.model import Product
--                products = Product.select(self.env)
--                for prod in products:
--                    db("""UPDATE ticket SET product=%s
--                          WHERE product=%s""", (prod.prefix, prod.name))
--                
--                db("""UPDATE system SET value=%s
--                      WHERE name=%s""", (DB_VERSION, DB_SYSTEM_KEY))
--                self.log.info("Upgraded multiproduct db schema from version %d"
--                              " to %d" % (db_installed_version, DB_VERSION))
--    
--    # ITemplateProvider methods
--    def get_templates_dirs(self):
--        """provide the plugin templates"""
--        return [resource_filename(__name__, 'templates')]
--    
--    def get_htdocs_dirs(self):
--        """proved the plugin htdocs"""
--        return []
++
 +    Bloodhound encapsulates access to product resources stored inside a
 +    Trac environment via product environments. They are compatible lightweight
 +    irepresentations of top level environment. 
- 
--    # IPermissionRequestor methods
--    def get_permission_actions(self):
--        acts = ['PRODUCT_CREATE', 'PRODUCT_DELETE', 'PRODUCT_MODIFY',
--                'PRODUCT_VIEW']
--        return acts + [('PRODUCT_ADMIN', acts)] + [('ROADMAP_ADMIN', acts)]
++
 +    Product environments contain among other things:
- 
--    # ITicketFieldProvider methods
--    def get_select_fields(self):
--        """Product select fields"""
--        return [(35, {'name': 'product', 'label': N_('Product'),
--                      'cls': Product, 'pk': 'prefix', 'optional': True})]
--    
--    def get_radio_fields(self):
--        """Product radio fields"""
--        return []
++
 +    * a configuration file, 
 +    * product-aware clones of the wiki and ticket attachments files,
- 
--    # IResourceManager methods
++
 +    Product environments do not have:
- 
--    def get_resource_realms(self):
--        """Manage 'product' realm.
++
 +    * product-specific templates and plugins,
 +    * a separate database
 +    * active participation in database upgrades and other setup tasks
 +    @property
 +    def system_info_providers(self):
 +        r"""System info will still be determined by the global environment.
-         """
--        yield 'product'
++        """
 +        return self.env.system_info_providers
- 
--    def get_resource_description(self, resource, format='default', context=None,
--                                 **kwargs):
--        """Describe product resource.
++
 +    @property
 +    def setup_participants(self):
 +        """Setup participants list for product environments will always
 +        be empty based on the fact that upgrades will only be handled by
 +        the global environment.
-         """
--        desc = resource.id
--        if format != 'compact':
--            desc = _('Product %(name)s', name=resource.id)
--        if context:
--            return self._render_link(context, resource.id, desc)
++        """
 +        return ()
 +
 +    components_section = ConfigSection('components',
 +            logtype = self.env.log_type
 +            logfile = self.env.log_file
 +            format = self.env.log_format
-         else:
--            return desc
++        else:
 +            logfile = self.log_file
 +            format = self.log_format
 +        if logtype == 'file' and not os.path.isabs(logfile):
 +                     .replace('%(project)s', self.project_name)
 +        self.log, self._log_handler = logger_handler_factory(
 +            logtype, logfile, self.log_level, logid, format=format)
- 
--    def _render_link(self, context, name, label, extra=''):
--        """Render link to product page.
++
 +        from trac import core, __version__ as VERSION
 +        self.log.info('-' * 32 + ' environment startup [Trac %s] ' + '-' * 32,
 +                      get_pkginfo(core).get('version', VERSION))
 +
 +        :param dest: Destination file; if not specified, the backup is
 +                     stored in a file called db_name.trac_version.bak
-         """
--        product = Product.select(self.env, where={'name' : name})
--        if product:
--            product = product[0]
--            href = context.href.products(product.prefix)
--            if 'PRODUCT_VIEW' in context.perm(product.resource):
--                return tag.a(label, class_='product', href=href + extra)
--        elif 'PRODUCT_CREATE' in context.perm('product', name):
--            return tag.a(label, class_='missing product', 
--                    href=context.href('products', action='new'),
--                    rel='nofollow')
--        return tag.a(label, class_='missing product')
++        """
 +        return self.env.backup(dest)
- 
--    def resource_exists(self, resource):
--        """Check whether product exists physically.
++
 +    def needs_upgrade(self):
 +        """Return whether the environment needs to be upgraded."""
 +        #for participant in self.setup_participants:
 +        :param backup: whether or not to backup before upgrading
 +        :param backup_dest: name of the backup file
 +        :return: whether the upgrade was performed
-         """
--        products = Product.select(self.env, where={'name' : resource.id})
--        return bool(products)
++        """
 +        # (Database) upgrades handled by global environment
 +        # FIXME: True or False ?
 +        return True
- 
++
 +    @property
 +    def href(self):
 +        """The application root path"""

File t333/t333_r1427886_mp_gen_schema.diff

+# HG changeset patch
+# Parent 3f53561a2a08f85cf3f0faefca00e18aa899fa13
+BH Multiproduct #333 : Generate multi-product DB schema from model meta-data
+
+diff -r 3f53561a2a08 bloodhound_multiproduct/multiproduct/api.py
+--- a/bloodhound_multiproduct/multiproduct/api.py	Thu Jan 03 00:36:35 2013 -0500
++++ b/bloodhound_multiproduct/multiproduct/api.py	Thu Jan 03 00:38:12 2013 -0500
+@@ -31,7 +31,7 @@
+ from trac.util.translation import _, N_
+ from trac.web.chrome import ITemplateProvider
+ 
+-from multiproduct.model import Product
++from multiproduct.model import Product, ProductResourceMap
+ 
+ DB_VERSION = 2
+ DB_SYSTEM_KEY = 'bloodhound_multi_product_version'
+@@ -43,20 +43,9 @@
+     implements(IEnvironmentSetupParticipant, ITemplateProvider,
+             IPermissionRequestor, ITicketFieldProvider, IResourceManager)
+     
+-    SCHEMA = [
+-        Table('bloodhound_product', key = ['prefix', 'name']) [
+-            Column('prefix'),
+-            Column('name'),
+-            Column('description'),
+-            Column('owner'),
+-            ],
+-        Table('bloodhound_productresourcemap', key = 'id') [
+-            Column('id', auto_increment=True),
+-            Column('product_id'),
+-            Column('resource_type'),
+-            Column('resource_id'),
+-            ]
+-        ]
++    SCHEMA = [modelcls._get_schema() \
++                for modelcls in (Product, ProductResourceMap)]
++    del modelcls
+     
+     def get_version(self):
+         """Finds the current version of the bloodhound database schema"""
+diff -r 3f53561a2a08 bloodhound_multiproduct/multiproduct/model.py
+--- a/bloodhound_multiproduct/multiproduct/model.py	Thu Jan 03 00:36:35 2013 -0500
++++ b/bloodhound_multiproduct/multiproduct/model.py	Thu Jan 03 00:38:12 2013 -0500
+@@ -86,6 +86,7 @@
+             'non_key_fields':['product_id','resource_type','resource_id',],
+             'no_change_fields':['id',],
+             'unique_fields':[],
++            'auto_inc':['id'],
+             }
+     
+     def reparent_resource(self, product=None):

File t333/t333_r1427886_schema_autoinc.diff

+# HG changeset patch
+# Parent d143652322b7ec13c6bd1f0b7aaf7fa01297ba6a
+BH Dashboard #333 : Consider auto_increment when generating schema from model metadata
+
+diff -r d143652322b7 bloodhound_dashboard/bhdashboard/model.py
+--- a/bloodhound_dashboard/bhdashboard/model.py	Wed Jan 02 18:06:37 2013 +0000
++++ b/bloodhound_dashboard/bhdashboard/model.py	Thu Jan 03 00:51:31 2013 -0500
+@@ -232,7 +232,9 @@
+     
+     @classmethod
+     def _get_schema(cls):
+-        fields =  [Column(field) for field in cls._get_fields()]
++        fields =  [Column(field, \
++                        auto_increment=field in cls._meta.get('auto_inc', [])) \
++                for field in cls._get_fields()]
+         return Table(cls._meta['table_name'], key=set(cls._meta['key_fields'] +
+                             cls._meta['unique_fields'])) [fields]
+ 
+diff -r d143652322b7 bloodhound_multiproduct/tests/model.py
+--- a/bloodhound_multiproduct/tests/model.py	Wed Jan 02 18:06:37 2013 +0000
++++ b/bloodhound_multiproduct/tests/model.py	Thu Jan 03 00:51:31 2013 -0500
+@@ -159,6 +159,6 @@
+         product.description = new_description
+         self.assertEqual(new_description, product.description)
+ 
+-if __name__ == '__main_':
++if __name__ == '__main__':
+     unittest.main()
+