Coverage for graphqler / compiler / resolvers / mutation_object_resolver.py: 75%

32 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-20 10:09 -0400

1""" 

2This will resolve the inputs of a mutation to object. A few fields will be introduced to a mutation, namely: 

3mutationType: One of [CREATE,UPDATE,DELETE,UNKNOWN] - this is determined semantically 

4hardDependsOn: A dictionary of inputname-object name that is required 

5 in the input (NON-NULL), depends on, ie: {'userId': 'User'} 

6softDependsOn: A dictionary of inputname-object name, depends on, ie: {'userId': 'User'} 

7""" 

8 

9import re 

10 

11from .resolver import Resolver 

12 

13 

14class MutationObjectResolver(Resolver): 

15 def __init__(self): 

16 super().__init__() 

17 

18 def resolve( 

19 self, 

20 objects: dict, 

21 mutations: dict, 

22 input_objects: dict, 

23 ) -> dict: 

24 """Resolve mutation inputs to queries based on semantical understanding of IDs and adds the mutation type 

25 one of [CREATE, UPDATE, DELETE, UNKNOWN] 

26 

27 Args: 

28 objects (dict): Objects to link the mutations to 

29 mutations (dict): Mutations to parse through 

30 input_objects (dict): Input objects to recursively search through different input object inputs 

31 

32 Returns: 

33 dict: The mutations enriched with aforementioned fields 

34 """ 

35 for mutation_name, mutation in mutations.items(): 

36 mutation_type = self.get_mutation_action(mutation_name, mutation["description"]) 

37 inputs_related_to_ids = self.get_inputs_related_to_ids(mutation["inputs"], input_objects) 

38 resolved_objects_to_inputs = self.resolve_inputs_related_to_ids_to_objects(mutation_name, inputs_related_to_ids, objects) 

39 

40 # Assign the enrichments 

41 mutations[mutation_name]["hardDependsOn"] = resolved_objects_to_inputs["hardDependsOn"] 

42 mutations[mutation_name]["softDependsOn"] = resolved_objects_to_inputs["softDependsOn"] 

43 mutations[mutation_name]["mutationType"] = mutation_type 

44 

45 return mutations 

46 

47 def get_mutation_action(self, mutation_name: str, mutation_description: str | None) -> str: 

48 """Gets the method action as a string by checking both the method name and method description 

49 

50 Args: 

51 mutation_name (str): The mutation name 

52 mutation_description (str | None): The mutation description 

53 

54 Returns: 

55 str: One of [CREATE,UDPATE,DELETE,UNKNOWN] 

56 """ 

57 create_pattern = re.compile(r"(create|add|insert)", re.IGNORECASE) 

58 update_pattern = re.compile(r"(update|modify|edit)", re.IGNORECASE) 

59 delete_pattern = re.compile(r"(delete|remove|erase)", re.IGNORECASE) 

60 

61 # Check if the method name matches any pattern 

62 if create_pattern.search(mutation_name): 

63 return "CREATE" 

64 elif update_pattern.search(mutation_name): 

65 return "UPDATE" 

66 elif delete_pattern.search(mutation_name): 

67 return "DELETE" 

68 

69 # Check if the method description matches any pattern 

70 if mutation_description: 

71 if create_pattern.search(mutation_description): 

72 return "CREATE" 

73 elif update_pattern.search(mutation_description): 

74 return "UPDATE" 

75 elif delete_pattern.search(mutation_description): 

76 return "DELETE" 

77 

78 return "UNKNOWN"