diff --git a/pyproject.toml b/pyproject.toml index a0353d2..d44b8e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "graphql_complexity" -version = "0.3.1" +version = "0.3.2" description = "A python library that provides complexity calculation helpers for GraphQL" authors = ["Checho3388 "] packages = [ diff --git a/src/graphql_complexity/evaluator/nodes.py b/src/graphql_complexity/evaluator/nodes.py index 3e7b19f..86b7acd 100644 --- a/src/graphql_complexity/evaluator/nodes.py +++ b/src/graphql_complexity/evaluator/nodes.py @@ -10,7 +10,7 @@ ) from graphql_complexity.config import Config -from graphql_complexity.evaluator.utils import get_node_argument_value +from graphql_complexity.evaluator.utils import get_node_argument_value, is_meta_type logger = logging.getLogger(__name__) @@ -107,8 +107,7 @@ def build_node( ) -> ComplexityNode: """Build a complexity node from a field node.""" type_ = type_info.get_type() - unwrapped_type = get_named_type(type_) - if unwrapped_type is not None and is_introspection_type(unwrapped_type): + if is_meta_type(type_, node): return MetaField(name=node.name.value) if isinstance(type_, GraphQLList): return build_list_node(node, complexity, variables, config) diff --git a/src/graphql_complexity/evaluator/utils.py b/src/graphql_complexity/evaluator/utils.py index a066107..0e04b68 100644 --- a/src/graphql_complexity/evaluator/utils.py +++ b/src/graphql_complexity/evaluator/utils.py @@ -1,14 +1,17 @@ from typing import Any -from graphql import DirectiveNode, FieldNode, VariableNode +from graphql import ( + DirectiveNode, + FieldNode, + VariableNode, + get_named_type, + is_introspection_type, +) def get_node_argument_value(node: FieldNode | DirectiveNode, arg_name: str, variables: dict[str, Any]) -> Any: """Returns the value of the argument given by parameter.""" - arg = next( - (arg for arg in node.arguments if arg.name.value == arg_name), - None - ) + arg = next((arg for arg in node.arguments if arg.name.value == arg_name), None) if not arg: raise ValueError(f"Value for {arg_name!r} not found in {node.name.value!r} arguments") @@ -16,3 +19,14 @@ def get_node_argument_value(node: FieldNode | DirectiveNode, arg_name: str, vari return variables.get(arg.value.name.value) return arg.value.value + + +def is_meta_type(type_, node) -> bool: + """Check if the field is a meta field.""" + unwrapped_type = get_named_type(type_) + return any( + ( + unwrapped_type is not None and is_introspection_type(unwrapped_type), + unwrapped_type is not None and node.name.value == "__typename", + ) + ) diff --git a/tests/test_complexity_visitor.py b/tests/test_complexity_visitor.py index b0249d6..0a0ed3e 100644 --- a/tests/test_complexity_visitor.py +++ b/tests/test_complexity_visitor.py @@ -24,6 +24,16 @@ def test_one_field_simple_complexity_calculation(): assert complexity == 1 +def test_typename_has_zero_complexity(): + query = """query { + __typename + }""" + + complexity = _evaluate_complexity(query) + + assert complexity == 0 + + def test_two_fields_simple_complexity_calculation(): query = """ query Something {