Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-gql for openSUSE:Factory checked in at 2026-08-21 16:53:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-gql (Old) and /work/SRC/openSUSE:Factory/.python-gql.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-gql" Fri Aug 21 16:53:20 2026 rev:4 rq:1372558 version:4.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-gql/python-gql.changes 2025-07-24 18:48:04.980026470 +0200 +++ /work/SRC/openSUSE:Factory/.python-gql.new.1258/python-gql.changes 2026-08-21 16:54:30.393474896 +0200 @@ -1,0 +2,92 @@ +Tue Jul 7 05:59:54 UTC 2026 - Johannes Kastl <[email protected]> + +- update to 4.0.0: + * Breaking Changes + * Change transports prototype using GraphQLRequest (#551) + * Using GraphQLRequest instead of DocumentNode for gql, + execute, subscribe methods (#556): + This is a big change: + - the gql and dsl_gql methods will now return a + GraphQLRequest instead of a Document Node a GraphQLRequest + is an object containing the document and optional + variable_values and operation_name + - ALL the execute and subscribe methods now receive a + GraphQLRequest as main argument instead of a DocumentNode, + variable_values and operation_name arguments + - The old method of sending variable_values as an argument of + execute or subscribe still works but is deprecated + See + https://gql.readthedocs.io/en/latest/usage/variables.html + for the new syntax. + * Fix subscription task cancel exception swallow (#548): + Previously if a task was cancelled while a subscription task + was active, the asyncio.CancelledError Exception would be + swallowed by our code. + This is not the case anymore so you should now trap that + Exception yourself. + * Clean up the file upload interface with FileVar class (#549): + The file upload functionality has been modified to require + FileVar instances for uploaded files (the old method still + works but is deprecated). + See + https://gql.readthedocs.io/en/latest/usage/file_upload.html + * Set logging level to DEBUG for all transports (#552) + * introspection now requests deprecated input fields by default + (#553) + Note that some backends might not support this and return + Unknown argument includeDeprecated. See #564 + * Trapping dependencies Exceptions into + TransportConnectionFailed (#558): + Now gql will trap Exceptions raised by dependencies when + executing a request and will encapsulate that Exception into + the TransportConnectionFailed Exception + * Set ssl=True by default for AIOHTTPTransport (#538) (issue + #529) + * New TransportConnectionClosed Exception replacing + ConnectionClosed Exception (#536) + * websocket attribute removed from transport, now using + '_connected' instead (#536) + * Upgrade lastest websockets and Exceptions overhaul (#543) + + * Features + - Batching requests is now fully supported, on sync or async + transports, with automatic batching: + - Implementation of execute_batch for async transports (#550) + - Implementation of automatic batching for async (#554) + See + https://gql.readthedocs.io/en/latest/advanced/batching_requests.html + * Fixes + - Fix httpx test deprecated warning (#542) + - Refactor websockets transports (#536) : + Refactor WebSockets Transport with Dependency Injection + Architecture + This major architectural improvement implements dependency + injection patterns across the WebSockets transport layer, + creating a more modular, testable, and extensible system: + - Created abstract AdapterConnection interface in + common/adapters/connection.py + - Implemented concrete WebSocketsAdapter to wrap the + websockets library + - Moved websockets_base.py to common/base.py maintaining + better structure which is independant of the websockets + library used + - Added new TransportConnectionClosed exception for clearer + error handling + - Reorganized code with proper separation of concerns: + - Moved common functionality into dedicated adapters folder + - Isolated connection handling from transport business logic + - Separated ListenerQueue into its own file for better + modularity + * Misc + - Remove MIT license classifier (#555) + - Refactor transports (#557) + - bump aiohttp to 3.11.2 (#541) + - Bumping all the dev dependencies to latest versions (#540) + - Bump test dependencies (#539) + - Update pytest to 8.3.4 and pytest-asyncio to 0.25.3 (#537) +- remove fix-tests.patch, merged upstream +- remove support-new-pytest-asyncio.patch, merged upstream +- add tests.patch to fix testsuite +- skip some broken tests (boo#1275674) + +------------------------------------------------------------------- Old: ---- fix-tests.patch gql-3.5.3.tar.gz support-new-pytest-asyncio.patch New: ---- gql-4.0.0.tar.gz tests.patch ----------(Old B)---------- Old: - Update pytest to 8.3.4 and pytest-asyncio to 0.25.3 (#537) - remove fix-tests.patch, merged upstream - remove support-new-pytest-asyncio.patch, merged upstream Old:- remove fix-tests.patch, merged upstream - remove support-new-pytest-asyncio.patch, merged upstream - add tests.patch to fix testsuite ----------(Old E)---------- ----------(New B)---------- New: - Update pytest to 8.3.4 and pytest-asyncio to 0.25.3 (#537) - remove fix-tests.patch, merged upstream - remove support-new-pytest-asyncio.patch, merged upstream ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-gql.spec ++++++ --- /var/tmp/diff_new_pack.dVFZfn/_old 2026-08-21 16:54:31.383510050 +0200 +++ /var/tmp/diff_new_pack.dVFZfn/_new 2026-08-21 16:54:31.384510086 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-gql # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,16 +19,14 @@ %bcond_without libalternatives %{?sle15_python_module_pythons} Name: python-gql -Version: 3.5.3 +Version: 4.0.0 Release: 0 Summary: GraphQL client for Python License: MIT URL: https://gql.readthedocs.io Source: https://github.com/graphql-python/gql/archive/refs/tags/v%{version}.tar.gz#/gql-%{version}.tar.gz -# PATCH-FIX-UPSTREAM Based on gh#graphql-python/gql#504 -Patch0: fix-tests.patch -# PATCH-FIX-UPSTREAM Based on gh#graphql-python/gql#537 -Patch1: support-new-pytest-asyncio.patch +# PATCH-FIX-UPSTEAM tests.patch gh#graphql-python/gql@3b2c396 +Patch0: tests.patch BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} BuildRequires: %{python_module wheel} @@ -36,15 +34,18 @@ BuildRequires: fdupes BuildRequires: python-rpm-macros # SECTION test requirements +BuildRequires: ca-certificates BuildRequires: %{python_module aiofiles} BuildRequires: %{python_module aiohttp} -BuildRequires: %{python_module anyio} -BuildRequires: %{python_module backoff >= 1.10.0} +BuildRequires: %{python_module anyio >= 3.0 with %python-anyio < 5} +BuildRequires: %{python_module backoff >= 1.10.1 with %python-backoff < 3.0} BuildRequires: %{python_module botocore} +BuildRequires: %{python_module certifi} BuildRequires: %{python_module flake8-import-order} BuildRequires: %{python_module flake8} -BuildRequires: %{python_module graphql-core >= 3.2 with %python-graphql-core < 3.4} +BuildRequires: %{python_module graphql-core >= 3.2 with %python-graphql-core < 3.3} BuildRequires: %{python_module httpx} +BuildRequires: %{python_module packaging} BuildRequires: %{python_module parse} BuildRequires: %{python_module pycodestyle} BuildRequires: %{python_module pylama} @@ -56,13 +57,14 @@ BuildRequires: %{python_module requests-toolbelt} BuildRequires: %{python_module requests} BuildRequires: %{python_module websockets} -BuildRequires: %{python_module yarl} +BuildRequires: %{python_module yarl >= 1.6 with %python-yarl < 2} +BuildRequires: ca-certificates-mozilla # /SECTION Requires: alts -Requires: python-anyio -Requires: python-backoff >= 1.11.1 -Requires: python-yarl >= 1.6 -Requires: (python-graphql-core >= 3.2 with python-graphql-core < 3.4) +Requires: (python-anyio >= 3.0 with python-anyio < 5) +Requires: (python-backoff >= 1.11.1 with python-backoff < 3.0) +Requires: (python-graphql-core >= 3.2 with python-graphql-core < 3.3) +Requires: (python-yarl >= 1.6 with python-yarl < 2) BuildArch: noarch %python_subpackages @@ -85,7 +87,12 @@ %check # skip some non-functional tests -%pytest -k "not (test_aiohttp_using_cli_ep or test_cli_ep_version or test_httpx_using_cli_ep or test_async_client_validation)" +IGNORED_CHECKS='test_aiohttp_using_cli_ep' +IGNORED_CHECKS+=' or test_cli_ep_version' +IGNORED_CHECKS+=' or test_httpx_using_cli_ep' +IGNORED_CHECKS+=' or test_async_client_validation' + +%pytest -k "not (network or ${IGNORED_CHECKS})" %pre %python_libalternatives_reset_alternative gql-cli ++++++ gql-3.5.3.tar.gz -> gql-4.0.0.tar.gz ++++++ ++++ 25775 lines of diff (skipped) ++++++ tests.patch ++++++ >From 3b2c396fb54c42f93bf428fb7bd2dcc52cf452e9 Mon Sep 17 00:00:00 2001 From: Hanusz Leszek <[email protected]> Date: Tue, 30 Jun 2026 10:39:15 +0200 Subject: [PATCH] Fix gql to work with graphql-core 3.3.0rc0 (#597) * Add kind to introspection query root types * Invert order or kind and name in introspection query to follow new graphql-core version * Restrict aiohttp to <= 3.13.2 for now to avoid unrelated tests break --- gql/dsl.py | 6 ++-- gql/utilities/build_client_schema.py | 12 ++++---- gql/utilities/get_introspection_query_ast.py | 10 +++--- gql/utilities/node_tree.py | 27 +++++++++-------- gql/utilities/serialize_variable_values.py | 2 +- setup.py | 2 +- tests/starwars/test_dsl.py | 32 +++++++++++--------- tests/test_transport.py | 29 +++++++++++++++++- tests/test_transport_batch.py | 29 +++++++++++++++++- 9 files changed, 105 insertions(+), 44 deletions(-) Index: gql-4.0.0/gql/utilities/build_client_schema.py =================================================================== --- gql-4.0.0.orig/gql/utilities/build_client_schema.py +++ gql-4.0.0/gql/utilities/build_client_schema.py @@ -23,10 +23,10 @@ INCLUDE_DIRECTIVE_JSON: IntrospectionDir "description": "Included when true.", "type": { "kind": "NON_NULL", - "name": "None", - "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": "None"}, + "name": None, + "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": None}, }, - "defaultValue": "None", + "defaultValue": None, } ], } @@ -48,10 +48,10 @@ SKIP_DIRECTIVE_JSON: IntrospectionDirect "description": "Skipped when true.", "type": { "kind": "NON_NULL", - "name": "None", - "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": "None"}, + "name": None, + "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": None}, }, - "defaultValue": "None", + "defaultValue": None, } ], } Index: gql-4.0.0/gql/utilities/get_introspection_query_ast.py =================================================================== --- gql-4.0.0.orig/gql/utilities/get_introspection_query_ast.py +++ gql-4.0.0/gql/utilities/get_introspection_query_ast.py @@ -35,9 +35,9 @@ def get_introspection_query_ast( schema.select(ds.__Schema.description) schema.select( - ds.__Schema.queryType.select(ds.__Type.name), - ds.__Schema.mutationType.select(ds.__Type.name), - ds.__Schema.subscriptionType.select(ds.__Type.name), + ds.__Schema.queryType.select(ds.__Type.name, ds.__Type.kind), + ds.__Schema.mutationType.select(ds.__Type.name, ds.__Type.kind), + ds.__Schema.subscriptionType.select(ds.__Type.name, ds.__Type.kind), ) schema.select(ds.__Schema.types.select(fragment_FullType)) @@ -125,11 +125,11 @@ def get_introspection_query_ast( ) if type_recursion_level >= 1: - current_field = ds.__Type.ofType.select(ds.__Type.kind, ds.__Type.name) + current_field = ds.__Type.ofType.select(ds.__Type.name, ds.__Type.kind) fragment_TypeRef.select(current_field) for _ in repeat(None, type_recursion_level - 1): - new_oftype = ds.__Type.ofType.select(ds.__Type.kind, ds.__Type.name) + new_oftype = ds.__Type.ofType.select(ds.__Type.name, ds.__Type.kind) current_field.select(new_oftype) current_field = new_oftype Index: gql-4.0.0/gql/utilities/node_tree.py =================================================================== --- gql-4.0.0.orig/gql/utilities/node_tree.py +++ gql-4.0.0/gql/utilities/node_tree.py @@ -29,22 +29,21 @@ def _node_tree_recursive( continue attr_value = getattr(obj, key, None) results.append(" " * (indent + 1) + f"{key}:") - if isinstance(attr_value, Iterable) and not isinstance( + if attr_value is None or ( + isinstance(attr_value, Sized) and len(attr_value) == 0 + ): + results.append(" " * (indent + 2) + "None") + elif isinstance(attr_value, Iterable) and not isinstance( attr_value, (str, bytes) ): - if isinstance(attr_value, Sized) and len(attr_value) == 0: + for item in attr_value: results.append( - " " * (indent + 2) + f"empty {type(attr_value).__name__}" - ) - else: - for item in attr_value: - results.append( - _node_tree_recursive( - item, - indent=indent + 2, - ignored_keys=ignored_keys, - ) + _node_tree_recursive( + item, + indent=indent + 2, + ignored_keys=ignored_keys, ) + ) else: results.append( _node_tree_recursive( @@ -89,4 +88,8 @@ def node_tree( # We are ignoring block attributes by default (in StringValueNode) ignored_keys.append("block") + # Ignore description field which was added to OperationDefinitionNode + # in graphql-core 3.3.0b0 + ignored_keys.append("description") + return _node_tree_recursive(obj, ignored_keys=ignored_keys) Index: gql-4.0.0/gql/utilities/serialize_variable_values.py =================================================================== --- gql-4.0.0.orig/gql/utilities/serialize_variable_values.py +++ gql-4.0.0/gql/utilities/serialize_variable_values.py @@ -115,7 +115,7 @@ def serialize_variable_values( operation = _get_document_operation(document, operation_name=operation_name) # Serialize every variable value defined for the operation - for var_def_node in operation.variable_definitions: + for var_def_node in operation.variable_definitions or (): var_name = var_def_node.variable.name.value var_type = type_from_ast(schema, var_def_node.type) Index: gql-4.0.0/tests/starwars/test_dsl.py =================================================================== --- gql-4.0.0.orig/tests/starwars/test_dsl.py +++ gql-4.0.0/tests/starwars/test_dsl.py @@ -19,7 +19,9 @@ from graphql import ( parse, print_ast, ) +from graphql import __version__ as graphql_version from graphql.utilities import get_introspection_query +from packaging import version from gql import Client, gql from gql.dsl import ( @@ -1015,6 +1017,10 @@ def test_invalid_meta_field_selection(ds ds.Query.hero.select(DSLMetaField("__type")) [email protected]( + version.parse(graphql_version) < version.parse("3.3.0rc0"), + reason="Requires graphql-core >= 3.3.0rc0", +) @pytest.mark.parametrize("option", [True, False]) def test_get_introspection_query_ast(option): @@ -1092,7 +1098,7 @@ DocumentNode definitions: OperationDefinitionNode directives: - empty tuple + None loc: Location <Location 0:43> @@ -1115,9 +1121,9 @@ DocumentNode alias: None arguments: - empty tuple + None directives: - empty tuple + None loc: Location <Location 22:41> @@ -1140,9 +1146,9 @@ DocumentNode alias: None arguments: - empty tuple + None directives: - empty tuple + None loc: Location <Location 33:37> @@ -1158,7 +1164,7 @@ DocumentNode selection_set: None variable_definitions: - empty tuple + None loc: Location <Location 0:43> @@ -1169,7 +1175,7 @@ DocumentNode definitions: OperationDefinitionNode directives: - empty tuple + None loc: Location <Location 0:43> @@ -1192,9 +1198,9 @@ DocumentNode alias: None arguments: - empty tuple + None directives: - empty tuple + None loc: Location <Location 22:41> @@ -1215,9 +1221,9 @@ DocumentNode alias: None arguments: - empty tuple + None directives: - empty tuple + None loc: Location <Location 33:37> @@ -1231,7 +1237,7 @@ DocumentNode selection_set: None variable_definitions: - empty tuple + None loc: Location <Location 0:43> Index: gql-4.0.0/tests/test_transport.py =================================================================== --- gql-4.0.0.orig/tests/test_transport.py +++ gql-4.0.0/tests/test_transport.py @@ -12,15 +12,42 @@ pytestmark = pytest.mark.requests def use_cassette(name): + import json + import vcr + # method to ignore introspection changes in graphql-core 3.3.0b0 + def graphql_body_matcher(r1, r2): + try: + b1 = json.loads(r1.body) + b2 = json.loads(r2.body) + if isinstance(b1, dict) and isinstance(b2, dict): + q1 = b1.get("query", "") + q2 = b2.get("query", "") + if "IntrospectionQuery" in q1 and "IntrospectionQuery" in q2: + return True + return b1 == b2 + elif isinstance(b1, list) and isinstance(b2, list) and len(b1) == len(b2): + for item1, item2 in zip(b1, b2): + q1 = item1.get("query", "") + q2 = item2.get("query", "") + if "IntrospectionQuery" in q1 and "IntrospectionQuery" in q2: + continue + if item1 != item2: + return False + return True + except Exception: + pass + return r1.body == r2.body + query_vcr = vcr.VCR( cassette_library_dir=os.path.join( os.path.dirname(__file__), "fixtures", "vcr_cassettes" ), record_mode="new_episodes", - match_on=["uri", "method", "body"], ) + query_vcr.register_matcher("graphql_body", graphql_body_matcher) + query_vcr.match_on = ["uri", "method", "graphql_body"] return query_vcr.use_cassette(name + ".yaml") Index: gql-4.0.0/tests/test_transport_batch.py =================================================================== --- gql-4.0.0.orig/tests/test_transport_batch.py +++ gql-4.0.0/tests/test_transport_batch.py @@ -12,15 +12,42 @@ pytestmark = pytest.mark.requests def use_cassette(name): + import json + import vcr + # method to ignore introspection changes in graphql-core 3.3.0b0 + def graphql_body_matcher(r1, r2): + try: + b1 = json.loads(r1.body) + b2 = json.loads(r2.body) + if isinstance(b1, dict) and isinstance(b2, dict): + q1 = b1.get("query", "") + q2 = b2.get("query", "") + if "IntrospectionQuery" in q1 and "IntrospectionQuery" in q2: + return True + return b1 == b2 + elif isinstance(b1, list) and isinstance(b2, list) and len(b1) == len(b2): + for item1, item2 in zip(b1, b2): + q1 = item1.get("query", "") + q2 = item2.get("query", "") + if "IntrospectionQuery" in q1 and "IntrospectionQuery" in q2: + continue + if item1 != item2: + return False + return True + except Exception: + pass + return r1.body == r2.body + query_vcr = vcr.VCR( cassette_library_dir=os.path.join( os.path.dirname(__file__), "fixtures", "vcr_cassettes" ), record_mode="new_episodes", - match_on=["uri", "method", "body"], ) + query_vcr.register_matcher("graphql_body", graphql_body_matcher) + query_vcr.match_on = ["uri", "method", "graphql_body"] return query_vcr.use_cassette(name + ".yaml")
