RedFox
RedFox

Reputation: 141

Is there a way to solve __enter__ AttributeError in ContextDecorator?

I'm trying to create a ContextDecorator. Here's my code:

class CmTag(ContextDecorator):

    def __init__(self, cm_tag_func):
        self.cm_tag_func = cm_tag_func
        
    def __enter__(self):        
        return self

    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None:
            traceback.print_exception(exc_type, exc_value, tb)
        else:
            name = self.cm_tag_func.__name__
            print(name)

    def __call__(self, **kwargs):

        name = self.cm_tag_func.__name__
        print(name)
        print(kwargs)
        self.cm_tag_func(**kwargs)

@CmTag
def testing(**kwargs):
    pass

with testing(foo='bar') as t:
    print('a test')

I expect the output to be:

testing
{'foo':'bar'}
a test
testing

That is, it first prints the name of the function. Then it prints out kwargs as a dictionary. Then it prints out whatever is there inside the context manager, which is 'a test', in this case. Finally upon exit, it prints out the name of the function again.

Instead, it says:

testing
{'foo': 'bar'}
Traceback (most recent call last):
  File "/workspace/sierra/src/sierra/test.py", line 32, in <module>
    with testing(foo='bar') as t:
AttributeError: __enter__

I saw other solutions saying __enter__ was not defined. But I've done it here.

How do I rectify this? Thanks.

Upvotes: 0

Views: 100

Answers (1)

Jonathan1609
Jonathan1609

Reputation: 1919

In the line

with testing(foo='bar') as t:
    print('a test')

since testing is an object of CmTag, you perform a call to __call__, however, you return None in that method instead of returning self. Adding return self at the end of that method would fix it.

Upvotes: 1

Related Questions