[Zope] get_transaction().commit() does not commit: Zope: OOBTree definition & creation

Harm_Kirchhoff at mail.digital.co.jp Harm_Kirchhoff at mail.digital.co.jp
Sun Nov 16 20:07:56 EST 2003


  Thank you very much for your comments. 
Yes, I shortened the code, because otherwise the mails get too long. This 
is a basic accounting db, using Zope, which I intend to make publicly 
available once it is stable, so disclosing the code is no problem at all, 
just a question of length and this mailing list is already very active.
I researched further, and it seems that it is the question of where you 
define the OOBTree. 
I naively thought you simply define the entire DB as an OOBTree, but I 
realized that you only define sub-branches as OOBTrees and only upon 
creation. I made some changes and now it runs. However, I am puzzled by 
your comment that an OOBTree does not allow these transactions. How do you 
open a db with an OOBTree ??? 
When I open the file AccDB.fs with a text editor I can see, that my code 
must have been executed, because I can see the strings for the nodes !
The new code (again shortened, because the original is still work in 
progress and contains a lot of scrap, if you want the full code, because 
there is something fundamentally strange, let me know I can mail it 
directly.):
(PS: I know that my style is extremely unpythonic, but don't be too 
strict, I am only on python since a couple of months)

The main loop:

def test():
    db = AccountingDB()
    print 'Database file:',db.mountedDB
    # create a ledger
    r = db.ledger_create('001','2003')
    if r[0] == False:
        if r[1][0] == 2:
            print "The database file does not exist, Will be created new 
now!"
            db.mount_db(True)
            db.unmount_db()
            print "DB Created, now creating ledger anew !"
            r = db.ledger_create('001','2003')
            if r[0] == False : print 'failed miserably ! aborting ...'  ; 
return
            print "Created new DB & ledger, congrats !"
        else:
            print r
            print "Can not find DB file. Aborting ..."
            return
    # open the ledger
    print db.ledger_open('001','2003')
    print db.ledger_close()
