[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] PixelArray question



Brian Fisher wrote:
On 8/26/07, Marcus von Appen <mva@xxxxxxxxxxxx> wrote:
   sf = pygame.Surface ((10, 20))
   sf.fill ((0, 0, 0))
   with PixelArray(sf) as p:
       buffer_request(p)

The PixelArray __enter__ method simply returns self. __exit__ unlocks the
parent surface and invalidates the array.
That's definitely something that should be supported once Python 2.6 is
available. As far as I understand p's lifetime will be limited to the
with ... : block anyhow, so it'll be (implicitly) deleted once the scope
is left (and the surface thus will be automatically unlocked - even in
the current implementation).
For now it's nothing we need to take care of however.

looking at the PEP fro the with statement, I don't think the "with"
statement will affect anything about when the pixelarray object will
be deleted, and moreover I don't see any reason to think p's lifetime
would be limited to the with block (the p is optional)
http://www.python.org/dev/peps/pep-0343/


The name "p" remains visible outside the with statement block.

it seems that Lenard's code block there would be translated to this:
        sf = pygame.Surface ((10, 20))
        sf.fill ((0, 0, 0))
        mgr = (EXPR)
        exit = mgr.__exit__  # Not calling it yet
        value = mgr.__enter__()
        exc = True
        try:
            try:
                p = value  # Only if "as VAR" is present
                buffer_request(p)
            except:
                # The exceptional case is handled here
                exc = False
                if not exit(*sys.exc_info()):
                    raise
                # The exception is swallowed if exit() returns true
        finally:
            # The normal and non-local-goto cases are handled here
            if exc:
                exit(None, None, None)

That code looks to me like the following would happen in this order:
1. PixelArray object is constructed
2. the PixelArray __enter__ method is executed and the return value is p

In my example "p" is just the object constructed in step 1.
def __enter__(self):
   return self

3. the block inside the with statement is executed
4. the PixelArray __exit__ method is executed

__exit__ simply releases the surface lock:
def __exit__(self, exc_type, exc_val, exc_tb):  # exception stuff is ignored
   self.unlock()  # Assumes PixelArray has an unlock method.
   return False  # let any exceptions propagate

5. the PixelArray object and whatever is returned from __enter__
delete sometime after the scope block containing the with is done


The PixelArray object is deleted upon exit of the scope enclosing of the with statement, unless there is an unhandled exception.

[snip]
Also, even though support for this isn't all that important until 2.6,
the PEP says with can be used and supported with this import line:
    from __future__ import with_statement


That is so some module that has an identifier "with" does not automatically break in Python 2.5.

...I could be totally wrong though so I wrote a testscript that looks
at how it all goes down with print statements. I wasn't able to test
the actual "with" statement (I don't have access to python 2.5 right
now) though

Here are the results:

>python TestWithResults.py
--- Testing exploded with
SourceClass.__init__
before with statement
TestClass.__init__
TestClass.__enter__
TestClass.do_work_on
TestClass.__exit__
after with statement
TestClass object is still in scope
TestClass.__del__
SourceClass.__del__
--- Testing with
SourceClass.__init__
before with statement
TestClass.__init__
TestClass.__enter__
TestClass.do_work_on
TestClass.__exit__
after with statement
TestClass object is still in scope
TestClass.__del__
SourceClass.__del__


I had to move the __future__ statement to the top of the file, but otherwise it is unchanged.

--
Lenard Lindstrom
<len-l@xxxxxxxxx>