Seja o pequeno código, assim como listado no example.py do projeto tOSM:
from tosm.objects import *
from tosm.properties import *
class Address(Tobj):
street = StringProperty()
number = PositiveIntegerProperty()
class Person(Tobj):
name = StringProperty()
tel = PositiveIntegerProperty()
address = ObjectProperty()
carlos = Person("Carlos", 99887766, Address(number=99, street="Koningstraat"))
dumped = carlos.dump()
recreated_carlos = Person.load(dumped)
Basicamente a parte que nos interessa são as duas últimas linhas: eu crio uma representação em estruturas Python dos meus objetos e, em seguida, recrio a classe (uma nova e inteiramente independente) a partir desta representação.
Para recriar o objeto do tipo Person, a classe Person provê um método da classe chamado load que consome esta estrutura python e devolve uma instância de si mesmo (esse método pertence na verdade à classe objects.Tobj, e é herdada pela classe Person).
vamos dar uma olhada em como o método load recria uma instância de Tobj:
@classmethod
def load(cls, raw):
"""
Recreate a tOSM object based on a structure
"""
tobj = cls()
for key,value in raw.items():
if key in tobj._tosm_properties:
meta_obj = cls.__getattribute__(cls,key)
if isinstance(meta_obj, ObjectProperty):
obj_class = meta_obj._object_definition
obj = obj_class.load(value)
setattr(tobj, key, obj)
#MAIS COISAS QUE OMITI POR CONVENIÊNCIA!!!!
return tobj
O método load recebe uma estrutura Python (dicionário) e itera sobre esta, procurando por properties da classe que casem com o nome da chave do dicionário recebido. Uma vez que se têm a tupla (key,value) da estrutura de entrada, para recriar eu preciso saber qual é a property da classe que têm o mesmo nome (nome contido em key). A princípio a maneira de se capturar o conteúdo (método, variável, etc.) de um objeto, tendo o nome do conteúdo é:
meta_obj = getattr(cls, key)
Porém o meu conteúdo é uma property, ela sobrescreveu o método get. Ou seja, quando eu fizer meta_obj = getattr(cls, key) invés de recuperar a property, eu estou invocando o método get da property.
A saída para isso é:
meta_obj = cls.__getattribute__(cls,key)
Com isso eu capturo a própria property e posso recriar uma instância dela com base no conteúdo passado dentro da estrutura para o método load.
obj_class = meta_obj._object_definition
obj = obj_class.load(value)
setattr(tobj, key, obj)
Se alguém achar um jeito mais simples, favor compartilhar a solução.