I would like to ensure that the class is only instantiated within a "with" statement.
i.e. this one is ok:
with X() as x:
...
and this is not:
x = X()
How can I ensure such functionality?
The checking of a value, if it was created by the Object constructor, can simply be done by comparing the object's constructor property value with the corresponding Object constructor function reference.
In the main method, we created an object of the User2 class using the new keyword and called the getUser1Object() method. It returns an object of class User1 , which we later store in getUser1Object . To check if it is null, we call the isNull() method and pass the object getUserObject as a parameter.
All answers so far do not provide what (I think) OP wants directly.
(I think) OP wants something like this:
>>> with X() as x:
... # ok
>>> x = X() # ERROR
Traceback (most recent call last):
File "run.py", line 18, in <module>
x = X()
File "run.py", line 9, in __init__
raise Exception("Should only be used with `with`")
Exception: Should only be used with `with`
This is what I come up with, it may not be very robust, but I think it's closest to OP's intention.
import inspect
import linecache
class X():
def __init__(self):
if not linecache.getline(__file__,
inspect.getlineno(inspect.currentframe().f_back)).lstrip(
).startswith("with "):
raise Exception("Should only be used with `with`")
def __enter__(self):
return self
def __exit__(self, *exc_info):
pass
This will give the exact same output as I showed above as long as with
is in the same line with X()
when using context manager.
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With