There is no straight forward way, as far as I know. But, you can have a boolean flag, to check if __enter__
was invoked, before the actual methods in the objects were called.
class MyContextManager(object):
def __init__(self):
self.__is_context_manager = False
def __enter__(self):
print "Entered"
self.__is_context_manager = True
return self
def __exit__(self, exc_type, exc_value, traceback):
print "Exited"
def do_something(self):
if not self.__is_context_manager:
raise Exception("MyContextManager should be used only with `with`")
print "I don't know what I am doing"
When you use it with with
,
with MyContextManager() as y:
y.do_something()
you will get
Entered
I don't know what I am doing
Exited
But, when you manually create an object, and invoke do_something
,
x = MyContextManager()
x.do_something()
you will get
Traceback (most recent call last):
File "/home/thefourtheye/Desktop/Test.py", line 22, in <module>
x.do_something()
File "/home/thefourtheye/Desktop/Test.py", line 16, in do_something
raise Exception("MyContextManager should be used only with `with`")
Exception: MyContextManager should be used only with `with`
Note: This is not a solid solution. Somebody can directly invoke __enter__
method alone, before calling any other methods and the __exit__
method may never be called in that case.
If you don't want to repeat that check in every function, you can make it a decorator, like this
class MyContextManager(object):
def __init__(self):
self.__is_context_manager = False
def __enter__(self):
print "Entered"
self.__is_context_manager = True
return self
def __exit__(self, exc_type, exc_value, traceback):
print "Exited"
def ensure_context_manager(func):
def inner_function(self, *args, **kwargs):
if not self.__is_context_manager:
raise Exception("This object should be used only with `with`")
return func(self, *args, **kwargs)
return inner_function
@ensure_context_manager
def do_something(self):
print "I don't know what I am doing"