I don't know whether it's really desirable, but it doesn't seem to be hard to achieve the 'direct syntactic port of ActiveRecord:' using an auxilliary queue and a registration callback e.g.,:
_RegisterPropertyQueue = []
class ActiveRecord(object):
class __metaclass__(type):
def __init__(cls, name, bases, dct):
setattr(cls, "_has_many", set())
setattr(cls, "_belongs_to", set())
setattr(cls, "_has_and_belongs_to_many", set())
for obj in _RegisterPropertyQueue:
obj.__register__(cls)
del _RegisterPropertyQueue[:]
class RegisterProperty(object):
def __new__(cls, *args, **kw):
o = object.__new__(cls)
_RegisterPropertyQueue.append(o)
return o
def __register__(self, cls):
raise NotImplementedError
class Relation(RegisterProperty):
def __init__(self, other):
self.other = other
class has_many(Relation):
def __register__(self, cls):
other = self.other
cls._has_many.add(other)
other._belongs_to.add(cls)
class belongs_to(Relation):
def __register__(self, cls):
other = self.other
cls._belongs_to.add(other)
other._has_many.add(cls)
class has_and_belongs_to_many(Relation):
def __register__(self, cls):
other = self.other
other._has_and_belongs_to_many.add(cls)
cls._has_and_belongs_to_many.add(other)
class ProjectManager(ActiveRecord): pass
class Milestones(ActiveRecord): pass
class Categories(ActiveRecord): pass
class Person(ActiveRecord):
belongs_to(ProjectManager)
has_many(Milestones)
has_and_belongs_to_many(Categories)
assert ProjectManager in Person._belongs_to
assert Milestones in Person._has_many
assert Person in Categories._has_and_belongs_to_many