Reputation: 17601
Let us say I have a python method to get last synced changelist in p4. (The question itself is not related to p4 but only a basic python question)
def get_last_synced_changelist(p4port, client_name, p4 = None):
with P4Connection(p4port) as p4:
last_change_list = p4.run_changes("-m1", "@%s" % client_name)
if last_change_list:
return last_change_list[0]["change"]
else:
return None
The caller of this method can either supply p4port which is a String or they could supply the p4 object in itself. My requirement is that if a "p4" object is supplied I want to run the method body without the with context, i.e, I dont want the enter or exit method called on the p4. This is because the responsibility of closing/entering p4 object lies now with the caller. If p4 object is not supplied the with syntax needs to be constructed in this program using the p4port string.
Can someone tell me what is the best way of structuring this method? I want to change the body as less as possible. Basically something like
p4 or with P4Connection(p4port) as p4:
p4.run_changes(...)
But I am not sure what the best syntax is.
Upvotes: 1
Views: 167
Reputation: 104712
In Python 2 you'll probably want to create your own context manager, either a dummy one as @glglgl shows in his answer, or perhaps one that wraps up the optional creation of the P4Connection:
import contextlib
@contextlib.context_manager
def p4_context(p4port, p4=None):
p4 is None:
with P4Connection(p4port) as p4:
yield p4
else:
yield p4
def get_last_synced_changelist(p4port, client_name, p4 = None):
with p4_context(p4port, p4) as p4:
last_change_list = p4.run_changes("-m1", "@%s" % client_name)
if last_change_list:
return last_change_list[0]["change"]
else:
return None
If you were using Python 3.3 or later, you could instead use the awesome new contextlib.ExitStack
class:
import contextlib
def get_last_synced_changelist(p4port, client_name, p4 = None):
with contextlib.ExitStack() as stack:
if p4 is None:
p4 = stack.enter_context(P4Connection(p4port))
last_change_list = p4.run_changes("-m1", "@%s" % client_name)
if last_change_list:
return last_change_list[0]["change"]
else:
return None
Upvotes: 0
Reputation: 91017
You can create a dummy context manager:
import contextlib
@contextlib.contextmanager
def dummyctx(x):
yield x
def get_last_synced_changelist(p4port, client_name, p4=None):
if p4 is None:
ctx = P4Connection(p4port)
else:
ctx = dummyctx(p4)
with ctx as p4:
last_change_list = p4.run_changes("-m1", "@%s" % client_name)
if last_change_list:
return last_change_list[0]["change"]
else:
return None
Upvotes: 2
Reputation:
It's not directly possible, with
is a compound statement and can't be embedded in expressions like this. But you can make use of the fact that your function also supports "borrowing" a resource:
def get_last_synced_changelist(p4port, client_name, p4 = None):
if p4 is None:
with P4Connection(p4port) as p4:
return get_last_synced_changelist(p4port, client_name, p4)
last_change_list = p4.run_changes("-m1", "@%s" % client_name)
if last_change_list:
return last_change_list[0]["change"]
else:
return None
This approach even works if you have separate functions for the two paths (which may make sense in this example, as p4port
is apparently not used when an existing P4Connection
is passed in).
Upvotes: 2