Modify

Opened 2 years ago

Last modified 17 months ago

#10251 new defect

Unable to upgrade OS X tracd 0.11.7 database

Reported by: fommil Owned by: rjollos
Priority: normal Component: WorkLogPlugin
Severity: normal Keywords:
Cc: Trac Release: 0.11

Description (last modified by rjollos)

I get the following exception when attempting to upgrade the TRAC install, with a similar thing when I go to any issue:

$ trac-admin /Users/samuel/Desktop/TRAC/test upgrade

Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/trac-admin", line 8, in <module>
    load_entry_point('Trac==0.11.7', 'console_scripts', 'trac-admin')()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/admin/console.py", line 1321, in run
    return admin.onecmd(command)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/admin/console.py", line 138, in onecmd
    rv = cmd.Cmd.onecmd(self, line) or 0
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/cmd.py", line 221, in onecmd
    return func(arg)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/admin/console.py", line 1154, in do_upgrade
    if not self.__env.needs_upgrade():
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/env.py", line 435, in needs_upgrade
    for participant in self.setup_participants:
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/core.py", line 70, in extensions
    return filter(None, [component.compmgr[cls] for cls in extensions])
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/core.py", line 207, in __getitem__
    component = cls(self)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Trac-0.11.7-py2.7.egg/trac/core.py", line 111, in maybe_init
    init(self)
  File "build/bdist.macosx-10.8-x86_64/egg/worklog/api.py", line 36, in __init__
AttributeError: 'Environment' object has no attribute 'get_read_db'

Attachments (0)

Change History (10)

comment:1 Changed 2 years ago by fommil

I went back to r10794, 0.11 branch, and this works ok.

comment:2 Changed 2 years ago by rjollos

  • Description modified (diff)

comment:3 Changed 2 years ago by rjollos

  • Owner changed from coling to rjollos

In [11830] I renamed 0.12 to trunk and made the comment that the 0.11 and 0.12 branches were equivalent. Looking at it now, however, I see that is not the case. I must have done something stupid, like diff 0.11 0.12 without the -r flag. I'll fix this now.

comment:4 Changed 2 years ago by rjollos

