Skip to content

Commit 9bdbb34

Browse files
committed
Allow parser context to be None
Default parameter of `parser_context` was already set to `None` but would had always raised an error. DRF parser allows `parser_context` to be `None` to so brings DJA to use the same API.
1 parent f8209c0 commit 9bdbb34

File tree

3 files changed

+31
-16
lines changed

3 files changed

+31
-16
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ any parts of the framework not mentioned in the documentation should generally b
1313
### Fixed
1414

1515
* Adjusted error messages to correctly use capitial "JSON:API" abbreviation as used in the specification.
16+
* Avoid error when `parser_context` is `None` while parsing.
1617

1718
### Changed
1819

Diff for: rest_framework_json_api/parsers.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ def parse(self, stream, media_type=None, parser_context=None):
8282
raise ParseError("Received document does not contain primary data")
8383

8484
data = result.get("data")
85-
view = parser_context["view"]
85+
parser_context = parser_context or {}
86+
view = parser_context.get("view")
8687

8788
from rest_framework_json_api.views import RelationshipView
8889

@@ -107,6 +108,7 @@ def parse(self, stream, media_type=None, parser_context=None):
107108
return data
108109

109110
request = parser_context.get("request")
111+
method = request and request.method
110112

111113
# Sanity check
112114
if not isinstance(data, dict):
@@ -115,7 +117,7 @@ def parse(self, stream, media_type=None, parser_context=None):
115117
)
116118

117119
# Check for inconsistencies
118-
if request.method in ("PUT", "POST", "PATCH"):
120+
if method in ("PUT", "POST", "PATCH"):
119121
resource_name = get_resource_name(
120122
parser_context, expand_polymorphic_types=True
121123
)
@@ -138,12 +140,12 @@ def parse(self, stream, media_type=None, parser_context=None):
138140
resource_types=", ".join(resource_name),
139141
)
140142
)
141-
if not data.get("id") and request.method in ("PATCH", "PUT"):
143+
if not data.get("id") and method in ("PATCH", "PUT"):
142144
raise ParseError(
143145
"The resource identifier object must contain an 'id' member"
144146
)
145147

146-
if request.method in ("PATCH", "PUT"):
148+
if method in ("PATCH", "PUT"):
147149
lookup_url_kwarg = getattr(view, "lookup_url_kwarg", None) or getattr(
148150
view, "lookup_field", None
149151
)

Diff for: tests/test_parsers.py

+24-12
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ def parser(self):
1515
return JSONParser()
1616

1717
@pytest.fixture
18-
def parse(self, parser, parser_context):
19-
def parse_wrapper(data):
18+
def parse(self, parser):
19+
def parse_wrapper(data, parser_context):
2020
stream = BytesIO(json.dumps(data).encode("utf-8"))
2121
return parser.parse(stream, None, parser_context)
2222

@@ -41,6 +41,7 @@ def test_parse_formats_field_names(
4141
settings,
4242
format_field_names,
4343
parse,
44+
parser_context,
4445
):
4546
settings.JSON_API_FORMAT_FIELD_NAMES = format_field_names
4647

@@ -59,25 +60,36 @@ def test_parse_formats_field_names(
5960
}
6061
}
6162

62-
result = parse(data)
63+
result = parse(data, parser_context)
6364
assert result == {
6465
"id": "123",
6566
"test_attribute": "test-value",
6667
"test_relationship": {"id": "123", "type": "TestRelationship"},
6768
}
6869

69-
def test_parse_extracts_meta(self, parse):
70+
def test_parse_extracts_meta(self, parse, parser_context):
7071
data = {
7172
"data": {
7273
"type": "BasicModel",
7374
},
7475
"meta": {"random_key": "random_value"},
7576
}
7677

77-
result = parse(data)
78+
result = parse(data, parser_context)
7879
assert result["_meta"] == data["meta"]
7980

80-
def test_parse_preserves_json_value_field_names(self, settings, parse):
81+
def test_parse_with_default_arguments(self, parse):
82+
data = {
83+
"data": {
84+
"type": "BasicModel",
85+
},
86+
}
87+
result = parse(data, None)
88+
assert result == {}
89+
90+
def test_parse_preserves_json_value_field_names(
91+
self, settings, parse, parser_context
92+
):
8193
settings.JSON_API_FORMAT_FIELD_NAMES = "dasherize"
8294

8395
data = {
@@ -87,17 +99,17 @@ def test_parse_preserves_json_value_field_names(self, settings, parse):
8799
},
88100
}
89101

90-
result = parse(data)
102+
result = parse(data, parser_context)
91103
assert result["json_value"] == {"JsonKey": "JsonValue"}
92104

93-
def test_parse_raises_error_on_empty_data(self, parse):
105+
def test_parse_raises_error_on_empty_data(self, parse, parser_context):
94106
data = []
95107

96108
with pytest.raises(ParseError) as excinfo:
97-
parse(data)
109+
parse(data, parser_context)
98110
assert "Received document does not contain primary data" == str(excinfo.value)
99111

100-
def test_parse_fails_on_list_of_objects(self, parse):
112+
def test_parse_fails_on_list_of_objects(self, parse, parser_context):
101113
data = {
102114
"data": [
103115
{
@@ -108,7 +120,7 @@ def test_parse_fails_on_list_of_objects(self, parse):
108120
}
109121

110122
with pytest.raises(ParseError) as excinfo:
111-
parse(data)
123+
parse(data, parser_context)
112124

113125
assert (
114126
"Received data is not a valid JSON:API Resource Identifier Object"
@@ -124,7 +136,7 @@ def test_parse_fails_when_id_is_missing_on_patch(self, rf, parse, parser_context
124136
}
125137

126138
with pytest.raises(ParseError) as excinfo:
127-
parse(data)
139+
parse(data, parser_context)
128140

129141
assert "The resource identifier object must contain an 'id' member" == str(
130142
excinfo.value

0 commit comments

Comments
 (0)