Skip to content

Commit 8f426f7

Browse files
committed
Rename read_only_list/dict to frozen_list/dict
Since GraphQL.js now uses frozen objects instead of ReadOnlyArrays, this is a better analogy, and Python already has frozenset(). Replicates graphql/graphql-js@f55c2a3
1 parent b0dc730 commit 8f426f7

17 files changed

+184
-184
lines changed

docs/modules/pyutils.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ PyUtils
2020
.. autofunction:: or_list
2121
.. autofunction:: quoted_or_list
2222
.. autofunction:: suggestion_list
23-
.. autoclass:: ReadOnlyError
24-
.. autoclass:: ReadOnlyList
25-
.. autoclass:: ReadOnlyDict
23+
.. autoclass:: FrozenError
24+
.. autoclass:: FrozenList
25+
.. autoclass:: FrozenDict

docs/modules/validation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ rules in this list has been adjusted to lead to the most clear output when encou
2828
multiple validation errors:
2929

3030
.. autodata:: specified_rules
31-
:annotation: = ReadOnlyList([...])
31+
:annotation: = FrozenList([...])
3232

3333
Spec Section: "Executable Definitions"
3434

graphql/pyutils/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +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_error import ReadOnlyError
25-
from .read_only_list import ReadOnlyList
26-
from .read_only_dict import ReadOnlyDict
24+
from .frozen_error import FrozenError
25+
from .frozen_list import FrozenList
26+
from .frozen_dict import FrozenDict
2727

2828
__all__ = [
2929
"camel_to_snake",
@@ -41,7 +41,7 @@
4141
"or_list",
4242
"quoted_or_list",
4343
"suggestion_list",
44-
"ReadOnlyError",
45-
"ReadOnlyList",
46-
"ReadOnlyDict",
44+
"FrozenError",
45+
"FrozenList",
46+
"FrozenDict",
4747
]
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
1-
__all__ = ["ReadOnlyDict"]
1+
__all__ = ["FrozenDict"]
22

3-
from .read_only_error import ReadOnlyError
3+
from .frozen_error import FrozenError
44

55

6-
class ReadOnlyDict(dict):
6+
class FrozenDict(dict):
77
"""Dictionary that can only be read, but not changed."""
88

99
def __delitem__(self, key):
10-
raise ReadOnlyError
10+
raise FrozenError
1111

1212
def __setitem__(self, key, value):
13-
raise ReadOnlyError
13+
raise FrozenError
1414

1515
def __add__(self, value):
1616
return dict.__add__(self, value)
1717

1818
def __iadd__(self, value):
19-
raise ReadOnlyError
19+
raise FrozenError
2020

2121
def clear(self):
22-
raise ReadOnlyError
22+
raise FrozenError
2323

2424
def pop(self, key, default=None):
25-
raise ReadOnlyError
25+
raise FrozenError
2626

2727
def popitem(self):
28-
raise ReadOnlyError
28+
raise FrozenError
2929

3030
def setdefault(self, key, default=None):
31-
raise ReadOnlyError
31+
raise FrozenError
3232

3333
def update(self, other=None):
34-
raise ReadOnlyError
34+
raise FrozenError

graphql/pyutils/frozen_error.py

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

3-
from .read_only_error import ReadOnlyError
3+
from .frozen_error import FrozenError
44

55

6-
class ReadOnlyList(list):
6+
class FrozenList(list):
77
"""List that can only be read, but not changed."""
88

99
def __delitem__(self, key):
10-
raise ReadOnlyError
10+
raise FrozenError
1111

1212
def __setitem__(self, key, value):
13-
raise ReadOnlyError
13+
raise FrozenError
1414

1515
def __add__(self, value):
1616
if isinstance(value, tuple):
1717
value = list(value)
1818
return list.__add__(self, value)
1919

2020
def __iadd__(self, value):
21-
raise ReadOnlyError
21+
raise FrozenError
2222

2323
def __mul__(self, value):
2424
return list.__mul__(self, value)
2525

2626
def __imul__(self, value):
27-
raise ReadOnlyError
27+
raise FrozenError
2828

2929
def append(self, x):
30-
raise ReadOnlyError
30+
raise FrozenError
3131

