Skip to content

Commit f3de9b2

Browse files
committed
Merged graphql function into query function.
This seems more expected to a user, who can now use a single function and select the type of query they want to submit.
1 parent 3a0ce65 commit f3de9b2

File tree

2 files changed

+42
-62
lines changed

2 files changed

+42
-62
lines changed

marklogic/rows.py

Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,16 @@
22
from requests import Session
33

44
"""
5-
Defines a RowManager class to simplify usage of the "/v1/rows" & "/v1/rows/graphql" REST
6-
endpoints defined at https://docs.marklogic.com/REST/POST/v1/rows/graphql.
5+
Defines classes to simplify usage of the REST rows service defined at
6+
https://docs.marklogic.com/REST/client/row-management.
77
"""
88

99

1010
class RowManager:
11-
"""
12-
Provides a method to simplify sending a GraphQL
13-
request to the GraphQL rows endpoint.
14-
"""
1511

1612
def __init__(self, session: Session):
1713
self._session = session
1814

19-
def graphql(self, graphql_query: str, return_response: bool = False, **kwargs):
20-
"""
21-
Send a GraphQL query to MarkLogic via a POST to the endpoint defined at
22-
https://docs.marklogic.com/REST/POST/v1/rows/graphql.
23-
24-
:param graphql_query: a GraphQL query string. Note - this is the query string
25-
only, not the entire query JSON object. See the following for more information:
26-
https://spec.graphql.org/October2021/#sec-Overview
27-
https://graphql.org/learn/queries/
28-
:param return_response: boolean specifying if the entire original response
29-
object should be returned (True) or if only the data should be returned (False)
30-
upon a success (2xx) response. Note that if the status code of the response is
31-
not 2xx, then the entire response is always returned.
32-
"""
33-
headers = kwargs.pop("headers", {})
34-
headers["Content-Type"] = "application/graphql"
35-
response = self._session.post(
36-
"v1/rows/graphql",
37-
headers=headers,
38-
data=json.dumps({"query": graphql_query}),
39-
**kwargs
40-
)
41-
return (
42-
response.json()
43-
if response.status_code == 200 and not return_response
44-
else response
45-
)
46-
4715
__accept_switch = {
4816
"json": "application/json",
4917
"xml": "application/xml",
@@ -66,43 +34,55 @@ def query(
6634
plan: dict = None,
6735
sql: str = None,
6836
sparql: str = None,
37+
graphql: str = None,
6938
format: str = "json",
7039
return_response: bool = False,
7140
**kwargs
7241
):
7342
"""
74-
Send a query to MarkLogic via a POST to the endpoint defined at
75-
https://docs.marklogic.com/REST/POST/v1/rows.
76-
Just like that endpoint, this function can be used for four different types of
77-
queries: Optic DSL, Serialized Optic, SQL, and SPARQL. The type of query
78-
processed by the function is dependent upon the parameter used in the call to
79-
the function.
43+
Sends a query to an endpoint at the MarkLogic rows service defined at
44+
https://docs.marklogic.com/REST/client/row-management.
45+
46+
One of 'dsl', 'plan', 'sql', 'sparql', or 'graphql' must be defined.
8047
For more information about Optic and using the Optic DSL, SQL, and SPARQL,
81-
see https://docs.marklogic.com/guide/app-dev/OpticAPI.
82-
If multiple query parameters are passed into the call, the function uses the
83-
query parameter that is first in the list: dsl, plan, sql, sparql.
48+
see https://docs.marklogic.com/guide/app-dev/OpticAPI. If one or more of these
49+
are passed into the call, the function uses the query parameter that is first
50+
in the prior list.
8451
8552
:param dsl: an Optic DSL query
8653
:param plan: a serialized Optic query
8754
:param sql: an SQL query
8855
:param sparql: a SPARQL query
56+
:param graphql: a GraphQL query string. This is the query string
57+
only, not the entire query JSON object. See
58+
https://docs.marklogic.com/REST/POST/v1/rows/graphql for more information.
59+
:param format: defines the format of the response. If a GraphQL query is
60+
submitted, this parameter is ignored and a JSON response is always returned.
8961
:param return_response: boolean specifying if the entire original response
9062
object should be returned (True) or if only the data should be returned (False)
9163
upon a success (2xx) response. Note that if the status code of the response is
9264
not 2xx, then the entire response is always returned.
9365
"""
94-
request_info = self.__get_request_info(dsl, plan, sql, sparql)
66+
path = "v1/rows/graphql" if graphql else "v1/rows"
9567
headers = kwargs.pop("headers", {})
96-
headers["Content-Type"] = request_info["content-type"]
97-
headers["Accept"] = RowManager.__accept_switch.get(format)
98-
response = self._session.post(
99-
"v1/rows", headers=headers, data=request_info["data"], **kwargs
100-
)
101-
return (
102-
RowManager.__query_format_switch.get(format)(response)
103-
if response.status_code == 200 and not return_response
104-
else response
105-
)
68+
data = None
69+
if graphql:
70+
data = json.dumps({"query": graphql})
71+
headers["Content-Type"] = "application/graphql"
72+
else:
73+
request_info = self.__get_request_info(dsl, plan, sql, sparql)
74+
data = request_info["data"]
75+
headers["Content-Type"] = request_info["content-type"]
76+
headers["Accept"] = RowManager.__accept_switch.get(format)
77+
78+
response = self._session.post(path, headers=headers, data=data, **kwargs)
79+
if response.ok and not return_response:
80+
return (
81+
response.json()
82+
if graphql
83+
else RowManager.__query_format_switch.get(format)(response)
84+
)
85+
return response
10686

10787
def __get_request_info(self, dsl: str, plan: dict, sql: str, sparql: str):
10888
"""

tests/test_graphql.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
def test_graphql(client):
2-
data = client.rows.graphql(
3-
"query musicianQuery { test_musician { lastName firstName dob } }"
2+
data = client.rows.query(
3+
graphql="query musicianQuery { test_musician { lastName firstName dob } }"
44
)
55
musicians = data["data"]["test_musician"]
66
assert 4 == len(musicians)
77
assert 1 == len([m for m in musicians if m["lastName"] == "Armstrong"])
88

99

1010
def test_graphql_return_response(client):
11-
response = client.rows.graphql(
12-
"query musicianQuery { test_musician { lastName firstName dob } }",
11+
response = client.rows.query(
12+
graphql="query musicianQuery { test_musician { lastName firstName dob } }",
1313
return_response=True,
1414
)
1515
assert 200 == response.status_code
@@ -20,8 +20,8 @@ def test_graphql_return_response(client):
2020

2121

2222
def test_graphql_bad_graphql(client):
23-
response = client.rows.graphql(
24-
"query musicianQuery { test_musician { lastName firstName dob } "
23+
response = client.rows.query(
24+
graphql="query musicianQuery { test_musician { lastName firstName dob } "
2525
)
2626
assert 1 == len(response["errors"])
2727
assert (
@@ -31,7 +31,7 @@ def test_graphql_bad_graphql(client):
3131

3232

3333
def test_graphql_bad_user(not_rest_user_client):
34-
response = not_rest_user_client.rows.graphql(
35-
"query musicianQuery { test_musician { lastName firstName dob } }"
34+
response = not_rest_user_client.rows.query(
35+
graphql="query musicianQuery { test_musician { lastName firstName dob } }"
3636
)
3737
assert 403 == response.status_code

0 commit comments

Comments
 (0)