Modify

Opened 12 years ago

Closed 9 years ago

#10251 closed defect (fixed)

Unable to upgrade OS X tracd 0.11.7 database

Reported by: Sam Halliday Owned by: Ryan J Ollos
Priority: normal Component: WorkLogPlugin
Severity: normal Keywords:
Cc: Trac Release: 0.11

Description (last modified by Ryan J Ollos)

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

comment:1 Changed 12 years ago by Sam Halliday

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

comment:2 Changed 12 years ago by Ryan J Ollos

Description: modified (diff)

comment:3 Changed 12 years ago by Ryan J Ollos

Owner: changed from Colin Guthrie to Ryan J Ollos

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 12 years ago by Ryan J Ollos

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 12 years ago by Ryan J Ollos

Status: newassigned

comment:6 Changed 12 years ago by Ryan J Ollos

(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 12 years ago by Ryan J Ollos

(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 12 years ago by Ryan J Ollos

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 12 years ago by Sam Halliday

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 12 years ago by Ryan J Ollos

Status: assignednew

comment:11 Changed 9 years ago by Ryan J Ollos

Resolution: fixed
Status: newclosed

I won't be doing any more work to support Trac < 1.0.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Ryan J Ollos.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


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

 
Note: See TracTickets for help on using tickets.