incubator-bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1352503 - in /incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct: __init__.py api.py model.py
Date Thu, 21 Jun 2012 11:49:10 GMT
Author: gjm
Date: Thu Jun 21 11:49:10 2012
New Revision: 1352503

URL: http://svn.apache.org/viewvc?rev=1352503&view=rev
Log:
multiproduct: refactor to give an api.MultiProductSystem module - towards #105 (from olemis)

Added:
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py
      - copied, changed from r1352501, incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py
Modified:
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py

Modified: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py?rev=1352503&r1=1352502&r2=1352503&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py (original)
+++ incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py Thu Jun 21
11:49:10 2012
@@ -17,7 +17,7 @@
 #  under the License.
 
 """multiproduct module"""
-from multiproduct.model import MultiProductEnvironmentProvider
+from multiproduct.api import MultiProductSystem
 from multiproduct.product_admin import ProductAdminPanel
 import multiproduct.ticket
 from multiproduct.web_ui import ProductModule

Copied: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py (from r1352501,
incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py)
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py?p2=incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py&p1=incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py&r1=1352501&r2=1352503&rev=1352503&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py (original)
+++ incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/api.py Thu Jun 21 11:49:10
2012
@@ -16,303 +16,16 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-"""Models to support multi-product"""
+"""Core components to support multi-product"""
 from datetime import datetime
 
 from pkg_resources import resource_filename
 from trac.core import Component, TracError, implements
-from trac.resource import ResourceNotFound
 from trac.db import Table, Column, DatabaseManager
 from trac.env import IEnvironmentSetupParticipant
 from trac.web.chrome import ITemplateProvider
-from trac.resource import Resource
-from trac.ticket.api import TicketSystem
-from trac.ticket.model import Ticket
-from trac.ticket.query import Query
-from trac.util.datefmt import utc
 
