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

Sometimes junk is left in the transaction when #returning #143

Open
asottile opened this issue Aug 28, 2014 · 1 comment
Open

Sometimes junk is left in the transaction when #returning #143

asottile opened this issue Aug 28, 2014 · 1 comment
Labels

Comments

@asottile
Copy link
Collaborator

At the start of every Cheetah method, if there's no running transaction, Cheetah will create a dummy one and assign it to self.transaction. At the end of the method, if self.transaction is a dummy, Cheetah will set it back to None.

All is well and good, unless the method happens to use #return, in which case the cleanup code never runs. The cleanup should be in a finally block, instead.

Upshot of this problem:

#def foo():#return "hello"
#def bar():world
>>> tmpl.foo()
'hello'
>>> tmpl.bar()
<object object at 0x7f96764a40a0>

That anonymous object is actually the NO_CONTENT sentinel that Cheetah returns when it thinks it's being called within a transaction.

The fix is to clean up the transaction in a finally block.

asottile added a commit that referenced this issue Aug 28, 2014
@asottile
Copy link
Collaborator Author

Actually fixing this is a little more difficult than just slapping a try: finally: around this as there are other ways to exit the function.

For instance:

#def foo()
    #return 5
#end def

By putting the cleanup code in a finally block, you end up with compiled source which looks like this:

        trans = self.transaction
        if not trans:
            self.transaction = trans = DummyTransaction()
            _dummyTrans = True
        else:
            _dummyTrans = False
        write = trans.write
        SL = self._CHEETAH__searchList
        _filter = self._CHEETAH__currentFilter

        try:

            ## START - generated method body

            return 5

            ## END - generated method body

        finally:
            if _dummyTrans:
                self.transaction = None
                return trans.getvalue()
            else:
                return NO_CONTENT

Simplifying the problem from the above code:

def foo():
    x = ''
    try:
        return 5
    finally:
        return x

Will return ''

So somehow the finally block would both need to know whether or not the function has returned / excepted naturally and make a decision based on that. I assume some extra code would need to be added when #returning

asottile added a commit that referenced this issue Dec 26, 2014
@asottile asottile added the bug label Mar 6, 2016
asottile added a commit that referenced this issue May 5, 2016
asottile added a commit that referenced this issue Jun 2, 2016
asottile added a commit that referenced this issue Jun 2, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant