This repository was archived by the owner on Jun 3, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
graphql requests module #244
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
ba58dd2
Dummy graphql requests module
ff29fb5
graphql api request
293c5da
return Model instances
8aaa63c
Update NOTICE (#242)
jeanniefinks 20b4ba4
bump main to 1.4.0 (#246)
dhuangnm c4426e9
Pin numpy version to <=1.21.6 (#247)
rahul-tuli e069283
lint
629016c
Merge branch 'main' into graphql-requests
f43ad7b
pass tests
461caf3
init files
e70499b
lint
abead91
Add dummy test using test-specific subclass
36f5941
tests
1875611
add incremeent_downloads=False
20d9637
allow empty arguments
6e8d707
comments
22e386f
Merge branch 'main' into graphql-requests
1fd0b74
refactor from main merge
33425c1
comments
3ff1a66
da comments
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
# flake8: noqa | ||
|
||
from .graphql import * | ||
from .query_parser import * | ||
from .utils import * |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
|
||
from typing import Any, Dict, List, Optional | ||
|
||
import requests | ||
|
||
from sparsezoo.utils import BASE_API_URL | ||
|
||
from .query_parser import QueryParser | ||
from .utils import map_keys, to_snake_case | ||
|
||
|
||
class GraphQLAPI: | ||
def fetch( | ||
self, | ||
operation_body: str, | ||
arguments: Optional[Dict[str, str]] = None, | ||
fields: Optional[List[str]] = None, | ||
url: Optional[str] = None, | ||
) -> Dict[str, Any]: | ||
""" | ||
Fetch data for models via api. Uses graphql convention of post, | ||
not get for requests. | ||
Input args are parsed to make a query body for the api request. | ||
For more details on the appropriate values, please refer to the | ||
url endpoint on the browser | ||
|
||
:param operation_body: The data object of interest | ||
:param arguments: Used to filter data object in the backend | ||
:param field: the object's field of interest | ||
""" | ||
|
||
response_objects = self.make_request( | ||
operation_body=operation_body, | ||
arguments=arguments, | ||
fields=fields, | ||
url=url, | ||
) | ||
|
||
return [ | ||
map_keys(dictionary=response_object, mapper=to_snake_case) | ||
for response_object in response_objects | ||
] | ||
|
||
def make_request( | ||
self, | ||
operation_body: str, | ||
arguments: Optional[Dict[str, str]] = None, | ||
fields: Optional[List[str]] = None, | ||
url: Optional[str] = None, | ||
) -> Dict[str, Any]: | ||
""" | ||
Given the input args, parse them to a graphql appropriate format | ||
and make an graph post request to get the desired raw response. | ||
Raw response's keys are in camelCase, not snake_case | ||
""" | ||
|
||
query = QueryParser( | ||
operation_body=operation_body, arguments=arguments, fields=fields | ||
) | ||
|
||
response = requests.post( | ||
url=url or f"{BASE_API_URL}/v2/graphql", json={"query": query.query_body} | ||
) | ||
|
||
response.raise_for_status() | ||
response_json = response.json() | ||
|
||
return response_json["data"][query.operation_body] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
|
||
from typing import Dict, List, Optional | ||
|
||
from .utils import to_camel_case | ||
|
||
|
||
DEFAULT_MODELS_FIELDS = ["modelId", "stub"] | ||
|
||
DEFAULT_FILES_FIELDS = ["displayName", "fileSize", "modelId", "fileType"] | ||
|
||
DEFAULT_TRAINING_RESULTS_FIELDS = [ | ||
"datasetName", | ||
"datasetType", | ||
"recordedUnits", | ||
"recordedValue", | ||
] | ||
|
||
DEFAULT_BENCHMARK_RESULTS_FIELDS = [ | ||
"batchSize", | ||
"deviceInfo", | ||
"numCores", | ||
"recordedUnits", | ||
"recordedValue", | ||
] | ||
|
||
DEPRECATED_STUB_ARGS_MAPPER = {"sub_domain": "task", "dataset": "source_dataset"} | ||
DEFAULT_FIELDS = { | ||
"models": DEFAULT_MODELS_FIELDS, | ||
"files": DEFAULT_FILES_FIELDS, | ||
"trainingResults": DEFAULT_TRAINING_RESULTS_FIELDS, | ||
"benchmarkResults": DEFAULT_BENCHMARK_RESULTS_FIELDS, | ||
} | ||
|
||
QUERY_BODY = """ | ||
{{ | ||
{operation_body} {arguments} | ||
{{ | ||
{fields} | ||
}} | ||
}} | ||
""" | ||
|
||
|
||
class QueryParser: | ||
"""Parse the class input arg fields to be used for graphql post requests""" | ||
|
||
def __init__( | ||
self, | ||
operation_body: str, | ||
arguments: Optional[Dict[str, str]] = None, | ||
fields: Optional[List[str]] = None, | ||
): | ||
self._operation_body = operation_body | ||
self._arguments = arguments | ||
self._fields = fields | ||
self._query_body = None | ||
|
||
self._parse() | ||
|
||
def _parse(self): | ||
"""Parse to a string compatible with graphql requst body""" | ||
horheynm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
self._parse_operation_body() | ||
self._parse_arguments() | ||
self._parse_fields() | ||
horheynm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self._build_query_body() | ||
|
||
def _parse_operation_body(self) -> None: | ||
self._operation_body = to_camel_case(self._operation_body) | ||
|
||
def _parse_arguments(self) -> None: | ||
"""Transform deprecated stub args and convert to camel case""" | ||
parsed_arguments = "" | ||
arguments = self.arguments or {} | ||
|
||
for argument, value in arguments.items(): | ||
if value is not None: | ||
contemporary_key = DEPRECATED_STUB_ARGS_MAPPER.get(argument, argument) | ||
camel_case_key = to_camel_case(contemporary_key) | ||
|
||
# single, double quotes matters | ||
if isinstance(value, str): | ||
parsed_arguments += f'{camel_case_key}: "{value}",' | ||
else: | ||
parsed_arguments += f"{camel_case_key}: {value}," | ||
|
||
if parsed_arguments: | ||
parsed_arguments = "(" + parsed_arguments + ")" | ||
self._arguments = parsed_arguments | ||
|
||
def _parse_fields(self) -> None: | ||
fields = self.fields or DEFAULT_FIELDS.get(self.operation_body) | ||
self.fields = " ".join(map(to_camel_case, fields)) | ||
|
||
def _build_query_body(self) -> None: | ||
self.query_body = QUERY_BODY.format( | ||
operation_body=self.operation_body, | ||
arguments=self.arguments, | ||
fields=self.fields, | ||
) | ||
|
||
@property | ||
def operation_body(self) -> str: | ||
"""Return the query operation body""" | ||
return self._operation_body | ||
|
||
@operation_body.setter | ||
def operation_body(self, operation_body: str) -> None: | ||
self._operation_body = operation_body | ||
|
||
@property | ||
def arguments(self) -> str: | ||
"""Return the query arguments""" | ||
return self._arguments | ||
|
||
@arguments.setter | ||
def arguments(self, arguments: str) -> None: | ||
self._operation_body = arguments | ||
|
||
@property | ||
def fields(self) -> str: | ||
"""Return the query fields""" | ||
return self._fields | ||
|
||
@fields.setter | ||
def fields(self, fields: str) -> None: | ||
self._fields = fields | ||
|
||
@property | ||
def query_body(self) -> str: | ||
"""Return the query body""" | ||
return self._query_body | ||
|
||
@query_body.setter | ||
def query_body(self, query_body: str) -> None: | ||
self._query_body = query_body |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from typing import Callable, Dict | ||
|
||
|
||
def to_camel_case(string: str): | ||
horheynm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"Convert string to camel case" | ||
components = string.split("_") | ||
return components[0] + "".join(word.title() for word in components[1:]) | ||
|
||
|
||
def to_snake_case(string: str): | ||
"Convert string to snake case" | ||
horheynm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return "".join( | ||
[ | ||
"_" + character.lower() if character.isupper() else character | ||
for character in string | ||
] | ||
).lstrip("_") | ||
|
||
|
||
def map_keys( | ||
dictionary: Dict[str, str], mapper: Callable[[str], str] | ||
) -> Dict[str, str]: | ||
"""Given a dictionary, update its key to a given mapper callable""" | ||
return {mapper(key): value for key, value in dictionary.items()} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.