`ClientForwardRefsPlugin` Error on generation
Summary
-
ariadne-codegen: 0.14.0 -
python:- 3.12.5
- 3.12.4
- 3.11.2
- https://github.com/mirumee/ariadne-codegen/blob/11bfe35bd62b2489927e0e93c6891bccc29c7f37/ariadne_codegen/contrib/client_forward_refs.py#L176-L188
Error log
Selected strategy: Strategy.CLIENT
Using schema from '....................'.
Reading queries from ''.
Using '********' as package name.
Generating package into '********'.
Using '********' as client name.
Using 'AsyncBaseClient' as base client class.
Coping base client class from '********'.
Generating enums into 'enums.py'.
Generating inputs into 'input_types.py'.
Generating fragments into 'fragments.py'.
Comments type: stable
Converting fields and arguments name to snake case.
Generating async client.
No files to copy.
Plugins to use: ariadne_codegen.contrib.no_reimports.NoReimportsPlugin,ariadne_codegen.contrib.client_forward_refs.ClientForwardRefsPlugin
================================================================================
<ast.Name object at 0x7d2e44ae0ed0> ('lineno', 'col_offset', 'end_lineno', 'end_col_offset') ('id', 'ctx')
self
Traceback (most recent call last):
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/bin/ariadne-codegen", line 8, in <module>
sys.exit(main())
^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/click/core.py", line 1078, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/main.py", line 37, in main
client(config_dict)
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/main.py", line 81, in client
generated_files = package_generator.generate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/client_generators/package.py", line 171, in generate
self._generate_client()
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/client_generators/package.py", line 257, in _generate_client
client_module = self.client_generator.generate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/client_generators/client.py", line 148, in generate
module = self.plugin_manager.generate_client_module(module)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/plugins/manager.py", line 60, in generate_client_module
return self._apply_plugins_on_object("generate_client_module", module)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/plugins/manager.py", line 40, in _apply_plugins_on_object
modified_obj = method(modified_obj, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/contrib/client_forward_refs.py", line 91, in generate_client_module
self._insert_import_statement_in_method(method_def)
File "/workspaces/python-devpod-try/xxDev/graphqltest/.venv/lib/python3.12/site-packages/ariadne_codegen/contrib/client_forward_refs.py", line 188, in _insert_import_statement_in_method
module=self.imported_classes[import_class_id],
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
KeyError: 'self'
Suggestion
https://github.com/mirumee/ariadne-codegen/blob/11bfe35bd62b2489927e0e93c6891bccc29c7f37/ariadne_codegen/contrib/client_forward_refs.py#L176-L188
import_class_id = import_class.id
+ if import_class_id == "self":
+ return
# We add the class to our set of imported in methods - these classes
# don't need to be imported at all in the global scope.
self.imported_in_method.add(import_class.id)
method_def.body.insert(
0,
ast.ImportFrom(
module=self.imported_classes[import_class_id],
names=[import_class],
),
)
In the above context:
print(self.imported_classes)
>>> {'AsyncBaseClient': '.async_base_client', 'UNSET': '.base_model', 'UnsetType': '.base_model', 'Upload': '.base_model', 'GraphQLField': '.base_operation'}
The code you're linking was changed in #306, do you have the same issue on latest main? If so, do you have a reproducible example or do you also get this on any of the two tests?
The code you're linking was changed in #306, do you have the same issue on latest main? If so, do you have a reproducible example or do you also get this on any of the two tests?
The pyroject.toml below would be suffice to demonstrate the case.
Steps:
- run
ariadne-codegenwithout plugins- OK
- run
ariadne-codegenwith the pluginClientForwardRefsPlugin- Error
- remove the previously generated codes and then run
ariadne-codegenwith the pluginClientForwardRefsPlugin- Error
[project]
name = "ard-test"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"ariadne-codegen==0.14.0",
]
[tool.ariadne-codegen]
remote_schema_url = "https://countries.trevorblades.com"
enable_custom_operations = true
plugins = [
"ariadne_codegen.contrib.client_forward_refs.ClientForwardRefsPlugin",
]
Thanks. The example uses latest release (0.14.0) but I was curious about if it failed on main. I used your example and can confirm it does. However, I'm wonder if this is partly related to enable_custom_operations = true since there are no other operations, there's also no other imports so the use of the plugin isn't clear to me. However the generation shouldn't fail.
I was going to run the tests for client forward refs on Python 3.12 but noticed that they never got added to the test fixture. I opened #314 to enable the tests
Thanks. The example uses latest release (
0.14.0) but I was curious about if it failed onmain. I used your example and can confirm it does. However, I'm wonder if this is partly related toenable_custom_operations = truesince there are no other operations, there's also no other imports so the use of the plugin isn't clear to me. However the generation shouldn't fail.I was going to run the tests for client forward refs on Python 3.12 but noticed that they never got added to the test fixture. I opened #314 to enable the tests
I was conducting a feasibility test of this package and am new to GraphQL. My use of the plugin was driven by curiosity to understand how plugins affect the code. The issue I’ve raised is to highlight a case of execution failure, but I am not experiencing issues with using this package otherwise—it appears to be excellent.
Attached are the diff results comparing two scenarios: one without any plugins and one with the ClientForwardRefsPlugin.
To achieve this, I added some error-bypassing code to the library package, which I previously mentioned.
diff --git a/graphql_client/client.py b/graphql_client/client.py
index dc5c970..8ff011b 100644
--- a/graphql_client/client.py
+++ b/graphql_client/client.py
@@ -16,7 +16,10 @@ from graphql import (
)
from .async_base_client import AsyncBaseClient
-from .base_operation import GraphQLField
+from .typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from ..base_operation import GraphQLField
def gql(q: str) -> str:
@@ -25,7 +28,10 @@ def gql(q: str) -> str:
class Client(AsyncBaseClient):
async def execute_custom_operation(
- self, *fields: GraphQLField, operation_type: OperationType, operation_name: str
+ self,
+ *fields: "GraphQLField",
+ operation_type: OperationType,
+ operation_name: str
) -> Dict[str, Any]:
selections = self._build_selection_set(fields)
combined_variables = self._combine_variables(fields)
@@ -43,7 +49,7 @@ class Client(AsyncBaseClient):
return self.get_data(response)
def _combine_variables(
- self, fields: Tuple[GraphQLField, ...]
+ self, fields: Tuple["GraphQLField", ...]
) -> Dict[str, Dict[str, Any]]:
variables_types_combined = {}
processed_variables_combined = {}
@@ -90,11 +96,13 @@ class Client(AsyncBaseClient):
)
def _build_selection_set(
- self, fields: Tuple[GraphQLField, ...]
+ self, fields: Tuple["GraphQLField", ...]
) -> List[SelectionNode]:
return [field.to_ast(idx) for idx, field in enumerate(fields)]
- async def query(self, *fields: GraphQLField, operation_name: str) -> Dict[str, Any]:
+ async def query(
+ self, *fields: "GraphQLField", operation_name: str
+ ) -> Dict[str, Any]:
return await self.execute_custom_operation(
*fields, operation_type=OperationType.QUERY, operation_name=operation_name
)
This is fixed on the main already. Thanks for noticing it. It will be in 0.16.0 ariadne-codegen version.