Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

with transaction() doesn't work as expected #372

Open
MikeOfZen opened this issue Oct 22, 2022 · 0 comments
Open

with transaction() doesn't work as expected #372

MikeOfZen opened this issue Oct 22, 2022 · 0 comments

Comments

@MikeOfZen
Copy link

MikeOfZen commented Oct 22, 2022

I know that there is little development but it might be useful for someone if using ZODB in 2022.

when trying to store changes to persistent objects inside a ZODB.DB.transaction with block.
they are not stored, and no error is raised.
while doing the same between transaction.begin() and transaction.commit() calls does work.

It seems to me that is the only way to currently use a with block is to change objects directly through conn.root(),
that means all persistent objects must know full path from root to themselves, which is impractical.

there is also another weird behavior. where after storing an object for the first time, and retrieving it returns the same object, while the 2nd call and up will return a different object.
this trips tests trying to check if something is stored successfully, as it only happens once.

the following code tries to store attributes in a 2 level persistent hierarchy (represents actual code)

import ZODB
import ZODB.FileStorage
from persistent.mapping import PersistentMapping
import transaction

store=ZODB.FileStorage.FileStorage("temp1.db")
db=ZODB.DB(store)

def get_init(name, obj):
    with db.transaction(f"creating root[{name}]") as conn:
        try:
            return conn.root()[name]
        except KeyError:
            conn.root()[name] = obj()
            return conn.root()[name]

class A:
    def __init__(self):
        self.cfg = PersistentMapping()

    def __setitem__(self, key, value) -> None:
        transaction.begin()
        self.cfg[key+", inside block"] = value
        transaction.commit()
        with db.transaction():
            self.cfg[key+", inside with"] = value #does not work
        #these should be equivalent, no?

    def __iter__(self):
        return iter(self.cfg)

class Manager:
    def __init__(self):
        self.a1=get_init("testing", PersistentMapping) # set up the db, should only happen once

    def __setitem__(self, name, obj) -> None:
        """Registers in persistent storage"""
        with db.transaction(f"Adding testing:{name}") as conn:
            if name in conn.root()["testing"]:
                print(f"testing with same name {name} already exists in storage")
                return
            conn.root()["testing"][name] = obj

    def __getitem__(self, name: str):
        return db.open().root()["testing"][name]

dm=Manager()

initial=A() #only relevant for forst run
dm['a']=initial #only relevant for forst run

fromdb1= dm['a']
fromdb2= dm['a']

with db.transaction() as conn:
    fromdb1.cfg['updated from outer txn, directly'] = 1 #doed not work
    conn.root()['testing']['a'].cfg['updated from outer txn,through conn'] = 1
    #this should be equivalent but only the second one works

# transaction.begin()
# transaction.commit()
initial['new txn updated on initial'] = 1
fromdb1['new txn updated on retrieved 1']= 1
fromdb2['new txn updated on retrieved 2']= 1
# db.open().root()['testing']['a']['new txn updated on new db']=1

print(f"initial obj - {initial.cfg}")
print(f"from db obj 1- {fromdb1.cfg}")
print(f"from db obj 2- {fromdb2.cfg}")
print(f"\nnew from db obj- {dm['a'].cfg}")

print(f"\nis the initial obj and the first obj from db the same: {initial is fromdb1}")
print(f"is the initial obj and the second obj from db the same: {initial is fromdb2}")

The expected result is for all writing methods to work similarly, or the docs to reflect those limitations.

Thanks!!

What version of Python and Zope/Addons I am using:

Python 3.9.2, ZODB3, Win1064bit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant