From cb41279772c27e244594440ea5e395943dfe0ac9 Mon Sep 17 00:00:00 2001 From: "s.kovbasa" Date: Wed, 20 Dec 2023 23:42:32 +0200 Subject: [PATCH 1/3] Raise TypeError for nonexistent fragment. Add basic isort config --- hiku/readers/graphql.py | 28 ++++++++++----------------- pyproject.toml | 5 +++++ tests/test_read_graphql.py | 39 ++++++++++++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/hiku/readers/graphql.py b/hiku/readers/graphql.py index 9bd046d2..1c659891 100644 --- a/hiku/readers/graphql.py +++ b/hiku/readers/graphql.py @@ -1,27 +1,14 @@ from collections import defaultdict - -from typing import ( - Optional, - Dict, - Iterator, - Tuple, - Union, - List, - cast, - Any, - Set, -) +from typing import Any, cast, Dict, Iterator, List, Optional, Set, Tuple, Union from graphql.language import ast from graphql.language.parser import parse + from hiku.utils import ImmutableDict -from ..directives import ( - Cached, - Directive, -) +from ..directives import Cached, Directive from ..operation import Operation, OperationType -from ..query import FieldOrLink, Fragment, Node, Field, Link, merge +from ..query import Field, FieldOrLink, Fragment, Link, merge, Node def parse_query(src: str) -> ast.DocumentNode: @@ -93,7 +80,7 @@ def get( try: return self._operations[self._operation_name] except KeyError: - raise ValueError( + raise TypeError( "Undefined operation name: {!r}".format( self._operation_name ) @@ -257,6 +244,9 @@ def _collect_fields( type_name = item.type_condition.name.value selection_set = item.selection_set elif isinstance(item, ast.FragmentSpreadNode): + if item.name.value not in fragments_map: + raise TypeError(f'Undefined fragment: "{item.name.value}"') + fragment = fragments_map[item.name.value] type_name = fragment.type_condition.name.value selection_set = fragment.selection_set @@ -376,6 +366,8 @@ def __init__( self.pending_fragments: Set[str] = set() def transform_fragment(self, name: str) -> List[Union[Field, Link]]: + if name not in self.fragments_map: + raise TypeError(f'Undefined fragment: "{name}"') return self.visit(self.fragments_map[name]) def visit_operation_definition( diff --git a/pyproject.toml b/pyproject.toml index 4420af80..81565716 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,3 +251,8 @@ ignore_missing_imports = true [tool.black] line-length = 80 target-version = ['py37'] + +[tool.isort] +py_version = "37" +profile = "black" +line_length = 80 diff --git a/tests/test_read_graphql.py b/tests/test_read_graphql.py index 0793e073..eb6123bf 100644 --- a/tests/test_read_graphql.py +++ b/tests/test_read_graphql.py @@ -1,11 +1,14 @@ import pytest - from graphql.language import ast from graphql.language.parser import parse -from hiku.query import Fragment, Node, Field, Link -from hiku.readers.graphql import read, OperationGetter -from hiku.readers.graphql import read_operation, OperationType +from hiku.query import Field, Fragment, Link, Node +from hiku.readers.graphql import ( + OperationGetter, + OperationType, + read, + read_operation, +) def check_read(source, query, variables=None): @@ -283,6 +286,34 @@ def test_reference_cycle_in_fragments(): err.match('Cyclic fragment usage: "Pakol"') +def test_non_existent_fragment_root(): + with pytest.raises(TypeError) as err: + read( + """ + query Pelota { + sinope + ...Pakol + } + """ + ) + err.match('Undefined fragment: "Pakol"') + + +def test_non_existent_fragment(): + with pytest.raises(TypeError) as err: + read( + """ + query Pelota { + sinope + pins { + ...Splosh + } + } + """ + ) + err.match('Undefined fragment: "Splosh"') + + def test_duplicated_fragment_names(): with pytest.raises(TypeError) as err: read( From 3c554fa0d31a08cce269c158e85cf4c01835ece6 Mon Sep 17 00:00:00 2001 From: "s.kovbasa" Date: Thu, 21 Dec 2023 00:55:35 +0200 Subject: [PATCH 2/3] Bump pdm action python version --- .github/workflows/release.yaml | 2 +- .github/workflows/test.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 62caabe1..5e7c353e 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -40,6 +40,6 @@ jobs: - name: Set up PDM uses: pdm-project/setup-pdm@v3 with: - python-version: "3.7" + python-version: "3.8" - name: Publish package distributions to PyPI run: pdm publish -u "__token__" -P ${{ secrets.TWINE_PASSWORD }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 63bb738e..803c7b29 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,7 +21,7 @@ jobs: - name: Set up PDM uses: pdm-project/setup-pdm@v3 with: - python-version: ${{ matrix.python-version }} + python-version: "3.8" - name: Install dependencies run: | pdm sync -d -G test -G dev From edcd7a81cf603da3fbcedfc335a0df45b827c75d Mon Sep 17 00:00:00 2001 From: "s.kovbasa" Date: Thu, 21 Dec 2023 01:04:02 +0200 Subject: [PATCH 3/3] Replace pdm action with pip install --- .github/workflows/release.yaml | 4 +--- .github/workflows/test.yaml | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5e7c353e..8d231e1d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -38,8 +38,6 @@ jobs: draft: false prerelease: ${{ steps.check_version.outputs.PRERELEASE }} - name: Set up PDM - uses: pdm-project/setup-pdm@v3 - with: - python-version: "3.8" + run: pip install pdm==2.10.4 - name: Publish package distributions to PyPI run: pdm publish -u "__token__" -P ${{ secrets.TWINE_PASSWORD }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 803c7b29..a5c3910b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,9 +19,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Set up PDM - uses: pdm-project/setup-pdm@v3 - with: - python-version: "3.8" + run: pip install pdm==2.10.4 - name: Install dependencies run: | pdm sync -d -G test -G dev