Skip to content

Commit 3ca6d64

Browse files
committed
Make more lists read only and add ReadOnlyDict
1 parent ac329dc commit 3ca6d64

File tree

9 files changed

+60
-19
lines changed

9 files changed

+60
-19
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ a query language for APIs created by Facebook.
1313
[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
1414

1515
The current version 1.0.4 of GraphQL-core-next is up-to-date with GraphQL.js version
16-
14.3.0. All parts of the API are covered by an extensive test suite of currently 1776
16+
14.3.0. All parts of the API are covered by an extensive test suite of currently 1778
1717
unit tests.
1818

1919

graphql/pyutils/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
from .or_list import or_list
2222
from .quoted_or_list import quoted_or_list
2323
from .suggestion_list import suggestion_list
24-
from .read_only_list import ReadOnlyError, ReadOnlyList
24+
from .read_only_error import ReadOnlyError
25+
from .read_only_list import ReadOnlyList
26+
from .read_only_dict import ReadOnlyDict
2527

2628
__all__ = [
2729
"camel_to_snake",
@@ -41,4 +43,5 @@
4143
"suggestion_list",
4244
"ReadOnlyError",
4345
"ReadOnlyList",
46+
"ReadOnlyDict",
4447
]

graphql/pyutils/read_only_dict.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
__all__ = ["ReadOnlyDict"]
2+
3+
from .read_only_error import ReadOnlyError
4+
5+
6+
class ReadOnlyDict(dict):
7+
"""Dictionary that can only be read, but not changed."""
8+
9+
def __delitem__(self, key):
10+
raise ReadOnlyError
11+
12+
def __setitem__(self, key, value):
13+
raise ReadOnlyError
14+
15+
def __add__(self, value):
16+
return dict.__add__(self, value)
17+
18+
def __iadd__(self, value):
19+
raise ReadOnlyError
20+
21+
def clear(self):
22+
raise ReadOnlyError
23+
24+
def pop(self, key, default=None):
25+
raise ReadOnlyError
26+
27+
def popitem(self):
28+
raise ReadOnlyError
29+
30+
def setdefault(self, key, default=None):
31+
raise ReadOnlyError
32+
33+
def update(self, other=None):
34+
raise ReadOnlyError
35+

graphql/pyutils/read_only_error.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
__all__ = ["ReadOnlyError"]
2+
3+
4+
class ReadOnlyError(TypeError):
5+
"""Error when trying to write to a read only collection."""

graphql/pyutils/read_only_list.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
__all__ = ["ReadOnlyError", "ReadOnlyList"]
1+
__all__ = ["ReadOnlyList"]
22

3-
4-
class ReadOnlyError(TypeError):
5-
"""Error when trying to write to a ReadOnlyList."""
3+
from .read_only_error import ReadOnlyError
64

75

86
class ReadOnlyList(list):

graphql/type/introspection.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
is_union_type,
2222
)
2323
from ..language import DirectiveLocation, print_ast
24-
from ..pyutils import inspect
24+
from ..pyutils import inspect, ReadOnlyDict
2525
from .scalars import GraphQLBoolean, GraphQLString
2626

2727
__all__ = [
@@ -492,7 +492,7 @@ class TypeKind(Enum):
492492

493493
# Since double underscore names are subject to name mangling in Python,
494494
# the introspection classes are best imported via this dictionary:
495-
introspection_types = {
495+
introspection_types = ReadOnlyDict({
496496
"__Schema": __Schema,
497497
"__Directive": __Directive,
498498
"__DirectiveLocation": __DirectiveLocation,
@@ -501,7 +501,7 @@ class TypeKind(Enum):
501501
"__InputValue": __InputValue,
502502
"__EnumValue": __EnumValue,
503503
"__TypeKind": __TypeKind,
504-
}
504+
})
505505

506506

507507
def is_introspection_type(type_: Any) -> bool:

graphql/type/scalars.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Any
33

44
from ..error import INVALID
5-
from ..pyutils import inspect, is_finite, is_integer
5+
from ..pyutils import inspect, is_finite, is_integer, ReadOnlyDict
66
from ..language.ast import (
77
BooleanValueNode,
88
FloatValueNode,
@@ -241,10 +241,10 @@ def parse_id_literal(ast, _variables=None):
241241
)
242242

243243

244-
specified_scalar_types = {
244+
specified_scalar_types = ReadOnlyDict({
245245
type_.name: type_
246246
for type_ in (GraphQLString, GraphQLInt, GraphQLFloat, GraphQLBoolean, GraphQLID)
247-
}
247+
})
248248

249249

250250
def is_specified_scalar_type(type_: Any) -> bool:

graphql/validation/specified_rules.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from typing import List
22

3+
from ..pyutils import ReadOnlyList
4+
35
from .rules import RuleType
46

57
# Spec Section: "Executable Definitions"
@@ -99,7 +101,7 @@
99101
# The order of the rules in this list has been adjusted to lead to the
100102
# most clear output when encountering multiple validation errors.
101103

102-
specified_rules: List[RuleType] = [
104+
specified_rules: List[RuleType] = ReadOnlyList([
103105
ExecutableDefinitionsRule,
104106
UniqueOperationNamesRule,
105107
LoneAnonymousOperationRule,
@@ -126,9 +128,9 @@
126128
VariablesInAllowedPositionRule,
127129
OverlappingFieldsCanBeMergedRule,
128130
UniqueInputFieldNamesRule,
129-
]
131+
])
130132

131-
specified_sdl_rules: List[RuleType] = [
133+
specified_sdl_rules: List[RuleType] = ReadOnlyList([
132134
LoneSchemaDefinitionRule,
133135
UniqueOperationTypesRule,
134136
UniqueTypeNamesRule,
@@ -143,4 +145,4 @@
143145
UniqueArgumentNamesRule,
144146
UniqueInputFieldNamesRule,
145147
ProvidedRequiredArgumentsOnDirectivesRule,
146-
]
148+
])

tests/pyutils/test_read_only_list.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def cannot_write():
6666
rol.sort()
6767
with raises(ReadOnlyError):
6868
rol.reverse()
69+
assert rol == [1, 2, 3]
6970

7071
def can_add_rol():
7172
rol1 = ReadOnlyList([1, 2])
@@ -75,6 +76,3 @@ def can_add_rol():
7576
def can_add_tuple():
7677
rol = ReadOnlyList([1, 2])
7778
assert rol + (3, 4) == [1, 2, 3, 4]
78-
79-
def read_only_error_is_type_error():
80-
assert issubclass(ReadOnlyError, TypeError)

0 commit comments

Comments
 (0)