How to create a python decorator programatically
Question: I am writing an app that creates/provides various Python decorators. I'd like
this app to be localized, including the names of the decorators. The
decorators would ultimately be used by other developers who are using my app
as a framework (think of my app as a test framework).

Ideally, I'd like to have the ability to create the decorators dynamically
based on the localization settings.

For instance, if the language selected is English, I'd like my decorator to be
named "apple", and if it's French, I'd like it to be named "pomme".

In the Python code, it would either look like:

    
    
    @apple
    def my_func():
        pass
    

or

    
    
    @pomme
    def my_func():
        pass
    

I ultimately want to have the flexibility to add many more languages without
having to modify or duplicate a bunch of code. Ideally, I would only have one
decorator function that would handle "apple" or "pomme" depending on the
settings.

What's the best way to achieve this?


Answer: First, don't do this. This will bring many problems upon you and make life
much harder for you and your users. Anyway, python is very dynamic so you can
do that.

Setup your package like that:

    
    
    yourpackage/
        __init__.py
        decorators.py
    

In `decorators.py`:

    
    
    # List all decorators you want to publish. Use english names here.
    __all__ = ['apple', 'orange', ...]
    
    # Here come implementations named in english
    def apple(...):
        ...
    
    ...
    

In `__init__.py`:

    
    
    # Whatever over submodules export or just []
    __all__ = [...]
    
    from . import decorators
    
    # Get locale somehow
    LOCALE = ...
    
    # This translation function could be as complex as you wish
    # I use a lookup in hard-coded dict
    TRANSLATIONS = {
        'fr': {'apple': u'pomme', ...},
        ...
    }
    def _translate_name(name):
        # If something is not translated we use default english name,
        # could be easily changed to raise error
        return TRANSLATIONS.get(LOCALE, {}).get(name, name)
    
    # Generate dynamic attributes to current module and add them to __all__
    import sys
    this_module = sys.modules[__name__]
    
    for name in decorators.__all__:
        translated = _translate_name(name)
        setattr(this_module, translated, getattr(decorators, name))
        __all__.append(translated)
    

Managing `__all__` in `__init__.py` is optional. This is to allow `from
yourmodule import *`.

