Repository: graphql-python/graphene
Pull request #1463 (2022-09-30 19:53:10)

Add copy function for GrapheneGraphQLType
Fixes https://github.com/graphql-python/graphene/issues/1333

First found in a Django project while upgrading to graphene 3. Django's `setUpTestData` tries to create a copy of a GrapheneGraphQLType and raises a `KeyError: 'graphene_type'`. This doesn't happen in graphene 2.1.8

codecov[bot]: # [Codecov](https://codecov.io/gh/graphql-python/graphene/pull/1463?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python) Report
Base: **95.88**% // Head: **95.87**% // Decreases project coverage by **`-0.00%`** :warning:
> Coverage data is based on head [(`1dbdb42`)](https://codecov.io/gh/graphql-python/graphene/pull/1463?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python) compared to base [(`ee1ff97`)](https://codecov.io/gh/graphql-python/graphene/commit/ee1ff975d71f6590eb6933d76d12054c9839774a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python).
> Patch coverage: 100.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #1463      +/-   ##
==========================================
- Coverage   95.88%   95.87%   -0.01%     
==========================================
  Files          51       50       -1     
  Lines        1726     1722       -4     
==========================================
- Hits         1655     1651       -4     
  Misses         71       71              
```


| [Impacted Files](https://codecov.io/gh/graphql-python/graphene/pull/1463?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python) | Coverage Δ | |
|---|---|---|
| [graphene/types/definitions.py](https://codecov.io/gh/graphql-python/graphene/pull/1463/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python#diff-Z3JhcGhlbmUvdHlwZXMvZGVmaW5pdGlvbnMucHk=) | `100.00% <100.00%> (ø)` | |
| [graphene/\_\_init\_\_.py](https://codecov.io/gh/graphql-python/graphene/pull/1463/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python#diff-Z3JhcGhlbmUvX19pbml0X18ucHk=) | | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/graphql-python/graphene/pull/1463?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=graphql-python).

erikwrede: Sorry for the long wait, thank you for the PR!
Can you please install & execute the `pre-commit` hooks to fix the linter?

keu210: > Sorry for the long wait, thank you for the PR! Can you please install & execute the `pre-commit` hooks to fix the linter?

sg. thanks!
erikwrede: Thank you for the contribution 🙂.
Expect release in next patch!

Patch:
diff --git a/graphene/types/definitions.py b/graphene/types/definitions.py
index e5505fd..ac574be 100644
--- a/graphene/types/definitions.py
+++ b/graphene/types/definitions.py
@@ -20,6 +20,11 @@ class GrapheneGraphQLType:
         self.graphene_type = kwargs.pop("graphene_type")
         super(GrapheneGraphQLType, self).__init__(*args, **kwargs)
 
+    def __copy__(self):
+        result = GrapheneGraphQLType(graphene_type=self.graphene_type)
+        result.__dict__.update(self.__dict__)
+        return result
+
 
 class GrapheneInterfaceType(GrapheneGraphQLType, GraphQLInterfaceType):
     pass


Test patch:
diff --git a/graphene/types/tests/test_definition.py b/graphene/types/tests/test_definition.py
index 0d8a95d..898fac7 100644
--- a/graphene/types/tests/test_definition.py
+++ b/graphene/types/tests/test_definition.py
@@ -1,4 +1,7 @@
+import copy
+
 from ..argument import Argument
+from ..definitions import GrapheneGraphQLType
 from ..enum import Enum
 from ..field import Field
 from ..inputfield import InputField
@@ -312,3 +315,16 @@ def test_does_not_mutate_passed_field_definitions():
         pass
 
     assert TestInputObject1._meta.fields == TestInputObject2._meta.fields
+
+
+def test_graphene_graphql_type_can_be_copied():
+    class Query(ObjectType):
+        field = String()
+
+        def resolve_field(self, info):
+            return ""
+
+    schema = Schema(query=Query)
+    query_type_copy = copy.copy(schema.graphql_schema.query_type)
+    assert query_type_copy.__dict__ == schema.graphql_schema.query_type.__dict__
+    assert isinstance(schema.graphql_schema.query_type, GrapheneGraphQLType)