diff --git a/README.md b/README.md index 9185707..db91bbe 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,31 @@ class FirstCrowdinClient(CrowdinClient): EXTENDED_REQUEST_PARAMS = {"proxies": proxies} ``` +### GraphQL API + +This library also provides the possibility to use [GraphQL API](https://developer.crowdin.com/graphql-api/): + +```python +from crowdin_api import CrowdinClient + +client = CrowdinClient( + token='{token}', + organization='{organization}' +) + +query = """ +query { + viewer { + id + name + } +} +""" + +# Execute the GraphQL query +response = client.graphql(query=query) +``` + ## Seeking Assistance If you find any problems or would like to suggest a feature, please read the [How can I contribute](https://github.com/crowdin/crowdin-api-client-python/blob/main/CONTRIBUTING.md#how-can-i-contribute) section in our contributing guidelines. diff --git a/crowdin_api/client.py b/crowdin_api/client.py index c121322..d5693da 100644 --- a/crowdin_api/client.py +++ b/crowdin_api/client.py @@ -91,9 +91,19 @@ def get_api_requestor(self) -> APIRequester: default_headers=self.get_default_headers(), extended_params=self.EXTENDED_REQUEST_PARAMS ) - return self._api_requestor + def graphql(self, query: str, variables: Optional[Dict] = None) -> Dict: + data = { + "query": query, + "variables": variables or {} + } + return self.get_api_requestor().request( + method="post", + path="graphql", + request_data=data + ) + @property def ai(self) -> Union[api_resources.AIResource, api_resources.EnterpriseAIResource]: if self._is_enterprise_platform: diff --git a/crowdin_api/tests/test_client.py b/crowdin_api/tests/test_client.py index 836291d..2fd9e1e 100644 --- a/crowdin_api/tests/test_client.py +++ b/crowdin_api/tests/test_client.py @@ -210,6 +210,25 @@ def test_storages(self, _m_api_requestor, property_name, class_name): requester="api_requestor", project_id=1, page_size=25 ) + @mock.patch("crowdin_api.client.CrowdinClient.get_api_requestor") + def test_graphql(self, mock_get_requestor): + """Test GraphQL functionality with basic request validation.""" + client = CrowdinClient() + assert isinstance(client, CrowdinClient) + + mock_requestor = mock.Mock() + mock_get_requestor.return_value = mock_requestor + mock_requestor.request.return_value = {"data": {"test": True}} + + query = "query { test }" + client.graphql(query=query) + + mock_requestor.request.assert_called_once() + call_args = mock_requestor.request.call_args[1] + assert call_args["method"] == "post" + assert call_args["path"] == "graphql" + assert call_args["request_data"]["query"] == query + class TestCrowdinClientEnterprise: @pytest.mark.parametrize(