From 19ad211069b2ed73376f043e7661f73b1d15dd80 Mon Sep 17 00:00:00 2001
From: davebshow <davebshow@gmail.com>
Date: Thu, 7 Jul 2016 13:27:53 -0400
Subject: [PATCH] simplify metaclass

---
 goblin/api.py        | 37 ++++++++++++++++++++++++++++++++++++-
 goblin/meta.py       |  8 +-------
 goblin/properties.py | 41 +++++------------------------------------
 3 files changed, 42 insertions(+), 44 deletions(-)

diff --git a/goblin/api.py b/goblin/api.py
index e920ff9..b0bec97 100644
--- a/goblin/api.py
+++ b/goblin/api.py
@@ -270,8 +270,43 @@ class Edge(meta.Element):
     target = property(gettarget, settarget, deltarget)
 
 
+class VertexPropertyDescriptor:
+    """Descriptor that validates user property input and gets/sets properties
+       as instance attributes."""
+
+    def __init__(self, name, vertex_property):
+        self._name = '_' + name
+        self._vertex_property = vertex_property.__class__
+        self._data_type = vertex_property.data_type
+        self._default = vertex_property.default
+
+    def __get__(self, obj, objtype):
+        if obj is None:
+            return self._vertex_property
+        default = self._default
+        if default:
+            default = self._data_type.validate(default)
+            default = self._vertex_property(self._default)
+        return getattr(obj, self._name, default)
+
+    def __set__(self, obj, val):
+        if isinstance(val, (list, tuple , set)):
+            vertex_property = []
+            for v in val:
+                v = self._data_type.validate(v)
+                vertex_property.append(
+                    self._vertex_property(self._data_type, value=v))
+
+        else:
+            val = self._data_type.validate(val)
+            vertex_property = self._vertex_property(self._data_type, value=val)
+        setattr(obj, self._name, vertex_property)
+
+
 class VertexProperty(meta.Element, abc.BaseProperty):
 
+    __descriptor__ = VertexPropertyDescriptor
+
     def __init__(self, data_type, *, value=None, default=None):
         if isinstance(data_type, type):
             data_type = data_type()
@@ -293,4 +328,4 @@ class VertexProperty(meta.Element, abc.BaseProperty):
 
     def __repr__(self):
         return '<{}(type={}, value={})'.format(self.__class__.__name__,
-                                               self.__data_type__, self.value)
+                                               self._data_type, self.value)
diff --git a/goblin/meta.py b/goblin/meta.py
index 0531080..8764da5 100644
--- a/goblin/meta.py
+++ b/goblin/meta.py
@@ -22,13 +22,7 @@ class ElementMeta(type):
         for k, v in namespace.items():
             if isinstance(v, abc.BaseProperty):
                 props[k] = v
-                if not isinstance(v, properties.Property):
-                    vertex_property = v.__class__
-                    v = properties.VertexPropertyDescriptor(
-                        k, vertex_property, v.data_type, default=v.default)
-                else:
-                    v = properties.PropertyDescriptor(
-                        k, v.data_type, default=v.default)
+                v = v.__descriptor__(k, v)
             new_namespace[k] = v
         new_namespace['__mapping__'] = mapper.create_mapping(namespace,
                                                              props)
diff --git a/goblin/properties.py b/goblin/properties.py
index ab74549..f6ab215 100644
--- a/goblin/properties.py
+++ b/goblin/properties.py
@@ -11,10 +11,10 @@ class PropertyDescriptor:
     """Descriptor that validates user property input and gets/sets properties
        as instance attributes."""
 
-    def __init__(self, name, data_type, *, default=None):
+    def __init__(self, name, prop):
         self._name = '_' + name
-        self._data_type = data_type
-        self._default = default
+        self._data_type = prop.data_type
+        self._default = prop.default
 
     def __get__(self, obj, objtype):
         if obj is None:
@@ -31,43 +31,12 @@ class PropertyDescriptor:
             del attr
 
 
-class VertexPropertyDescriptor:
-    """Descriptor that validates user property input and gets/sets properties
-       as instance attributes."""
-
-    def __init__(self, name, vertex_property, data_type, *, default=None):
-        self._name = '_' + name
-        self._vertex_property = vertex_property
-        self._data_type = data_type
-        self._default = default
-
-    def __get__(self, obj, objtype):
-        if obj is None:
-            return self._vertex_property
-        default = self._default
-        if default:
-            default = self._data_type.validate(default)
-            default = self._vertex_property(self._default)
-        return getattr(obj, self._name, default)
-
-    def __set__(self, obj, val):
-        if isinstance(val, (list, tuple , set)):
-            vertex_property = []
-            for v in val:
-                v = self._data_type.validate(v)
-                vertex_property.append(
-                    self._vertex_property(self._data_type, value=v))
-
-        else:
-            val = self._data_type.validate(val)
-            vertex_property = self._vertex_property(self._data_type, value=val)
-        setattr(obj, self._name, vertex_property)
-
-
 class Property(abc.BaseProperty):
     """API class used to define properties. Replaced with
       :py:class:`PropertyDescriptor` by :py:class:`api.ElementMeta`."""
 
+    __descriptor__ = PropertyDescriptor
+
     def __init__(self, data_type, *, default=None):
         if isinstance(data_type, type):
             data_type = data_type()
-- 
GitLab