-DB_VERSION = 1
-DB_SYSTEM_KEY = 'bloodhound_multi_product_version'
-PLUGIN_NAME = 'Bloodhound multi product'
-
-def dict_to_kv_str(data=None, sep=' AND '):
-    """Converts a dictionary into a string and a list suitable for using as part
-    of an SQL where clause like:
-        ('key0=%s AND key1=%s', ['value0','value1'])
-    The sep argument allows ' AND ' to be changed for ',' for UPDATE purposes
-    """
-    if data is None:
-        return ('', [])
-    return (sep.join(['%s=%%s' % k for k in data.keys()]), data.values())
-
-def fields_to_kv_str(fields, data, sep=' AND '):
-    """Converts a list of fields and a dictionary containing those fields into a
-    string and a list suitable for using as part of an SQL where clause like:
-        ('key0=%s,key1=%s', ['value0','value1'])
-    """
-    return dict_to_kv_str(dict([(f, data[f]) for f in fields]), sep)
-
-class ModelBase(object):
-    """Base class for the models to factor out common features
-    Derived classes should provide a meta dictionary to describe the table like:
-    
-    _meta = {'table_name':'mytable',
-             'object_name':'WhatIWillCallMyselfInMessages',
-             'key_fields':['id','id2'],
-             'non_key_fields':['thing','anotherthing'],
-             }
-    """
-    
-    def __init__(self, env, keys=None):
-        """Initialisation requires an environment to be specified.
-        If keys are provided, the Model will initialise from the database
-        """
-        # make this impossible to instantiate without telling the class details
-        # about itself in the self.meta dictionary
-        self._old_data = {}
-        self._data = {}
-        self._exists = False
-        self._env = env
-        self._all_fields = self._meta['key_fields'] + \
-                           self._meta['non_key_fields']
-        if keys is not None:
-            self._get_row(keys)
-        else:
-            self._update_from_row(None)
-    
-    def update_field_dict(self, field_dict):
-        """Updates the object's copy of the db fields (no db transaction)"""
-        self._data.update(field_dict)
-    
-    def __getattr__(self, name):
-        """Overridden to allow table.field style field access."""
-        try:
-            if name in self._all_fields:
-                return self._data[name]
-        except KeyError:
-            raise AttributeError(name)
-        raise AttributeError(name)
-    
-    def __setattr__(self, name, value):
-        """Overridden to allow table.field = value style field setting."""
-        data = self.__dict__.get('data')
-        fields = self.__dict__.get('fields')
-        
-        if data and fields and name in fields:
-            self._data[name] = value
-        else:
-            dict.__setattr__(self, name, value)
-            
-    
-    def _update_from_row(self, row = None):
-        """uses a provided database row to update the model"""
-        fields = self._meta['key_fields']+self._meta['non_key_fields']
-        self._exists = row is not None
-        if row is None:
-            row = [None]*len(fields)
-        self._data = dict([(fields[i], row[i]) for i in range(len(row))])
-        self._old_data = {}
-        self._old_data.update(self._data)
-    
-    def _get_row(self, keys):
-        """queries the database and stores the result in the model"""
-        row = None
-        where, values = fields_to_kv_str(self._meta['key_fields'], keys)
-        fields = ','.join(self._meta['key_fields']+self._meta['non_key_fields'])
-        sdata = {'fields':fields,
-                 'where':where}
-        sdata.update(self._meta)
-        
-        sql = """SELECT %(fields)s FROM %(table_name)s
-                 WHERE %(where)s""" % sdata
-        with self._env.db_query as db:
-            for row in db(sql, values):
-                self._update_from_row(row)
-                break
-            else:
-                raise ResourceNotFound('No %(object_name)s with %(where)s' %
-                                sdata)
-    
-    def delete(self):
-        """Deletes the matching record from the database"""
-        if not self._exists:
-            raise TracError('%(object_name)s does not exist' % self._meta)
-        where, values = fields_to_kv_str(self._meta['key_fields'], self._data)
-        sdata = {'where': where}
-        sdata.update(self._meta)
-        sql = """DELETE FROM %(table_name)s
-                 WHERE %(where)s""" % sdata
-        with self._env.db_transaction as db:
-            db(sql, values)
-            self._exists = False
-            self._data = dict([(k, None) for k in self._data.keys()])
-            self._old_data.update(self._data)
-            TicketSystem(self._env).reset_ticket_fields()
-    
-    def insert(self):
-        """Create new record in the database"""
-        sdata = None
-        if self._exists or len(self.select(self._env, where =
-                                dict([(k,self._data[k])
-                                      for k in self._meta['key_fields']]))):
-            sdata = {'keys':','.join(["%s='%s'" % (k, self._data[k])
-                                     for k in self._meta['key_fields']])}
-        elif len(self.select(self._env, where =
-                                dict([(k,self._data[k])
-                                      for k in self._meta['unique_fields']]))):
-            sdata = {'keys':','.join(["%s='%s'" % (k, self._data[k])
-                                     for k in self._meta['unique_fields']])}
-        if sdata:
-            sdata.update(self._meta)
-            raise TracError('%(object_name)s %(keys)s already exists' %
-                            sdata)
-            
-        for key in self._meta['key_fields']:
-            if not self._data[key]:
-                sdata = {'key':key}
-                sdata.update(self._meta)
-                raise TracError('%(key)s required for %(object_name)s' %
-                                sdata)
-        fields = self._meta['key_fields']+self._meta['non_key_fields']
-        sdata = {'fields':','.join(fields),
-                 'values':','.join(['%s'] * len(fields))}
-        sdata.update(self._meta)
-        
-        sql = """INSERT INTO %(table_name)s (%(fields)s)
-                 VALUES (%(values)s)""" % sdata
-        with self._env.db_transaction as db:
-            db(sql, [self._data[f] for f in fields])
-            self._exists = True
-            self._old_data.update(self._data)
-            TicketSystem(self._env).reset_ticket_fields()
-
-    def _update_relations(self, db):
-        """Extra actions due to update"""
-        pass
-    
-    def update(self):
-        """Update the matching record in the database"""
-        if self._old_data == self._data:
-            return 
-        if not self._exists:
-            raise TracError('%(object_name)s does not exist' % self._meta)
-        for key in self._meta['no_change_fields']:
-            if self._data[key] != self._old_data[key]:
-                raise TracError('%s cannot be changed' % key)
-        for key in self._meta['key_fields'] + self._meta['unique_fields']:
-            if self._data[key] != self._old_data[key]:
-                if len(self.select(self._env, where = {key:self._data[key]})):
-                    raise TracError('%s already exists' % key)
-        
-        setsql, setvalues = fields_to_kv_str(self._meta['non_key_fields'],
-                                             self._data, sep=',')
-        where, values = fields_to_kv_str(self._meta['key_fields'], self._data)
-        
-        sdata = {'where': where,
-                 'values': setsql}
-        sdata.update(self._meta)
-        sql = """UPDATE %(table_name)s SET %(values)s
-                 WHERE %(where)s""" % sdata
-        with self._env.db_transaction as db:
-            db(sql, setvalues + values)
-            self._update_relations(db)
-            self._old_data.update(self._data)
-            TicketSystem(self._env).reset_ticket_fields()
-    
-    @classmethod
-    def select(cls, env, db=None, where=None):
-        """Query the database to get a set of records back"""
-        rows = []
-        fields = cls._meta['key_fields']+cls._meta['non_key_fields']
-        
-        sdata = {'fields':','.join(fields),}
-        sdata.update(cls._meta)
-        sql = r'SELECT %(fields)s FROM %(table_name)s' % sdata
-        wherestr, values = dict_to_kv_str(where)
-        if wherestr:
-            wherestr = ' WHERE ' + wherestr
-        for row in env.db_query(sql + wherestr, values):
-            # we won't know which class we need until called
-            model = cls.__new__(cls)
-            data = dict([(fields[i], row[i]) for i in range(len(fields))])
-            model.__init__(env, data)
-            rows.append(model)
-        return rows
-
-class Product(ModelBase):
-    """The Product table"""
-    _meta = {'table_name':'bloodhound_product',
-            'object_name':'Product',
-            'key_fields':['prefix',],
-            'non_key_fields':['name', 'description', 'owner'],
-            'no_change_fields':['prefix',],
-            'unique_fields':['name'],
-            }
-    
-    @property
-    def resource(self):
-        """Allow Product to be treated as a Resource"""
-        return Resource('product', self.name)
-    
-    def delete(self, resources_to=None):
-        """ override the delete method so that we can move references to this
-        object to a new product """
-        if resources_to is not None:
-            new_product = Product(self._env, resources_to)
-            if not new_product._exists:
-                sdata = {'new_table':resources_to}
-                sdata.update(self._meta)
-                raise TracError('%(object_name)s %(new_table)s does not exist' %
-                                sdata)
-        super(Product, self).delete()
-        #find and update all resources that should move
-        where = {'product_id':self._data['prefix']}
-        for prm in ProductResourceMap.select(self._env, where=where):
-            prm._data['product_id'] = resources_to
-            prm.update()
-    
-    def _update_relations(self, db=None, author=None):
-        """Extra actions due to update"""
-        # tickets need to be updated
-        old_name = self._old_data['name']
-        new_name = self._data['name']
-        now = datetime.now(utc)
-        comment = 'Product %s renamed to %s' % (old_name, new_name)
-        if old_name != new_name:
-            for t in Product.get_tickets(self._env, old_name):
-                ticket = Ticket(self._env, t['id'], db)
-                ticket['product'] = new_name
-                ticket.save_changes(author, comment, now)
-    
-    @classmethod
-    def get_tickets(cls, env, product=''):
-        """Retrieve all tickets associated with the product."""
-        q = Query.from_string(env, 'product=%s' % product)
-        return q.execute()
-
-class ProductResourceMap(ModelBase):
-    """Table representing the mapping of resources to their product"""
-    _meta = {'table_name':'bloodhound_productresourcemap',
-            'object_name':'ProductResourceMapping',
-            'key_fields':['id',],
-            'non_key_fields':['product_id','resource_type','resource_id',],
-            'no_change_fields':['id',],
-            'unique_fields':[],
-            }
-    
-    def reparent_resource(self, product=None):
-        """a specific function to update a record when it is to move product"""
-        if product is not None:
-            new_product = Product(self._env, product)
-            if not new_product._exists:
-                sdata = {'new_table':product}
-                sdata.update(self.meta)
-                raise TracError('%(object_name)s %(new_table)s does not exist' %
-                                sdata)
-        self._data['product_id'] = product
-        self.update()
-
-class MultiProductEnvironmentProvider(Component):
+class MultiProductSystem(Component):
     """Creates the database tables and template directories"""
     
     implements(IEnvironmentSetupParticipant, ITemplateProvider)

Modified: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py?rev=1352503&r1=1352502&r2=1352503&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py (original)
+++ incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/model.py Thu Jun 21 11:49:10
2012
@@ -20,11 +20,9 @@
 from datetime import datetime
 
 from pkg_resources import resource_filename
-from trac.core import Component, TracError, implements
+from trac.core import TracError
 from trac.resource import ResourceNotFound
 from trac.db import Table, Column, DatabaseManager
-from trac.env import IEnvironmentSetupParticipant
-from trac.web.chrome import ITemplateProvider
 from trac.resource import Resource
 from trac.ticket.api import TicketSystem
 from trac.ticket.model import Ticket
@@ -312,77 +310,3 @@ class ProductResourceMap(ModelBase):
         self._data['product_id'] = product
         self.update()
 
-class MultiProductEnvironmentProvider(Component):
-    """Creates the database tables and template directories"""
-    
-    implements(IEnvironmentSetupParticipant, ITemplateProvider)
-    
-    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, _ = 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()
-    
-    # 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 []
-



Mime
View raw message