Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to access a function's attributes/parameters within a ContextDecorator?

I'm trying to write a context manager decorator using Python's contextlib.ContextDecorator class.

Is there a way to access the decorated function's parameters within the context manager?

Here's an example of what I'm doing:

from contextlib import ContextDecorator

class savePen(ContextDecorator):
    def __enter__(self):
        self.prevPen = self.dc.GetPen()     # AttributeError
        return self

    def __exit__(self, *exc):
        self.dc.SetPen(self.prevPen)
        return False

Given the above, this:

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style

should be equivalent to:

def func(dc, param1, param2):
    prevPen = dc.GetPen()
    # do stuff, possibly changing the pen style
    dc.SetPen(prevPen)

I've scoured the docs for contextlib and haven't found anything useful.

Does anyone know how to access the decorated functions' attributes from within a ContextDecorator class?

EDIT1:

As @chepner said in this response, ContextDecorator is sugar for

def func(dc, param1, param2):
    with savePen():
        ...

and that it cannot access the functions' parameters.

However, in this case, whatever runs inside of with savePen() has access to the function parameters dc, param1, and param2. This makes me think that I should be able to access them using ContextDecorator.

For example, this is valid:

def func(dc, param1, param2):
    with savePen():
        print(param1)
like image 224
dthor Avatar asked Jul 30 '15 18:07

dthor


People also ask

How to use the DOT property accessor in JavaScript?

Choose the dot property accessor when the property name is known ahead of time. The dot property accessor works correctly when the property name is a valid identifier. An identifier in JavaScript contains Unicode letters, $, _, and digits 0..9, but cannot start with a digit.

How to access object properties in JavaScript?

3 Ways To Access Object Properties in JavaScript 1. Dot property accessor. You can use the dot property accessor in a chain to access deeper properties: object.prop1. 2. Square brackets property accessor. The first expression should evaluate to an object and the second expression should... 3. Object ...

When does the DOT property accessor work correctly?

The dot property accessor works correctly when the property name is a valid identifier. An identifier in JavaScript contains Unicode letters, $, _, and digits 0..9, but cannot start with a digit. This is not a problem, because usually, the property names are valid identifiers: e.g. name, address, street, createdBy.


1 Answers

contextlib.contextmanager seems more appropriate here. Note that, like anything else, you can't access the local variables of a function body from outside the function (short of introspection hacks, anyway).

@contextlib.contextmanager
def savePen(dc):
    prevPen = dc.GetPen()
    yield
    dc.SetPen(prevPen)

with savePen(dc):
    func(dc, param1, param2)

Note that with a ContextDecorator, the context manager is instantiated with no arguments, that is

@savePen()
def func(dc, param1, param2):
    # do stuff, possibly changing the pen style

is syntactic sugar (according to the documentation) for

def func(dc, param1, param2):
    with savePen():
        ...

and so there's no way to tell savePen which object (dc) to work with.

like image 197
chepner Avatar answered Sep 24 '22 02:09

chepner