Coverage for farmbot_sidecar_starter_pack/state.py: 100%

66 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-09-03 09:23 -0700

1"""State management.""" 

2 

3import json 

4import inspect 

5from datetime import datetime 

6 

7def get_call_stack_depth(): 

8 """Return the depth of the current call stack.""" 

9 depth = 0 

10 frame = inspect.currentframe() 

11 while frame: 

12 depth += 1 

13 frame = frame.f_back 

14 return depth 

15 

16def get_function_call_info(): 

17 """Return the name and given arguments of the function where this is called.""" 

18 # back to print_status then back to the function that called print_status 

19 frame = inspect.currentframe().f_back.f_back 

20 func_name = frame.f_code.co_name 

21 args, _, _, values = inspect.getargvalues(frame) 

22 arg_strings = [f"{arg}={repr(values[arg])}" for arg in args if arg != "self"] 

23 arg_str = ", ".join(arg_strings) 

24 return f"{func_name}({arg_str})" 

25 

26 

27class State(): 

28 """State class.""" 

29 

30 NO_TOKEN_ERROR = "ERROR: You have no token, please call `get_token` using your login credentials and the server you wish to connect to." 

31 

32 def __init__(self): 

33 self.token = None 

34 self.error = None 

35 self.last_messages = {} 

36 self.last_published = {} 

37 self.verbosity = 2 

38 self.json_printing = True 

39 self.timeout = { 

40 "api": 15, 

41 "listen": 15, 

42 "movements": 120, 

43 } 

44 self.test_env = False 

45 self.ssl = True 

46 self.min_call_stack_depth = 100 

47 self.dry_run = False 

48 self.resource_cache = {} 

49 

50 def print_status(self, endpoint_json=None, description=None, update_only=False, end="\n"): 

51 """Handle changes to output based on user-defined verbosity.""" 

52 depth = get_call_stack_depth() 

53 if depth < self.min_call_stack_depth: 

54 self.min_call_stack_depth = depth 

55 top = depth == self.min_call_stack_depth 

56 no_end = end == "" and description != "" 

57 indent = "" if (top or no_end) else " " * 4 

58 

59 if self.verbosity >= 2 and not update_only: 

60 if top: 

61 print() 

62 function = get_function_call_info() 

63 print(f"{indent}`{function}` called at {datetime.now()}") 

64 if self.verbosity >= 1: 

65 if self.verbosity == 1 and not update_only and top: 

66 print() 

67 if description is not None: 

68 print(indent + description, end=end, flush=(end == "")) 

69 if endpoint_json is not None and self.json_printing: 

70 json_str = json.dumps(endpoint_json, indent=4) 

71 indented_str = indent + json_str.replace("\n", "\n" + indent) 

72 print(indented_str) 

73 

74 def check_token(self): 

75 """Ensure the token persists throughout sidecar.""" 

76 

77 if self.token is None: 

78 self.print_status(description=self.NO_TOKEN_ERROR) 

79 self.error = self.NO_TOKEN_ERROR 

80 raise ValueError(self.NO_TOKEN_ERROR) 

81 

82 def save_cache(self, endpoint, records): 

83 """Cache records.""" 

84 self.resource_cache[endpoint] = records 

85 

86 def fetch_cache(self, endpoint): 

87 """Fetch cached records.""" 

88 return self.resource_cache.get(endpoint) 

89 

90 def clear_cache(self, endpoint=None): 

91 """Clear the cache.""" 

92 if endpoint is not None and endpoint in self.resource_cache: 

93 del self.resource_cache[endpoint] 

94 else: 

95 self.resource_cache = {}