3232
def extend(self, iterable):
33-
raise ReadOnlyError
33+
raise FrozenError
3434

3535
def insert(self, i, x):
36-
raise ReadOnlyError
36+
raise FrozenError
3737

3838
def remove(self, x):
39-
raise ReadOnlyError
39+
raise FrozenError
4040

4141
def pop(self, i=None):
42-
raise ReadOnlyError
42+
raise FrozenError
4343

4444
def clear(self):
45-
raise ReadOnlyError
45+
raise FrozenError
4646

4747
def sort(self, *, key=None, reverse=False):
48-
raise ReadOnlyError
48+
raise FrozenError
4949

5050
def reverse(self):
51-
raise ReadOnlyError
51+
raise FrozenError

graphql/pyutils/read_only_error.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

graphql/type/directives.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, Dict, Sequence, cast
22

33
from ..language import ast, DirectiveLocation
4-
from ..pyutils import inspect, ReadOnlyList
4+
from ..pyutils import inspect, FrozenList
55
from .definition import GraphQLArgument, GraphQLInputType, GraphQLNonNull, is_input_type
66
from .scalars import GraphQLBoolean, GraphQLString
77

@@ -165,7 +165,7 @@ def assert_directive(directive: Any) -> GraphQLDirective:
165165
)
166166

167167

