Python: setting a metaclass for all files in a folder

I wrote a metaclass that I use for logging in my python project. It allows each class to automatically register all activity. The only problem is that I don't want to go into every file and have to add:

__metaclass__ = myMeta 

Is there a way to set the metaclass in the top-level folder so that all files below it use this metaclass?

+8
python metaclass environment-variables package project
source share
2 answers

No, you can only specify a metaclass for each class or for each module. You cannot install it for the whole package.

In Python 3.1 and later, you can builtins.__build_class__ and programmatically insert a metaclass, see Overriding the default metaclass () before running Python .

In Python 2.7, you can replace __builtins__.object with a subclass that uses your metaclass. Like the builtins.__build_class__ , it is an advanced hacker and breaks your code in the same way as getting your metaclass anywhere.

Do this by replacing the object reference with __builtin__ module :

 import __builtin__ class MetaClass(type): def __new__(mcls, name, *args): # do something in the metaclass return super(MetaClass, mcls).__new__(mcls, name, *args) orig_object = __builtin__.orig_object class metaobject(orig_object): __metaclass__ = MetaClass def enable(): # *replace* object with one that uses your metaclass __builtin__.object = metaobject def disable(): __builtin__.object = orig_object 

Run enable() before importing your package, and all new-style classes (those that can support the metaclass) will have your metaclass. Note that this behavior will now apply to all Python code that has not yet been loaded, including the standard library, since your package imports the code. You probably want to use:

 enable() import package disable() 

to limit the effects.

+6
source share

Here is a simple method. Just subclass the class itself with the __metaclass__ attribute in the subclass. This process can be automated.

util.py

 class A(object): def __init__(self, first, second): self.first = first self.second = second def __str__(self): return '{} {}'.format(self.first, self.second) 

main.py

 from datetime import datetime from util import A def meta(*args): cls = type(*args) setattr(cls, 'created', datetime.now().ctime()) return cls try: print(A.created) except AttributeError as e: print(e) class A(A): __metaclass__ = meta print(A.created, str(A('Michael', 'Jackson'))) 

Test

 $ python main.py type object 'A' has no attribute 'created' ('Wed Mar 9 22:58:16 2016', 'Michael Jackson') 
+1
source share

All Articles