Coverage for graphqler / compiler / resolvers / resolver.py: 82%
45 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-20 10:09 -0400
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-20 10:09 -0400
1from .utils import find_closest_string
2from graphqler.utils.parser_utils import get_base_oftype
5class Resolver:
6 def __init__(self):
7 pass
9 def get_inputs_related_to_ids(self, inputs: dict, input_objects: dict) -> dict:
10 """Recursively finds any inputs that has ID in its name as that would imply it references other objects
12 Args:
13 inputs (dict): An inputs
14 input_objects (dict): The input objects to be used for recursive search
16 Returns:
17 dict: A dictionary of id and if it's NON_NULL or not IE. {'userId': False, 'clientId': True}
18 """
19 if inputs is None:
20 return {}
21 else:
22 found_ids = {}
23 for input_name, input in inputs.items():
24 if self.is_input_an_id(input):
25 found_ids[input_name] = input["kind"] == "NON_NULL"
26 elif self.is_input_object(input):
27 input_object_name = input["ofType"]["name"]
28 input_object = input_objects[input_object_name]
29 found_ids.update(self.get_inputs_related_to_ids(input_object["inputFields"], input_objects))
30 return found_ids
32 def resolve_inputs_related_to_ids_to_objects(self, endpoint_name: str, inputs_related_to_ids: dict, objects: dict) -> dict:
33 """Resolves inputs related to IDs by looking at the name of the parameter after the ID string is removed
35 Args:
36 endpoint_name (str): The name of the query or mutation for these inputs
37 inputs_related_to_ids (dict): The inputs name (IE: userId)
38 objects (dict): All the possible objects for this API
40 Returns:
41 dict: Input parameters to the objects and the required / not required mappings
42 """
43 input_id_object_mapping = {"hardDependsOn": {}, "softDependsOn": {}}
45 for input_name, required in inputs_related_to_ids.items():
46 # Get the object's name
47 object_name = input_name
48 if input_name.lower() == "id":
49 guessed_object_name = find_closest_string(objects.keys(), endpoint_name)
50 elif input_name.lower() == "ids":
51 guessed_object_name = find_closest_string(objects.keys(), endpoint_name)
52 elif input_name[-2:].lower() == "id":
53 object_name = object_name[:-2]
54 guessed_object_name = find_closest_string(objects.keys(), object_name)
55 elif input_name[-3:].lower() == "ids":
56 object_name = object_name[:-3]
57 guessed_object_name = find_closest_string(objects.keys(), object_name)
58 else:
59 guessed_object_name = ""
61 # Check if the object's name is in the object listing
62 if guessed_object_name in objects:
63 assigned_dependency_name = guessed_object_name
64 else:
65 assigned_dependency_name = "UNKNOWN"
67 # Now assign it either a hardDependsOn or softDependsOn
68 if required:
69 input_id_object_mapping["hardDependsOn"][input_name] = assigned_dependency_name
70 else:
71 input_id_object_mapping["softDependsOn"][input_name] = assigned_dependency_name
72 return input_id_object_mapping
74 def is_input_object(self, input: dict) -> bool:
75 return input["ofType"] and input["ofType"]["kind"] == "INPUT_OBJECT"
77 def is_input_an_id(self, input: dict) -> bool:
78 """Checks if the input is an ID field
80 Args:
81 input (dict): The input field to check
83 Returns:
84 bool: True if the field is an ID, False otherwise
85 """
86 if input["ofType"]:
87 input = get_base_oftype(input["ofType"])
89 return input["kind"] == "SCALAR" and input["type"] == "ID"