Produces this output in the shell, provided the db file does not exist:
>>> AccDB.test()
Database file: C:\Documents and Settings\Kirchhoff\My 
Documents\Python\AccDB\AccDB.fs
The database file does not exist, Will be created new now!
DB Created, now creating ledger anew !
Created new DB & ledger, congrats !
(True, 'Opened:C:\\Documents and Settings\\Kirchhoff\\My 
Documents\\Python\\AccDB\\AccDB.fs')
(True, 'Closed')


The functions, 
ledger_create:
Creates a new DB and a basic ledger in dictionary form and closes the 
ledger.

ledger_open:
Opens an existing ledger.

ledger_close:
Closes an existing ledger.

I am 100% sure that the code is executed, because all functions perform 
basic entry checks and do abort if they can not find a valid ledger 
structure in place. On top, the function basic_validation() performs an 
extensive validation of the infrastructure, so that the code would abort 
with an error message, if the ledgers were not correctly created:

    def __init__(self):
        # Defines variables to be used throughout the instance, while the
        # session is in place.
        #
        self.mountedDB   = 'C:\Documents and Settings\Kirchhoff\My 
Documents\Python\AccDB\AccDB.fs'
        self.cust_acc    = ''
        self.fin_yr      = ''
        self.open        = ''
        self.maxper      = 13
        self.periods     = ','.join(map(str,range(1,self.maxper+1)))
        self.open_per    = ''
        self.closed_pers = []
        self.user        = ''

    def mount_db(self, flag=False):
        """ Mounts the accounting database."""
        # Check that my DB exists. This is the default. However, when the 
very first ledger is created,
        # Zope must create a DB and for this, the check must be skipped.
        if flag == False:
            r = hkToolBox.Test_File(self.mountedDB,'w')
            if r == False:
                r = hkToolBox.Test_File(self.mountedDB, 'e')
                if r == False                                      : 
return(False,[2,'File does not exist'])
                else                                               : 
return(False,[1,'File can not be opened for writing'])

        # Mount DB:
        # Note: If you have an error in this section, upon re-run it is 
likely
        # that the db is still locked and that FileStorage wil fail, 
because no connection.close() was executed.
        # Solution: End python and restart python.
        self.st = FileStorage.FileStorage(self.mountedDB)
        self.db = DB(self.st)
        self.connection = self.db.open()
        self.dbroot = self.connection.root()
        #self.dbroot = OOBTree()                     I found that when you 
define
        #                                            entire root as 
OOBTree on every start
        #                                            data is not stored.
        return (True,'db mounted:'+ self.mountedDB)

    def unmount_db(self):
        """ Unmounts the database. This is required to free the locking 
that ZODB tracks in its
            lock table."""
 
        get_transaction().commit()     # commit any changes that may be 
pending.
        self.connection.close()
        self.db.close()
        self.st.close() 

    def ledger_create(self,CstNo,FY):
        """Creates a new ledger for a customer and a new financial 
year."""        #Input Validation: CstNo & FY must be strings.
        # Input validation:
        if type(CstNo) <> str                                  : 
return(False,[1000,'CstNo no string'])
        if type(FY) <> str                                     : 
return(False,[1001,'FY must be string'])

        r = self.mount_db()
        if r[0] == False                                       : 
return(False,r[1])
 
        # Ensure that this account and financial year does not exist:
        if self.dbroot.has_key(CstNo)         == True :
            if self.dbroot[CstNo].has_key(FY) == True :
                self.unmount_db()                              ; 
return(False, FY+' exist for '+CstNo)
        else :                # if CstNo sub-branch does not exist
            self.dbroot[CstNo] = OOBTree()
                              # Only define the OOBTree once, upon 
creation.
            self._p_changed = 1
            get_transaction().commit()
 
        # Since neither this FY or neither this FY nor CstNo do exist, 
create base ledger:
        # Note: This ledger must pass the basic_validation() !

        zero=chr(0)+chr(0)+chr(0)+chr(0) 
        # Set up basic infrastructure 
        self.dbroot[CstNo] = { FY :{} }
        self.dbroot[CstNo] [FY] = { 'ini' : {} , 'accper' : {} }
        self.dbroot[CstNo] [FY] ['ini'] ['lastE']  = zero 
        self.dbroot[CstNo] [FY] ['ini'] ['lastS']  = zero
        self.dbroot[CstNo] [FY] ['ini'] ['locked'] = ''
        self.dbroot[CstNo] [FY] ['ini'] ['closed'] = []
        self.dbroot[CstNo] [FY] ['ini'] ['open']   = '1'
        self.dbroot[CstNo] [FY] ['ini'] ['templ']  = ''

        self.dbroot[CstNo] [FY] ['1'] = {}
        self.dbroot[CstNo] [FY] ['1'] ['E']        = {} 
        self.dbroot[CstNo] [FY] ['1'] ['S']        = {}
        self.dbroot[CstNo] [FY] ['1'] ['accno']    = {}
        self.dbroot[CstNo] [FY] ['1'] ['acba' ]    = {}

        self._p_changed = 1
        get_transaction().commit()
        # I recommend always to leave validation here, because it ensures 
that both routines
        # are always in concordance & will help in future debugging.
        r = self.basic_validation(CstNo,FY)
        self.unmount_db()
 
        if r[0] == False                                       : return 
(False, r[1]) 
        return (True,[0,'ledger created ok'])
 
    def ledger_open(self,CstNo, FY, User='guest'):
        """iniializes the class with basic settings."""
        # Initializes the database environment.
        # These variables will be used throughout the instance to access 
records.
        # If this ledger does not yet exist, a new one is created.
        # Returns:
        #    Tuple:(False/True , 'error message if False')

        #Input Validation
        if type(CstNo) <> str                                  : 
return(False,[1000,'CstNo must be string'])
        if type(FY) <> str                                     : 
return(False,[1001,'FY must be string'])

        r = self.mount_db()
        if r[0] == False                                       : 
return(False,r[1])

        # if you need to validate the user (pathword &c.), do it here.
 
        # Verify that DB is not locked. If not, lock it now.
        if self.dbroot.has_key(CstNo)     == False :
            self.unmount_db()                                  ; 
return(False, [3,'Customer account does not exist'])

        if self.dbroot[CstNo].has_key(FY) == False :
            self.unmount_db()                                  ; 
return(False, [4,'Financial Year does not exist'])
 
        # Test that this branch (Fin Year of Customer) is not in use & 
reserve:
        if self.dbroot[CstNo] [FY] ['ini'] ['locked'] <> ''    : 
return(False,[5,self.dbroot[CstNo] [FY] ['ini'] ['locked']])
        self.dbroot[CstNo] [FY] ['ini'] ['locked'] = User
        get_transaction().commit()

        # Debug: Validate the database:
        m=self.basic_validation(CstNo,FY)
        if m[0] == False  : self.unmount_db()                  ; 
return(False, m[1])

        # Set the environment variables for the instance
        self.cust_acc    = CstNo
        self.fin_yr      = FY
        self.user        = User
        self.open_per    = self.dbroot[self.cust_acc] [self.fin_yr] 
['ini'] ['open']
        self.closed_pers = self.dbroot[self.cust_acc] [self.fin_yr] 
['ini'] ['closed']

        # ... happy booking !
        return(True,'Opened:' + self.mountedDB)

    def ledger_close(self):
        """Closes currently opened ledger & unmounts DB."""
        # check that environment variables are proper and that branch is 
actually locked.
        if self.dbroot.has_key(self.cust_acc)      == False :
            self.unmount_db()                                  ; 
return(False, [3,'Custumer account does not exist'])
        if self.dbroot[self.cust_acc].has_key(self.fin_yr) == False :
            self.unmount_db()                                  ; 
return(False, [4,'Financial Year does not exist'])

        # unlock branch
        u0 = self.dbroot[self.cust_acc] [self.fin_yr] ['ini'] ['locked']
        self.dbroot[self.cust_acc] [self.fin_yr] ['ini'] ['locked'] = ''
        self._p_changed = 1
        get_transaction().commit()
        # unmount DB
        self.unmount_db()
        # reset all variables.
        u1 = self.user
        self.__init__()
        # just for checking consistency:
        if u0 <> u1                                            : 
return(False,[6,'User who closed was not same as opened'])
        return(True, 'Closed') 






Dieter Maurer <dieter at handshake.de>
2003/11/15 04:50

 
        宛先:   Harm_Kirchhoff at mail.digital.co.jp
        cc:     zope at zope.org
        件名:   Re: [Zope] get_transaction().commit() does not commit


Harm_Kirchhoff at mail.digital.co.jp wrote at 2003-11-14 19:28 +0900:
 > I guess it is another newbie question, but I can not save data to the 
DB:
 > 
 > I open the DB like this:
 > 
 >         self.st = FileStorage.FileStorage(self.mountedDB)
 >         self.db = DB(self.st)
 >         self.connection = self.db.open()
 >         self.dbroot = self.connection.root()
 >         self.dbroot = OOBTree()
 >         return (True,'db mounted:'+ self.mountedDB)
 > 
 >  Next I make a number of changes to self.dbroot:
 > 
 >         self.dbroot[CstNo] [FY] ['1'] ['E']        = {} 

Are you sure, this code is executed?

An "OOBTree" would not allow these operations.

 > ...
 > When I open again and try verify whether the keys exist, using 
 > self.dbroot.has_key(CstNo)   # for example
 > they do not exist.
 > Looking at the DB with a text editor to see what is in there, reveals 
that 
 > there is nothing.
 > The entire program runs through without any error.

There must be more about which you do not tell us.
Somewhere inside this darkness is something that confuses you.

-- 
Dieter






More information about the Zope mailing list