Repository: polygraph-python/polygraph

Issue:
Implement GraphQL type cache for GraphQL meta-types

Discussion:

Patch:
diff --git a/polygraph/types/basic_type.py b/polygraph/types/basic_type.py
index 3498d26..26e54b8 100644
--- a/polygraph/types/basic_type.py
+++ b/polygraph/types/basic_type.py
@@ -1,3 +1,5 @@
+from functools import wraps
+
 from polygraph.exceptions import PolygraphSchemaError, PolygraphValueError
 from polygraph.types.definitions import TypeDefinition, TypeKind
 from polygraph.utils.trim_docstring import trim_docstring
@@ -7,6 +9,22 @@ def typedef(type_):
     return type_.__type
 
 
+type_builder_registry = {}
+
+
+def type_builder_cache(method):
+    @wraps(method)
+    def wrapper(cls, *args):
+        unique_args = frozenset(args)
+        if (cls, unique_args) in type_builder_registry:
+            return type_builder_registry[(cls, unique_args)]
+        else:
+            return_val = method(cls, *args)
+            type_builder_registry[(cls, unique_args)] = return_val
+            return return_val
+    return wrapper
+
+
 class PolygraphTypeMeta(type):
     def __new__(cls, name, bases, namespace):
         default_description = trim_docstring(namespace.get("__doc__", ""))
@@ -95,6 +113,7 @@ class Union(PolygraphOutputType, PolygraphType):
     GraphQL Object types, but provides for no guaranteed fields between
     those types.
     """
+    @type_builder_cache
     def __new__(cls, *types):
         types = set(types)
         assert len(types) >= 2, "Unions must consist of more than 1 type"
@@ -135,6 +154,7 @@ class List(PolygraphType):
     each item in the list is serialized as per the item type.
     """
 
+    @type_builder_cache
     def __new__(cls, type_):
         type_name = typedef(type_).name
 
@@ -160,6 +180,7 @@ class NonNull(PolygraphType):
     """
     Represents a type for which null is not a valid result.
     """
+    @type_builder_cache
     def __new__(cls, type_):
         type_name = typedef(type_).name
 


Test patch:
diff --git a/polygraph/types/tests/test_union.py b/polygraph/types/tests/test_union.py
index 0c60c7d..07abe3d 100644
--- a/polygraph/types/tests/test_union.py
+++ b/polygraph/types/tests/test_union.py
@@ -5,11 +5,13 @@ from polygraph.types.basic_type import Union
 from polygraph.types.scalar import Float, Int, String
 
 
-@skip  # FIXME
+# @skip  # FIXME
 class UnionTypeTest(TestCase):
     def test_commutativity(self):
         self.assertEqual(Union(String, Int), Union(Int, String))
+        self.assertEqual(Union(String, Int, Float), Union(Float, String, Int, String))
 
+    @skip
     def test_associativity(self):
         self.assertEqual(
             Union(Union(String, Int), Float),
@@ -22,6 +24,7 @@ class UnionTypeTest(TestCase):
             Union(String, Int),
         )
 
+    @skip
     def test_pipe_operator_with_more_than_two_types(self):
         self.assertEqual(
             String | Int | Float,