168-
specified_directives = ReadOnlyList(
168+
specified_directives = FrozenList(
169169
[GraphQLIncludeDirective, GraphQLSkipDirective, GraphQLDeprecatedDirective]
170170
)
171171
specified_directives.__doc__ = """The full list of specified directives."""

graphql/type/introspection.py

Lines changed: 2 additions & 2 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, ReadOnlyDict
24+
from ..pyutils import inspect, FrozenDict
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 = ReadOnlyDict(
495+
introspection_types = FrozenDict(
496496
{
497497
"__Schema": __Schema,
498498
"__Directive": __Directive,

graphql/type/scalars.py

Lines changed: 2 additions & 2 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, ReadOnlyDict
5+
from ..pyutils import inspect, is_finite, is_integer, FrozenDict
66
from ..language.ast import (
77
BooleanValueNode,
88
FloatValueNode,
@@ -241,7 +241,7 @@ def parse_id_literal(ast, _variables=None):
241241
)
242242

243243

244-
specified_scalar_types = ReadOnlyDict(
244+
specified_scalar_types = FrozenDict(
245245
{
246246
type_.name: type_
247247
for type_ in (

graphql/validation/specified_rules.py

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

3-
from ..pyutils import ReadOnlyList
3+
from ..pyutils import FrozenList
44

55
from .rules import RuleType
66

@@ -101,7 +101,7 @@
101101
# The order of the rules in this list has been adjusted to lead to the
102102
# most clear output when encountering multiple validation errors.
103103

104-
specified_rules: List[RuleType] = ReadOnlyList(
104+
specified_rules: List[RuleType] = FrozenList(
105105
[
106106
ExecutableDefinitionsRule,
107107
UniqueOperationNamesRule,
@@ -138,7 +138,7 @@
138138
most clear output when encountering multiple validation errors.
139139
"""
140140

141-
specified_sdl_rules: List[RuleType] = ReadOnlyList(
141+
specified_sdl_rules: List[RuleType] = FrozenList(
142142
[
143143
LoneSchemaDefinitionRule,
144144
UniqueOperationTypesRule,

tests/pyutils/test_frozen_dict.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from pytest import raises
2+
3+
from graphql.pyutils import FrozenError, FrozenDict
4+
5+
6+
def describe_frozen_list():
7+
def can_read():
8+
fd = FrozenDict({1: 2, 3: 4})
9+
assert fd == {1: 2, 3: 4}
10+
assert list(i for i in fd) == [1, 3]
11+
assert fd.copy() == fd
12+
assert 3 in fd
13+
assert 2 not in fd
14+
assert fd[1] == 2
15+
with raises(KeyError):
16+
fd[2]
17+
assert len(fd) == 2
18+
assert fd.get(1) == 2
19+
assert fd.get(2, 5) == 5
20+
assert list(fd.items()) == [(1, 2), (3, 4)]
21+
assert list(fd.keys()) == [1, 3]
22+
assert list(fd.values()) == [2, 4]
23+
24+
def cannot_write():
25+
fd = FrozenDict({1: 2, 3: 4})
26+
with raises(FrozenError):
27+
fd[1] = 2
28+
with raises(FrozenError):
29+
fd[4] = 5
30+
with raises(FrozenError):
31+
del fd[1]
32+
with raises(FrozenError):
33+
del fd[3]
34+
with raises(FrozenError):
35+
fd.clear()
36+
with raises(FrozenError):
37+
fd.pop(1)
38+
with raises(FrozenError):
39+
fd.pop(4, 5)
40+
with raises(FrozenError):
41+
fd.popitem()
42+
with raises(FrozenError):
43+
fd.setdefault(1, 2)
44+
with raises(FrozenError):
45+
fd.setdefault(4, 5)
46+
with raises(FrozenError):
47+
fd.update({1: 2})
48+
with raises(FrozenError):
49+
fd.update({4: 5})
50+
assert fd == {1: 2, 3: 4}

tests/pyutils/test_frozen_error.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from graphql.pyutils import FrozenError
2+
3+
4+
def describe_frozen_error():
5+
def frozen_error_is_type_error():
6+
assert issubclass(FrozenError, TypeError)

tests/pyutils/test_frozen_list.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from pytest import raises
2+
3+
from graphql.pyutils import FrozenError, FrozenList
4+
5+
6+
def describe_frozen_list():
7+
def can_read():
8+
fl = FrozenList([1, 2, 3])
9+
assert fl == [1, 2, 3]
10+
assert list(i for i in fl) == fl
11+
assert fl.copy() == fl
12+
assert 2 in fl
13+
assert 4 not in fl
14+
assert fl + [4, 5] == [1, 2, 3, 4, 5]
15+
assert [4, 5] + fl == [4, 5, 1, 2, 3]
16+
assert fl * 2 == [1, 2, 3, 1, 2, 3]
17+
assert 2 * fl == [1, 2, 3, 1, 2, 3]
18+
assert fl[1] == 2
19+
with raises(IndexError):
20+
fl[3]
21+
assert fl[1:4] == [2, 3]
22+
assert fl[::2] == [1, 3]
23+
assert len(fl) == 3
24+
assert min(fl) == 1
25+
assert max(fl) == 3
26+
assert sum(fl) == 6
27+
assert fl.index(2) == 1
28+
with raises(ValueError):
29+
fl.index(4)
30+
assert fl.count(2) == 1
31+
assert fl.count(4) == 0
32+
assert list(reversed(fl)) == [3, 2, 1]
33+
assert sorted(fl) == [1, 2, 3]
34+
35+
def cannot_write():
36+
fl = FrozenList([1, 2, 3])
37+
with raises(FrozenError):
38+
fl[1] = 4
39+
with raises(FrozenError):
40+
fl[1:4] = [4]
41+
with raises(FrozenError):
42+
del fl[1]
43+
with raises(FrozenError):
44+
del fl[1:4]
45+
with raises(FrozenError):
46+
fl[1::2] = [4]
47+
with raises(FrozenError):
48+
del fl[::2]
49+
with raises(FrozenError):
50+
fl.append(4)
51+
with raises(FrozenError):
52+
fl.clear()
53+
with raises(FrozenError):
54+
fl.extend([4])
55+
with raises(FrozenError):
56+
fl += [4]
57+
with raises(FrozenError):
58+
fl *= 2
59+
with raises(FrozenError):
60+
fl.insert(1, 4)
61+
with raises(FrozenError):
62+
fl.pop()
63+
with raises(FrozenError):
64+
fl.remove(2)
65+
with raises(FrozenError):
66+
fl.sort()
67+
with raises(FrozenError):
68+
fl.reverse()
69+
assert fl == [1, 2, 3]
70+
71+
def can_add_rol():
72+
fl1 = FrozenList([1, 2])
73+
rol2 = FrozenList([3, 4])
74+
assert fl1 + rol2 == [1, 2, 3, 4]
75+
76+
def can_add_tuple():
77+
fl = FrozenList([1, 2])
78+
assert fl + (3, 4) == [1, 2, 3, 4]

0 commit comments

Comments
 (0)