From 3cd8b92d5f79a66abb1a8dc6eba84fe61b896e4f Mon Sep 17 00:00:00 2001 From: dexhunter Date: Sat, 7 Nov 2026 02:21:14 +0000 Subject: [PATCH] perf(assert_name): skip per-char generator -- 25% faster schema build assert_name() checked the name tail with a generator that called is_name_continue() once per character. For ASCII text, str.isidentifier() is true exactly for [_a-zA-Z][_a-zA-Z0-9]*, so valid names now return after isascii() and isidentifier(). Invalid names keep the same checks in the same order, so error classes and messages are unchanged. build_ast_schema on the GitHub SDL: 14.40 ms -> 10.79 ms (25% less time). Co-Authored-By: Aiden --- src/graphql/type/assert_name.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/graphql/type/assert_name.py b/src/graphql/type/assert_name.py index b335cd07..fec7fc31 100644 --- a/src/graphql/type/assert_name.py +++ b/src/graphql/type/assert_name.py @@ -1,7 +1,6 @@ """Assertions for naming conventions""" from ..error import GraphQLError -from ..language.character_classes import is_name_continue, is_name_start __all__ = ["assert_enum_value_name", "assert_name"] @@ -20,6 +19,10 @@ def assert_name(name: str) -> str: ... graphql.error.graphql_error.GraphQLError: Names must start with [_a-zA-Z] ... """ + # an ASCII identifier is exactly a GraphQL name: [_a-zA-Z][_a-zA-Z0-9]* + if isinstance(name, str) and name.isascii() and name.isidentifier(): + return name + # only invalid names get here, so find out what is wrong with them if name is None: msg = "Must provide name." raise TypeError(msg) @@ -29,13 +32,13 @@ def assert_name(name: str) -> str: if not name: msg = "Expected name to be a non-empty string." raise GraphQLError(msg) - if not all(is_name_continue(char) for char in name[1:]): + # report a bad tail first, since a valid tail implies a bad first char + tail = name[1:].replace("_", "") + if tail and not (tail.isascii() and tail.isalnum()): msg = f"Names must only contain [_a-zA-Z0-9] but {name!r} does not." raise GraphQLError(msg) - if not is_name_start(name[0]): - msg = f"Names must start with [_a-zA-Z] but {name!r} does not." - raise GraphQLError(msg) - return name + msg = f"Names must start with [_a-zA-Z] but {name!r} does not." + raise GraphQLError(msg) def assert_enum_value_name(name: str) -> str: