Coverage for farmbot_sidecar_starter_pack/state.py: 100%
70 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-09-11 15:43 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-09-11 15:43 -0700
1"""State management."""
3import json
4import inspect
5from datetime import datetime
8def get_call_stack_depth():
9 """Return the depth of the current call stack."""
10 depth = 0
11 frame = inspect.currentframe()
12 while frame:
13 depth += 1
14 frame = frame.f_back
15 return depth
18def get_function_call_info():
19 """Return the name and given arguments of the function where this is called."""
20 # back to print_status then back to the function that called print_status
21 frame = inspect.currentframe().f_back.f_back
22 func_name = frame.f_code.co_name
23 args, _, _, values = inspect.getargvalues(frame)
24 arg_strings = []
25 for arg in args:
26 if arg != "self":
27 arg_strings.append(f"{arg}={repr(values[arg])}")
28 arg_str = ", ".join(arg_strings)
29 return f"{func_name}({arg_str})"
32NO_TOKEN_ERROR = """
33ERROR: You have no token, please call `get_token`
34using your login credentials and the server you wish to connect to.
35"""
38class State():
39 """State class."""
41 NO_TOKEN_ERROR = NO_TOKEN_ERROR.replace("\n", "")
43 def __init__(self):
44 self.token = None
45 self.error = None
46 self.last_messages = {}
47 self.last_published = {}
48 self.verbosity = 2
49 self.json_printing = True
50 self.timeout = {
51 "api": 15,
52 "listen": 15,
53 "movements": 120,
54 }
55 self.test_env = False
56 self.ssl = True
57 self.min_call_stack_depth = 100
58 self.dry_run = False
59 self.resource_cache = {}
61 def print_status(self, endpoint_json=None, description=None, update_only=False, end="\n"):
62 """Handle changes to output based on user-defined verbosity."""
63 depth = get_call_stack_depth()
64 if depth < self.min_call_stack_depth:
65 self.min_call_stack_depth = depth
66 top = depth == self.min_call_stack_depth
67 no_end = end == "" and description != ""
68 indent = "" if (top or no_end) else " " * 4
70 if self.verbosity >= 2 and not update_only:
71 if top:
72 print()
73 function = get_function_call_info()
74 print(f"{indent}`{function}` called at {datetime.now()}")
75 if self.verbosity >= 1:
76 if self.verbosity == 1 and not update_only and top:
77 print()
78 if description is not None:
79 print(indent + description, end=end, flush=end == "")
80 if endpoint_json is not None and self.json_printing:
81 json_str = json.dumps(endpoint_json, indent=4)
82 indented_str = indent + json_str.replace("\n", "\n" + indent)
83 print(indented_str)
85 def check_token(self):
86 """Ensure the token persists throughout sidecar."""
88 if self.token is None:
89 self.print_status(description=self.NO_TOKEN_ERROR)
90 self.error = self.NO_TOKEN_ERROR
91 raise ValueError(self.NO_TOKEN_ERROR)
93 def save_cache(self, endpoint, records):
94 """Cache records."""
95 self.resource_cache[endpoint] = records
97 def fetch_cache(self, endpoint):
98 """Fetch cached records."""
99 return self.resource_cache.get(endpoint)
101 def clear_cache(self, endpoint=None):
102 """Clear the cache."""
103 if endpoint is not None and endpoint in self.resource_cache:
104 del self.resource_cache[endpoint]
105 else:
106 self.resource_cache = {}