"""This is a convenient way to deeply nest try/finally statements."""
__docformat__ = "restructuredtext"
# Created: Tue Oct 11 08:42:23 PDT 2005
# Author: Shannon -jj Behrens
# Email: jjinux@users.sourceforge.net
#
# Copyright (c) Shannon -jj Behrens. All rights reserved.
from traceback import print_exc
def tryFinally(tasks, handleFinallyException=None):
"""This is a convenient way to deeply nest try/finally statements.
It is appropriate for complicated resource initialization and destruction.
For instance, if you have a list of 50 things that need to get intialized
and later destructed via using try/finally (especially if you need to
create the list dynamically) this function is appropriate.
Given::
tasks = [
((f_enter_0, enter_0_args, enter_0_kargs),
(f_exit_0, exit_0_args, exit_0_kargs)),
((f_enter_1, enter_1_args, enter_1_kargs),
(f_exit_1, exit_1_args, exit_1_kargs)),
((f_enter_2, enter_2_args, enter_2_kargs),
(f_exit_2, exit_2_args, exit_2_kargs))
]
Execute::
f_enter_0(*enter_0_args, **enter_0_kargs)
try:
f_enter_1(*enter_1_args, **enter_1_kargs)
try:
f_enter_2(*enter_2_args, **enter_2_kargs)
try:
pass
finally:
try:
f_exit_2(*exit_2_args, **exit_2_kargs)
except Exception, e:
handleFinallyException(e)
finally:
try:
f_exit_1(*exit_1_args, **exit_1_kargs)
except Exception, e:
handleFinallyException(e)
finally:
try:
f_exit_0(*exit_0_args, **exit_0_kargs)
except Exception, e:
handleFinallyException(e)
tasks
See the example above. Note that you can leave out parts of the tuples
by passing shorter tuples. For instance, here are two examples::
# Second tuple missing.
((f_enter_2, enter_2_args, enter_2_kargs),)
# Leave out args or args and kargs.
((f_enter_2,),
(f_exit_2, exit_2_args))
Don't forget that a tuple of 1 item is written ``(item,)``. This is an
amazingly easy thing to do.
handleFinallyException(e)
This is a callback that gets called if an exception, ``e``, is raised
in a finally block. By default, traceback.print_exc is called.
"""
def defaultFinallyExceptionHandler(e):
print_exc()
def castTwoParts(first):
lenFirst = len(first)
default = ((), ())
max = len(default)
if lenFirst >gt; max:
raise ValueError("""tasks must be a list of tuples of the form (enterTuple, exitTuple).""", first)
return first + default[lenFirst:]
def doNothing(*args, **kargs):
pass
def castFunctionArgsKargs(fTuple):
lenFTuple = len(fTuple)
default = (doNothing, (), {})
max = len(default)
if lenFTuple >gt; max:
raise ValueError("""Each tuple in tasks is a pair of tuples that look like (f, args, kargs).""",
fTuple)
return fTuple + default[lenFTuple:]
if not len(tasks):
return
if not handleFinallyException:
handleFinallyException = defaultFinallyExceptionHandler
first, others = tasks[0], tasks[1:]
first = castTwoParts(first)
first = (castFunctionArgsKargs(first[0]),
castFunctionArgsKargs(first[1]))
((fEnter, fEnterArgs, fEnterKargs),
(fExit, fExitArgs, fExitKargs)) = first
fEnter(*fEnterArgs, **fEnterKargs)
try:
tryFinally(others, handleFinallyException)
finally:
try:
fExit(*fExitArgs, **fExitKargs)
except Exception, e:
handleFinallyException(e)
if __name__ == '__main__':
from cStringIO import StringIO
def printEverything(*args, **kargs): print >gt;>gt;buf, `args`, `kargs`
def refuseArgs(): print >gt;>gt;buf, "refused args"
def raiseValueError(): raise ValueError
def finallyExceptionHandler(e): print >gt;>gt;buf, "caught exception in finally"
tasks = [
((printEverything, ("enter_0_args",), {"in": "in"}),
(printEverything, ("exit_0_args",))),
((printEverything,),
(raiseValueError,)),
((refuseArgs,),)
]
result = """('enter_0_args',) {'in': 'in'}
() {}
refused args
caught exception in finally
('exit_0_args',) {}
"""
buf = StringIO()
tryFinally(tasks, finallyExceptionHandler)
assert buf.getvalue() == result
I decided to give Ubuntu 20.04 a try on my 2015 15" MacBook Pro. I didn't actually install it; I just live booted from a USB thumb drive which was enough to try out everything I wanted. In summary, it's not perfect, and issues with my camera would prevent me from switching, but given the right hardware, I think it's a really viable option. The first thing I wanted to try was what would happen if I plugged in a non-HiDPI screen given that my laptop has a HiDPI screen. Without sub-pixel scaling, whatever scale rate I picked for one screen would apply to the other. However, once I turned on sub-pixel scaling, I was able to pick different scale rates for the internal and external displays. That looked ok. I tried plugging in and unplugging multiple times, and it didn't crash. I doubt it'd work with my Thunderbolt display at work, but it worked fine for my HDMI displays at home. I even plugged it into my TV, and it stuck to the 100% scaling I picked for the othe
Comments