Skip to content

Commit

Permalink
Show warning when trying to deep copy a schema (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cito committed Feb 7, 2021
1 parent 4c94212 commit 826b7a1
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/graphql/pyutils/frozen_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ def __iadd__(self, value):
def __hash__(self):
return hash(tuple(self.items()))

def __copy__(self):
def __copy__(self) -> "FrozenDict":
return FrozenDict(self)

copy = __copy__

def __deepcopy__(self, memo):
def __deepcopy__(self, memo: Dict) -> "FrozenDict":
return FrozenDict({k: deepcopy(v, memo) for k, v in self.items()})

def clear(self):
Expand Down
6 changes: 3 additions & 3 deletions src/graphql/pyutils/frozen_list.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from copy import deepcopy
from typing import List, TypeVar
from typing import Dict, List, TypeVar

from .frozen_error import FrozenError

Expand Down Expand Up @@ -35,10 +35,10 @@ def __imul__(self, value):
def __hash__(self):
return hash(tuple(self))

def __copy__(self):
def __copy__(self) -> "FrozenList":
return FrozenList(self)

def __deepcopy__(self, memo):
def __deepcopy__(self, memo: Dict) -> "FrozenList":
return FrozenList(deepcopy(value, memo) for value in self)

def append(self, x):
Expand Down
33 changes: 33 additions & 0 deletions src/graphql/type/definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ def to_kwargs(self) -> Dict[str, Any]:
extension_ast_nodes=self.extension_ast_nodes or FrozenList(),
)

def __copy__(self) -> "GraphQLNamedType": # pragma: no cover
return self.__class__(**self.to_kwargs())


def is_named_type(type_: Any) -> bool:
return isinstance(type_, GraphQLNamedType)
Expand Down Expand Up @@ -428,6 +431,9 @@ def to_kwargs(self) -> Dict[str, Any]:
specified_by_url=self.specified_by_url,
)

def __copy__(self) -> "GraphQLScalarType": # pragma: no cover
return self.__class__(**self.to_kwargs())


def is_scalar_type(type_: Any) -> bool:
return isinstance(type_, GraphQLScalarType)
Expand Down Expand Up @@ -539,6 +545,9 @@ def to_kwargs(self) -> Dict[str, Any]:
ast_node=self.ast_node,
)

def __copy__(self) -> "GraphQLField": # pragma: no cover
return self.__class__(**self.to_kwargs())

@property
def is_deprecated(self) -> bool:
return self.deprecation_reason is not None
Expand Down Expand Up @@ -649,6 +658,9 @@ def to_kwargs(self) -> Dict[str, Any]:
ast_node=self.ast_node,
)

def __copy__(self) -> "GraphQLArgument": # pragma: no cover
return self.__class__(**self.to_kwargs())


def is_required_argument(arg: GraphQLArgument) -> bool:
return is_non_null_type(arg.type) and arg.default_value is Undefined
Expand Down Expand Up @@ -736,6 +748,9 @@ def to_kwargs(self) -> Dict[str, Any]:
is_type_of=self.is_type_of,
)

def __copy__(self) -> "GraphQLObjectType": # pragma: no cover
return self.__class__(**self.to_kwargs())

@cached_property
def fields(self) -> GraphQLFieldMap:
"""Get provided fields, wrapping them as GraphQLFields if needed."""
Expand Down Expand Up @@ -856,6 +871,9 @@ def to_kwargs(self) -> Dict[str, Any]:
resolve_type=self.resolve_type,
)

def __copy__(self) -> "GraphQLInterfaceType": # pragma: no cover
return self.__class__(**self.to_kwargs())

@cached_property
def fields(self) -> GraphQLFieldMap:
"""Get provided fields, wrapping them as GraphQLFields if needed."""
Expand Down Expand Up @@ -974,6 +992,9 @@ def to_kwargs(self) -> Dict[str, Any]:
**super().to_kwargs(), types=self.types, resolve_type=self.resolve_type
)

def __copy__(self) -> "GraphQLUnionType": # pragma: no cover
return self.__class__(**self.to_kwargs())

@cached_property
def types(self) -> List[GraphQLObjectType]:
"""Get provided types."""
Expand Down Expand Up @@ -1095,6 +1116,9 @@ def __init__(
def to_kwargs(self) -> Dict[str, Any]:
return dict(**super().to_kwargs(), values=self.values.copy())

def __copy__(self) -> "GraphQLEnumType": # pragma: no cover
return self.__class__(**self.to_kwargs())

@cached_property
def _value_lookup(self) -> Dict[Any, str]:
# use first value or name as lookup
Expand Down Expand Up @@ -1232,6 +1256,9 @@ def to_kwargs(self) -> Dict[str, Any]:
ast_node=self.ast_node,
)

def __copy__(self) -> "GraphQLEnumValue": # pragma: no cover
return self.__class__(**self.to_kwargs())

@property
def is_deprecated(self) -> bool:
return self.deprecation_reason is not None
Expand Down Expand Up @@ -1321,6 +1348,9 @@ def to_kwargs(self) -> Dict[str, Any]:
else self.out_type,
)

def __copy__(self) -> "GraphQLInputObjectType": # pragma: no cover
return self.__class__(**self.to_kwargs())

@cached_property
def fields(self) -> GraphQLInputFieldMap:
"""Get provided fields, wrap them as GraphQLInputField if needed."""
Expand Down Expand Up @@ -1422,6 +1452,9 @@ def to_kwargs(self) -> Dict[str, Any]:
ast_node=self.ast_node,
)

def __copy__(self) -> "GraphQLInputField": # pragma: no cover
return self.__class__(**self.to_kwargs())


def is_required_input_field(field: GraphQLInputField) -> bool:
return is_non_null_type(field.type) and field.default_value is Undefined
Expand Down
3 changes: 3 additions & 0 deletions src/graphql/type/directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ def to_kwargs(self) -> Dict[str, Any]:
ast_node=self.ast_node,
)

def __copy__(self) -> "GraphQLDirective": # pragma: no cover
return self.__class__(**self.to_kwargs())


def is_directive(directive: Any) -> bool:
"""Test if the given value is a GraphQL directive."""
Expand Down
8 changes: 8 additions & 0 deletions src/graphql/type/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Union,
cast,
)
from warnings import warn

from ..error import GraphQLError
from ..language import ast
Expand Down Expand Up @@ -285,6 +286,13 @@ def to_kwargs(self) -> Dict[str, Any]:
assume_valid=self._validation_errors is not None,
)

def __copy__(self) -> "GraphQLSchema": # pragma: no cover
return self.__class__(**self.to_kwargs())

def __deepcopy__(self, memo_: Dict) -> "GraphQLSchema": # pragma: no cover
warn("Cannot deep copy a schema. Creating a flat copy instead.")
return self.__copy__()

def get_type(self, name: str) -> Optional[GraphQLNamedType]:
return self.type_map.get(name)

Expand Down

0 comments on commit 826b7a1

Please sign in to comment.