I wrote a metaclass that I'm using for logging purposes in my python project. It makes every class automatically log all activity. The only issue is that I don't want to go into every file and have to add in:
__metaclass__ = myMeta
Is there a way to set the metaclass in the top level folder so that all the files underneath use that metaclass?
No, you can only specify the metaclass per class or per module. You cannot set it for the whole package.
In Python 3.1 and onwards, you can intercept the builtins.__build_class__
hook and insert a metaclass programatically, see Overriding the default type() metaclass before Python runs.
In Python 2.7, you could replace __builtins__.object
with a subclass that uses your metaclass. Like the builtins.__build_class__
hook, this is advanced hackery and break your code as much as getting your metaclass in everwhere.
Do so by replacing the object
reference on the __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()
this before importing your package and all new-style classes (those that can support a metaclass) will have your metaclass. Note that this behaviour now will propagate to all Python code not already loaded, including the standard library, as your package imports code. You probably want to use:
enable()
import package
disable()
to limit the effects.
Here's a simple technique. Just subclass the class itself with __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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With