Hi, I see your point with code like
with make_res1(...) as a, make_res2(...) as b, make_res3(...) as c:
... # use a,b,c here
The problem with this is that it’s quite difficult to put a “custom” code between make_res1()
and make_res2()
, between make_res2()
and make_res3()
etc. What if I need about five lines of code to “compute” an argument for make_res2
, given a
as the input?
Something which in my idea would be written as
def program():
a = yield make_resource1()
... # five more lines which now have access to the acquired `a`
# which result in a variable `a1`
b = yield make_resource2(a1)
... # few more lines which have access to both `a` and `b`
# which result in a variable `b1`
c = yield make_resource3(b1)
... # 5x the same as above
... # use the variables a,b,c,d,e...
# ...,e,d,c,b,a "unroll" automatically at the end of block
My example of such code (my motivation for exploring this area) could be
def test_functional_test_case():
a = create_a(name='a') # create an entity of type A via REST POST
all_as = list_as() # list all known As via REST GET
assert len(all_as) == 1 # assert the system has only one entity of type A
assert all_as[0].name == 'a' # assert the POST respects the supplied name
b = create_b(a_id=a.id) # create an entity of type B via REST POST
assert b.a_id == a.id # the POST respects the linking to the instance of A
... # more nested resources, more asserts
# the most recently acquired resource is released here
# ....
# DELETE b
# DELETE a
I know it’s possible to restructure the code like
with make_res1(...) as a,
asserts_and_make_res2_(...) as b,
asserts_make_res3(...) as c:
pass
but this require much more writing for each test case. The ultimate goal is to create a terse, nice syntax for each test which is just a “script” running some scenario, and needs to cleanup after itself at the end (even if some assert fails).
I hope this makes clear why I would like to avoid nesting with
s, either explicitely, or by using multiple resource managers within single with
statement.