Here is the 0.11 and 0.12 diff @ r11829:

  • setup.py

    Only in 0.11: setup.cfg
    diff -ru 0.11/setup.py 0.12/setup.py
    old new  
    77setup(name=PACKAGE, 
    88      description='Plugin to manage the which tickets users are currently working on', 
    99      keywords='trac plugin ticket working', 
    10       version='0.1', 
     10      version='0.2', 
    1111      url='', 
    1212      license='http://www.opensource.org/licenses/mit-license.php', 
    1313      author='Colin Guthrie', 
  • worklog/api.py

    Only in 0.12/.svn/pristine: 18
    Only in 0.11/.svn/pristine: 1f
    Only in 0.12/.svn/pristine: 4d
    Only in 0.11/.svn/pristine: 74
    Only in 0.11/.svn/pristine: 7f
    Only in 0.12/.svn/pristine: 85
    Only in 0.11/.svn/pristine: aa
    Only in 0.11/.svn/pristine: b3
    Only in 0.12/.svn/pristine: d3
    Binary files 0.11/.svn/wc.db and 0.12/.svn/wc.db differ
    diff -ru 0.11/worklog/api.py 0.12/worklog/api.py
    old new  
    3333        self.db_installed_version = None 
    3434 
    3535        # Initialise database schema version tracking. 
    36         db = self.env.get_db_cnx() 
     36        db = self.env.get_read_db() 
    3737        cursor = db.cursor() 
    3838        cursor.execute("SELECT value FROM system WHERE name=%s", (self.db_version_key,)) 
    3939        try: 
    4040            self.db_installed_version = int(cursor.fetchone()[0]) 
    4141        except: 
    42             self.db_installed_version = 0 
    43             try: 
    44                 cursor.execute("INSERT INTO system (name,value) VALUES(%s,%s)", 
    45                                (self.db_version_key, self.db_installed_version)) 
    46                 db.commit() 
    47             except Exception, e: 
    48                 db.rollback() 
    49                 raise e 
    50  
     42            @self.env.with_transaction() 
     43            def do_init(db): 
     44              cursor = db.cursor() 
     45              self.db_installed_version = 0 
     46              cursor.execute("INSERT INTO system (name,value) VALUES(%s,%s)", 
     47                             (self.db_version_key, self.db_installed_version)) 
    5148     
    5249    def environment_created(self): 
    5350        """Called when a new Trac environment is created.""" 
     
    5754    def system_needs_upgrade(self): 
    5855        return self.db_installed_version < self.db_version 
    5956 
    60     def do_db_upgrade(self): 
     57    def do_db_upgrade(self, db): 
    6158        # Legacy support hack (supports upgrades from revisions r2495 or before) 
    62         db = self.env.get_db_cnx() 
    63         cursor = db.cursor() 
    6459        if self.db_installed_version == 0: 
    6560            try: 
     61                cursor = self.env.get_read_db().cursor() 
    6662                cursor.execute('SELECT * FROM work_log LIMIT 1') 
    67                 db.commit() 
    6863                # We've succeeded so we actually have version 1 
    6964                self.db_installed_version = 1 
    7065            except: 
    71                 db.rollback() 
     66                cursor.connection.rollback() 
     67                self.db_installed_version = 0 
    7268        # End Legacy support hack 
    7369 
    7470        # Do the staged updates 
     
    123119            # Updates complete, set the version 
    124120            cursor.execute("UPDATE system SET value=%s WHERE name=%s",  
    125121                           (self.db_version, self.db_version_key)) 
    126             db.commit() 
    127122        except Exception, e: 
    128123            self.log.error("WorklogPlugin Exception: %s" % (e,)); 
    129124            db.rollback() 
     
    132127 
    133128     
    134129    def needs_user_man(self): 
    135         db = self.env.get_db_cnx() 
     130        db = self.env.get_read_db() 
    136131        cursor = db.cursor() 
    137132        try: 
    138133            cursor.execute('SELECT MAX(version) FROM wiki WHERE name=%s', (user_manual_wiki_title,)) 
    139             db.commit() 
    140134            maxversion = int(cursor.fetchone()[0]) 
    141135        except: 
    142             db.rollback() 
     136            cursor.connection.rollback() 
    143137            maxversion = 0 
    144138 
    145139        return maxversion < user_manual_version 
    146140 
    147     def do_user_man_update(self): 
     141    def do_user_man_update(self, db): 
    148142        when = int(time.time()) 
    149         db = self.env.get_db_cnx() 
    150143        cursor = db.cursor() 
    151144        try: 
    152145            cursor.execute('INSERT INTO wiki (name,version,time,author,ipnr,text,comment,readonly) ' 
     
    176169        transactions. This is done implicitly after all participants have 
    177170        performed the upgrades they need without an error being raised. 
    178171        """ 
    179         def p(s): 
    180             print s 
    181             return True 
    182172        print "Worklog needs an upgrade" 
    183173        if self.system_needs_upgrade(): 
    184             p("Upgrading Database") 
    185             self.do_db_upgrade() 
     174            print " * Upgrading Database" 
     175            @self.env.with_transaction(db) 
     176            def real_do_db_upgrade(db): 
     177              self.do_db_upgrade(db) 
    186178        if self.needs_user_man(): 
    187             p("Upgrading usermanual") 
    188             self.do_user_man_update() 
     179            print " * Upgrading usermanual" 
     180            @self.env.with_transaction(db) 
     181            def real_do_user_man_update(db): 
     182              self.do_user_man_update(db) 
    189183        print "Done upgrading Worklog" 
    190184 
    191185 
  • worklog/manager.py

    diff -ru 0.11/worklog/manager.py 0.12/worklog/manager.py
    old new  
    6565        # If we get here then we know we can start work :) 
    6666        return True 
    6767 
    68     def save_ticket(self, tckt, db, msg): 
     68    def save_ticket(self, tckt, msg): 
    6969        # determine sequence number...  
    7070        cnum = 0 
    7171        tm = TicketModule(self.env) 
    72         for change in tm.grouped_changelog_entries(tckt, db): 
     72        for change in tm.grouped_changelog_entries(tckt, None): 
    7373            if change['permanent']: 
    7474                cnum += 1 
    7575        nowdt = self.now 
    7676        nowdt = to_datetime(nowdt) 
    77         tckt.save_changes(self.authname, msg, nowdt, db, cnum+1) 
     77        tckt.save_changes(self.authname, msg, nowdt, None, cnum+1) 
    7878        ## Often the time overlaps and causes a db error, 
    7979        ## especially when the trac integration post-commit hook is used. 
    8080        ## NOTE TO SELF. I DON'T THINK THIS IS NECESSARY RIGHT NOW... 
    8181        #count = 0 
    8282        #while count < 10: 
    8383        #    try: 
    84         #        tckt.save_changes(self.authname, msg, self.now, db, cnum+1) 
     84        #        tckt.save_changes(self.authname, msg, self.now, None, cnum+1) 
    8585        #        count = 42 
    8686        #    except Exception, e: 
    8787        #        self.now += 1 
    8888        #        count += 1 
    89         db.commit() 
    9089         
    9190        tn = TicketNotifyEmail(self.env) 
    9291        tn.notify(tckt, newticket=0, modtime=nowdt) 
     
    104103        # ticket modification. 
    105104 
    106105        # If the ticket is closed, we need to reopen it. 
    107         db = self.env.get_db_cnx() 
    108         tckt = Ticket(self.env, ticket, db) 
     106        tckt = Ticket(self.env, ticket) 
    109107 
    110108        if 'closed' == tckt['status']: 
    111109            tckt['status'] = 'reopened' 
    112110            tckt['resolution'] = '' 
    113             self.save_ticket(tckt, db, 'Automatically reopening in order to start work.') 
     111            self.save_ticket(tckt, 'Automatically reopening in order to start work.') 
    114112 
    115113            # Reinitialise for next test 
    116             db = self.env.get_db_cnx() 
    117             tckt = Ticket(self.env, ticket, db) 
     114            tckt = Ticket(self.env, ticket) 
    118115 
    119116             
    120117        if self.authname != tckt['owner']: 
     
    123120                tckt['status'] = 'accepted' 
    124121            else: 
    125122                tckt['status'] = 'new' 
    126             self.save_ticket(tckt, db, 'Automatically reassigning in order to start work.') 
     123            self.save_ticket(tckt, 'Automatically reassigning in order to start work.') 
    127124 
    128125            # Reinitialise for next test 
    129             db = self.env.get_db_cnx() 
    130             tckt = Ticket(self.env, ticket, db) 
     126            tckt = Ticket(self.env, ticket) 
    131127 
    132128 
    133129        if 'accepted' != tckt['status']: 
    134130            tckt['status'] = 'accepted' 
    135             self.save_ticket(tckt, db, 'Automatically accepting in order to start work.') 
     131            self.save_ticket(tckt, 'Automatically accepting in order to start work.') 
    136132 
    137133        # There is a chance the user may be working on another ticket at the moment 
    138134        # depending on config options 
    139135        if self.config.getbool('worklog', 'autostopstart'): 
    140136            # Don't care if this fails, as with these arguments the only failure 
    141137            # point is if there is no active task... which is the desired scenario :) 
    142             self.stop_work() 
     138            self.stop_work(comment='Stopping work on this ticket to start work on #%s.' % (ticket)) 
    143139            self.explanation = '' 
    144140  
    145         cursor = db.cursor() 
    146         cursor.execute('INSERT INTO work_log (worker, ticket, lastchange, starttime, endtime) ' 
    147                        'VALUES (%s, %s, %s, %s, %s)', 
    148                        (self.authname, ticket, self.now, self.now, 0)) 
    149         db.commit() 
     141        @self.env.with_transaction() 
     142        def do_log(db): 
     143          cursor = db.cursor() 
     144          cursor.execute('INSERT INTO work_log (worker, ticket, lastchange, starttime, endtime) ' 
     145                         'VALUES (%s, %s, %s, %s, %s)', 
     146                         (self.authname, ticket, self.now, self.now, 0)) 
    150147        return True 
    151148 
    152149     
     
    168165 
    169166        stoptime = float(stoptime) 
    170167         
    171         db = self.env.get_db_cnx(); 
    172         cursor = db.cursor() 
    173         cursor.execute('UPDATE work_log ' 
    174                        'SET endtime=%s, lastchange=%s, comment=%s ' 
    175                        'WHERE worker=%s AND lastchange=%s AND endtime=0', 
    176                        (stoptime, stoptime, comment, self.authname, active['lastchange'])) 
    177         db.commit() 
     168        @self.env.with_transaction() 
     169        def do_log(db): 
     170          cursor = db.cursor() 
     171          cursor.execute('UPDATE work_log ' 
     172                         'SET endtime=%s, lastchange=%s, comment=%s ' 
     173                         'WHERE worker=%s AND lastchange=%s AND endtime=0', 
     174                         (stoptime, stoptime, comment, self.authname, active['lastchange'])) 
    178175 
    179176        plugtne = self.config.getbool('worklog', 'timingandestimation') and self.config.get('ticket-custom', 'hours') 
    180177        plughrs = self.config.getbool('worklog', 'trachoursplugin') and self.config.get('ticket-custom', 'totalhours') 
     
    214211            if not message: 
    215212                message = 'Hours recorded automatically by the worklog plugin.' 
    216213 
    217             db = self.env.get_db_cnx() 
    218             tckt = Ticket(self.env, active['ticket'], db) 
     214            tckt = Ticket(self.env, active['ticket']) 
    219215 
    220216            if plugtne: 
    221217                tckt['hours'] = hours 
    222             self.save_ticket(tckt, db, message) 
     218            self.save_ticket(tckt, message) 
    223219            message = '' 
    224220 
    225221        if message: 
    226             db = self.env.get_db_cnx() 
    227             tckt = Ticket(self.env, active['ticket'], db) 
    228             self.save_ticket(tckt, db, message) 
     222            tckt = Ticket(self.env, active['ticket']) 
     223            self.save_ticket(tckt, message) 
    229224 
    230225        return True 
    231226 
    232227 
    233228    def who_is_working_on(self, ticket): 
    234         db = self.env.get_db_cnx() 
     229        db = self.env.get_read_db() 
    235230        cursor = db.cursor() 
    236231        cursor.execute('SELECT worker,starttime FROM work_log WHERE ticket=%s AND endtime=0', (ticket,)) 
    237232        try: 
     
    248243        if self.authname == 'anonymous': 
    249244            return None 
    250245 
    251         db = self.env.get_db_cnx() 
     246        db = self.env.get_read_db() 
    252247        cursor = db.cursor() 
    253248        cursor.execute('SELECT MAX(lastchange) FROM work_log WHERE worker=%s', (self.authname,)) 
    254249        row = cursor.fetchone() 
     
    289284        return task 
    290285 
    291286    def get_work_log(self, mode='all'): 
    292         db = self.env.get_db_cnx() 
     287        db = self.env.get_read_db() 
    293288        cursor = db.cursor() 
    294289        if mode == 'user': 
    295290            cursor.execute('SELECT wl.worker, s.value, wl.starttime, wl.endtime, wl.ticket, t.summary, t.status, wl.comment ' 
  • worklog/timeline_hook.py

    diff -ru 0.11/worklog/timeline_hook.py 0.12/worklog/timeline_hook.py
    old new  
    3434            ts_stop = to_timestamp(stop) 
    3535 
    3636            ticket_realm = Resource('ticket') 
    37             db = self.env.get_db_cnx() 
     37            db = self.env.get_read_db() 
    3838            cursor = db.cursor() 
    3939 
    4040            cursor.execute("""SELECT wl.worker,wl.ticket,wl.time,wl.starttime,wl.comment,wl.kind,t.summary,t.status,t.resolution,t.type 

comment:5 Changed 2 years ago by rjollos

  • Status changed from new to assigned

comment:6 Changed 2 years ago by rjollos

(In [12089]) Refs #10206, #10251:

  • Made the trunk compatible with Trac 0.11, by rolling out changes introduced in [9480] and later. There is nothing forcing us to adapt to the new Trac DB API at the moment, and it is easier to maintain a single code-base that is compatible back to Trac 0.11. The Trac DB API changed again in 1.0, so we are better off waiting and adapting to that API down the road anyway.
  • Attempted to cleanup the mess of import statements in every module. Modified the entry_points to adapt to these changes.
  • Made the XmlRpc lib an optional component. There is more work to do here still.

comment:7 Changed 2 years ago by rjollos

(In [12090]) Refs #10206, #10251:

  • Renamed timeline_hook.py to timeline.py, with the goal of making the source code layout match the standard for Trac plugins.
  • Fixed an error introduced in [12089] due to a missing import.


As in [12088], if your trac.ini file specifies the individual components to enable, you'll have to make the following change:

worklog.timeline_hook.worklogtimelineaddon = enabled

->

worklog.timeline.worklogtimelineeventprovider = enabled

comment:8 Changed 2 years ago by rjollos

What the plugin needs now is someone to do more thorough testing than I've had time for. I would greatly appreciate the effort, and you can expect rapid follow-up and resolution of any issues that are found, within hours or a day at the most.

comment:9 Changed 2 years ago by fommil

Thanks for this rjollos, but I never got to follow up when TH was down to say that I've now migrated to trac 1.0 :-)

comment:10 Changed 17 months ago by rjollos

  • Status changed from assigned to new

Add Comment

Modify Ticket

Action
as new .
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.