From 938c6f5e134031061a3349f3b19a620ec383c982 Mon Sep 17 00:00:00 2001 From: Christophe de Vienne Date: Mon, 4 Jun 2012 19:22:32 +0200 Subject: [PATCH] Attempting a on-demand resolution of datatypes references, so we don't need to call resolve_references anymore. It works with python 2, but not yet python 3 (some weakref issues) --- tox.ini | 1 + wsme/root.py | 1 - wsme/tests/test_types.py | 11 ++++++++++- wsme/types.py | 31 ++++++++++++++++++++++++------- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/tox.ini b/tox.ini index 097b68c..ad6595d 100644 --- a/tox.ini +++ b/tox.ini @@ -32,6 +32,7 @@ deps= webtest coverage simplejson + zope.interface<=3.8.99 transaction<=1.1.1 [testenv:sphinxext] diff --git a/wsme/root.py b/wsme/root.py index 107189b..2016fef 100644 --- a/wsme/root.py +++ b/wsme/root.py @@ -117,7 +117,6 @@ class WSRoot(object): :rtype: list of (path, :class:`FunctionDefinition`) """ if self._api is None: - self.__registry__.resolve_references() self._api = [i for i in scan_api(self)] return self._api diff --git a/wsme/tests/test_types.py b/wsme/tests/test_types.py index 1290d13..b8515ee 100644 --- a/wsme/tests/test_types.py +++ b/wsme/tests/test_types.py @@ -287,6 +287,15 @@ class TestTypes(unittest.TestCase): types.register_type(A) types.register_type(B) - types.registry.resolve_references() assert A.b.datatype is B + + def test_base(self): + class B1(types.Base): + b2 = types.wsattr('B2') + + class B2(types.Base): + b2 = types.wsattr('B2') + + assert B1.b2.datatype is B2, repr(B1.b2.datatype) + assert B2.b2.datatype is B2 diff --git a/wsme/types.py b/wsme/types.py index c891a1d..9e25def 100644 --- a/wsme/types.py +++ b/wsme/types.py @@ -203,13 +203,15 @@ class wsattr(object): #: The attribute name on the public of the api. #: Defaults to :attr:`key` self.name = name - self._datatype = datatype + self._datatype = (datatype,) #: True if the attribute is mandatory self.mandatory = mandatory #: Default value. The attribute will return this instead #: of :data:`Unset` if no value has been set. self.default = default + self.complextype = None + def __get__(self, instance, owner): if instance is None: return self @@ -231,6 +233,9 @@ class wsattr(object): self.__set__(instance, Unset) def _get_datatype(self): + if isinstance(self._datatype, tuple): + self._datatype = \ + self.complextype().__registry__.resolve_type(self._datatype[0]) if isinstance(self._datatype, weakref.ref): return self._datatype() return self._datatype @@ -320,6 +325,7 @@ def inspect_class(class_): attrdef.key = name if attrdef.name is None: attrdef.name = name + attrdef.complextype = weakref.ref(class_) attributes.append(attrdef) setattr(class_, name, attrdef) @@ -378,6 +384,7 @@ class Registry(object): class_._wsme_attributes = None class_._wsme_attributes = inspect_class(class_) + class_.__registry__ = self self.complex_types.append(weakref.ref(class_)) def lookup(self, typename): @@ -402,15 +409,25 @@ class Registry(object): } return type_ - def resolve_references(self): - for ct in self.complex_types: - ct = ct() - for attr in list_attributes(ct): - attr.datatype = self.resolve_type(attr.datatype) - # Default type registry registry = Registry() def register_type(class_): return registry.register(class_) + + +class BaseMeta(type): + def __new__(cls, name, bases, dct): + r = type.__new__(cls, name, bases, dct) + if bases[0] is object: + return r + if getattr(r, '__registry__', None) is None: + registry.register(r) + else: + r.__registry__.register(r) + return r + + +class Base(object): + __metaclass__ = BaseMeta