ariadne-codegen icon indicating copy to clipboard operation
ariadne-codegen copied to clipboard

`ClientForwardRefsPlugin` Error on generation

Open duodecanol opened this issue 1 year ago • 5 comments

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],
            ),
        )

duodecanol avatar Sep 13 '24 07:09 duodecanol

In the above context:

print(self.imported_classes)
>>> {'AsyncBaseClient': '.async_base_client', 'UNSET': '.base_model', 'UnsetType': '.base_model', 'Upload': '.base_model', 'GraphQLField': '.base_operation'}

duodecanol avatar Sep 13 '24 07:09 duodecanol

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?

bombsimon avatar Sep 13 '24 08:09 bombsimon

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-codegen without plugins
    • OK
  • run ariadne-codegen with the plugin ClientForwardRefsPlugin
    • Error
  • remove the previously generated codes and then run ariadne-codegen with the plugin ClientForwardRefsPlugin
    • 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",
]

duodecanol avatar Sep 15 '24 07:09 duodecanol

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

bombsimon avatar Sep 15 '24 15:09 bombsimon

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

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
         )

duodecanol avatar Sep 15 '24 16:09 duodecanol

This is fixed on the main already. Thanks for noticing it. It will be in 0.16.0 ariadne-codegen version.

DamianCzajkowski avatar Oct 02 '25 13:10 DamianCzajkowski