toggling decorators

Related searches

What's the best way to toggle decorators on and off, without actually going to each decoration and commenting it out? Say you have a benchmarking decorator:

# deco.py
def benchmark(func):
  def decorator():
    # fancy benchmarking 
  return decorator

and in your module something like:

# mymodule.py
from deco import benchmark

class foo(object):
  @benchmark
  def f():
    # code

  @benchmark
  def g():
    # more code

That's fine, but sometimes you don't care about the benchmarks and don't want the overhead. I have been doing the following. Add another decorator:

# anothermodule.py
def noop(func):
  # do nothing, just return the original function
  return func

And then comment out the import line and add another:

# mymodule.py
#from deco import benchmark 
from anothermodule import noop as benchmark

Now benchmarks are toggled on a per-file basis, having only to change the import statement in the module in question. Individual decorators can be controlled independently.

Is there a better way to do this? It would be nice to not have to edit the source file at all, and to specify which decorators to use in which files elsewhere.

You could add the conditional to the decorator itself:

def benchmark(func):
    if not <config.use_benchmark>:
        return func
    def decorator():
    # fancy benchmarking 
    return decorator

Globally toggling the usage of decorator, Decorators affect the byte-code generated when the function definition following them is executed (which is before and separate from when the� This doesn't allow per-file toggling, and if the decorators are from a standard library or otherwise can't be edited it would have to be done in wrappers for every decorator. – engineerC Feb 1 '13 at 4:35

I've been using the following approach. It's almost identical to the one suggested by CaptainMurphy, but it has the advantage that you don't need to call the decorator like a function.

import functools

class SwitchedDecorator:
    def __init__(self, enabled_func):
        self._enabled = False
        self._enabled_func = enabled_func

    @property
    def enabled(self):
        return self._enabled

    @enabled.setter
    def enabled(self, new_value):
        if not isinstance(new_value, bool):
            raise ValueError("enabled can only be set to a boolean value")
        self._enabled = new_value

    def __call__(self, target):
        if self._enabled:
            return self._enabled_func(target)
        return target


def deco_func(target):
    """This is the actual decorator function.  It's written just like any other decorator."""
    def g(*args,**kwargs):
        print("your function has been wrapped")
        return target(*args,**kwargs)
    functools.update_wrapper(g, target)
    return g


# This is where we wrap our decorator in the SwitchedDecorator class.
my_decorator = SwitchedDecorator(deco_func)

# Now my_decorator functions just like the deco_func decorator,
# EXCEPT that we can turn it on and off.
my_decorator.enabled=True

@my_decorator
def example1():
    print("example1 function")

# we'll now disable my_decorator.  Any subsequent uses will not
# actually decorate the target function.
my_decorator.enabled=False
@my_decorator
def example2():
    print("example2 function")

In the above, example1 will be decorated, and example2 will NOT be decorated. When I have to enable or disable decorators by module, I just have a function that makes a new SwitchedDecorator whenever I need a different copy.

1-Toggle / 1-Decorator / Rocker - Combination Wall Plates, Get free shipping on qualified 1-Toggle / 1-Decorator / Rocker Combination Wall Plates or Buy Online Pick Up in Store today in the Electrical department. Decorators which take arguments other than a single function are essentially decorator factories which must create and return the actual decorator used. This is why the decorator in your question needed to be nested one level deeper.

Here is what I finally came up with for per-module toggling. It uses @nneonneo's suggestion as a starting point.

Random modules use decorators as normal, no knowledge of toggling.

foopkg.py:

from toggledeco import benchmark

@benchmark
def foo():
    print("function in foopkg")

barpkg.py:

from toggledeco import benchmark

@benchmark
def bar():
    print("function in barpkg")

The decorator module itself maintains a set of function references for all decorators that have been disabled, and each decorator checks for its existence in this set. If so, it just returns the raw function (no decorator). By default the set is empty (everything enabled).

toggledeco.py:

import functools

_disabled = set()
def disable(func):
    _disabled.add(func)
def enable(func):
    _disabled.discard(func)

def benchmark(func):
    if benchmark in _disabled:
        return func
    @functools.wraps(func)
    def deco(*args,**kwargs):
        print("--> benchmarking %s(%s,%s)" % (func.__name__,args,kwargs))
        ret = func(*args,**kwargs)
        print("<-- done")
    return deco

The main program can toggle individual decorators on and off during imports:

from toggledeco import benchmark, disable, enable

disable(benchmark) # no benchmarks...
import foopkg

enable(benchmark) # until they are enabled again
import barpkg

foopkg.foo() # no benchmarking 
barpkg.bar() # yes benchmarking

reload(foopkg)
foopkg.foo() # now with benchmarking

Output:

function in foopkg
--> benchmarking bar((),{})
function in barpkg
<-- done
--> benchmarking foo((),{})
function in foopkg
<-- done

This has the added bug/feature that enabling/disabling will trickle down to any submodules imported from modules imported in the main function.

EDIT:

Here's class suggested by @nneonneo. In order to use it, the decorator must be called as a function ( @benchmark(), not @benchmark ).

class benchmark:
    disabled = False

    @classmethod
    def enable(cls):
        cls.disabled = False

    @classmethod
    def disable(cls):
        cls.disabled = True

    def __call__(cls,func):
        if cls.disabled:
            return func
        @functools.wraps(func)
        def deco(*args,**kwargs):
            print("--> benchmarking %s(%s,%s)" % (func.__name__,args,kwargs))
            ret = func(*args,**kwargs)
            print("<-- done")
        return deco

Toggle/Decorator Wall Plates at Lowes.com, 30 products in Toggle/Decorator | Wall Plates. Filter Sort. Featured, Best Sellers, Highest Rated, New Arrivals. Sort By. slider closed. Standard Wall Plate Type:� Shapenty 13 Colors Plastic Toggle Single Hole Spring Loaded Elastic Drawstring Rope Cord Locks Clip Ends Round Ball Shape Luggage Lanyard Stopper Sliding Fastener Buttons, 4PCS for Each Color, 52PCS

I would implement a check for a config file inside the decorator's body. If benchmark has to be used according to the config file, then I would go to your current decorator's body. If not, I would return the function and do nothing more. Something in this flavor:

# deco.py
def benchmark(func):
  if config == 'dontUseDecorators': # no use of decorator
      # do nothing
      return func
  def decorator(): # else call decorator
      # fancy benchmarking 
  return decorator

What happens when calling a decorated function ? @ in

@benchmark
def f():
    # body comes here

is syntactic sugar for this

f = benchmark(f)

so if config wants you to overlook decorator, you are just doing f = f() which is what you expect.

feature-toggle-decorator, Feature Toggle Decorator. Travis npm David. A decorator that will only execute the wrapped function if it is given a truthy parameter, and� Technique(s) for decorating. When you are near your home, a button will appear at about 7 O'clock on your Radar -- "Toggle Decoration Mode." Clicking this will open your various "hooks" for modification. Unused hooks and Items you have already placed will "highlight". You are now in Decoration Mode. or You are no longer in Decoration Mode.

I don't think anyone has suggested this yet:

benchmark_modules = set('mod1', 'mod2') # Load this from a config file

def benchmark(func):
  if not func.__module__ in benchmark_modules:
      return func

  def decorator():
    # fancy benchmarking 
  return decorator

Each function or method has a __module__ attribute that is the name of the module where the function is defined. Create a whitelist (or blacklist if you prefer) of modules where benchmarking is to occur, and if you don't want to benchmark that module just return the original undecorated function.

Legrand� Decorator Plastic 1-Toggle Switch Combination Wall , Legrand. Features. Number of gangs: 2; Style: decorator; Thermoset. Specifications. Wall Plate Configuration. Rocker/GFCI, Combination, Toggle. Color/Finish. Toggling between his home in Los Angeles and his hometown of New York, David Netto is a Harvard architecture school dropout who revels in the unexpected, making traditionalism feel hip, and modernism like a warm and textured cocoon.

The decorator now takes care of this. One other change you’ve made is to add a raise inside of the exception handling blocks. This is so that the decorator will work properly. You could write the decorator to handle these errors, but since these exceptions only apply to urllib, you might be better off keeping the decorator the way it is. That

There can be many times when we need to set, clear or toggle a bit in C Language so in this article which is from answer on our website. You can use structs and then apply them in your code, to set, clear and toggle bits.

A slick way of hacking Being subtle in a game typically used not to get banned, by turning on your hacks at certain moments instead of keeping them on the whole game.

Comments
  • This doesn't allow per-file toggling, and if the decorators are from a standard library or otherwise can't be edited it would have to be done in wrappers for every decorator.
  • Will this work with a decorator that takes arguments?
  • Interesting approach. I'd go a bit further and make the decorator a full-up class, with enable() and disable() methods. A __call__() method allows it to behave like a decorator, albeit one with state. This will get rid of the enable and disable functions and the need to have a global _disabled set, since each individual decorator will maintain that state.