Skip to content

Commit 4eef921

Browse files
authored
Merge pull request #5 from botcity-dev/fix-resource-discovery
FIX: Iterate over all frames on the stack to add to search path.
2 parents 79b8f57 + de5d777 commit 4eef921

File tree

1 file changed

+47
-10
lines changed

1 file changed

+47
-10
lines changed

botcity/base/bot.py

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,32 @@
88

99

1010
class BaseBot:
11+
12+
def __init__(self, *args, **kwargs):
13+
self._resource_folder_name = "resources"
14+
15+
@property
16+
def resource_folder_name(self) -> str:
17+
"""The name used for the resources folder
18+
when looking for files.
19+
20+
Returns:
21+
str: The folder name for resources. Defaults to `resources`
22+
"""
23+
return self._resource_folder_name or "resources"
24+
25+
@resource_folder_name.setter
26+
def resource_folder_name(self, name: str):
27+
"""The name used for the resources folder
28+
whe looking for files.
29+
30+
Args:
31+
name (str): The folder name for resources. Defaults to `resources`
32+
"""
33+
if not name:
34+
raise ValueError("Resources folder name must not be None nor empty.")
35+
self._resource_folder_name = name
36+
1137
def action(self, execution=None):
1238
"""
1339
Execute an automation action.
@@ -18,7 +44,7 @@ def action(self, execution=None):
1844
"""
1945
raise NotImplementedError("You must implement this method.")
2046

21-
def get_resource_abspath(self, filename, resource_folder="resources"):
47+
def get_resource_abspath(self, filename, resource_folder=None):
2248
"""
2349
Compose the resource absolute path taking into account the package path.
2450
@@ -29,18 +55,26 @@ def get_resource_abspath(self, filename, resource_folder="resources"):
2955
Returns:
3056
abs_path (str): The absolute path to the file.
3157
"""
58+
resource_folder = resource_folder or self.resource_folder_name
3259
return path.join(self._resources_path(resource_folder), filename)
3360

34-
def _resources_path(self, resource_folder="resources"):
61+
def _resources_path(self, resource_folder=None):
3562
# This checks if this is a pyinstaller binary
3663
# More info here: https://pyinstaller.org/en/stable/runtime-information.html#run-time-information
64+
resource_folder = resource_folder or self.resource_folder_name
65+
3766
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
3867
klass_name = self.__class__.__name__
39-
res_path = os.path.join(sys._MEIPASS, klass_name, "resources")
68+
res_path = os.path.join(sys._MEIPASS, klass_name, resource_folder)
4069
else:
4170
res_path = sys.modules[self.__module__].__file__
4271
return path.join(path.dirname(path.realpath(res_path)), resource_folder)
4372

73+
def _get_frame_path(self, frame):
74+
frame_filename = inspect.getframeinfo(frame).filename
75+
frame_dir = os.path.dirname(frame_filename)
76+
return frame_dir
77+
4478
def _search_image_file(self, label):
4579
"""
4680
When finding images, this is the priority in which we will look into:
@@ -55,6 +89,7 @@ def _search_image_file(self, label):
5589
- sys._MEIPASS
5690
- current working dir
5791
"""
92+
resource_folder = self.resource_folder_name
5893

5994
# map_images
6095
img_path = self.state.map_images.get(label)
@@ -71,7 +106,7 @@ def _search_image_file(self, label):
71106
# "resources" folder at sys._MEIPASS/<package>/
72107
locations.append(self.get_resource_abspath(""))
73108
# "resources" folder parallel to the sys._MEIPASS folder
74-
locations.append(os.path.join(sys._MEIPASS, "resources"))
109+
locations.append(os.path.join(sys._MEIPASS, resource_folder))
75110
# sys._MEIPASS
76111
locations.append(sys._MEIPASS)
77112
else:
@@ -82,15 +117,17 @@ def _search_image_file(self, label):
82117

83118
# "resources" folder parallel to the `find` caller file.
84119
try:
85-
caller = inspect.currentframe().f_back.f_back
86-
caller_filename = inspect.getframeinfo(caller).filename
87-
caller_dir = os.path.dirname(caller_filename)
88-
locations.append(os.path.join(caller_dir, "resources"))
120+
frame = inspect.currentframe()
121+
while frame is not None:
122+
caller_dir = self._get_frame_path(frame)
123+
caller_path = os.path.join(caller_dir, resource_folder)
124+
locations.append(caller_path)
125+
frame = frame.f_back
89126
except: # noqa: E722
90127
pass
91128

92129
# "resources" folder parallel to the current working dir
93-
locations.append(os.path.join(os.getcwd(), "resources"))
130+
locations.append(os.path.join(os.getcwd(), resource_folder))
94131

95132
# current working dir
96133
locations.append(os.getcwd())
@@ -125,7 +162,7 @@ def main(cls):
125162
execution = None
126163
# TODO: Refactor this later for proper parameters to be passed
127164
# in a cleaner way
128-
if len(sys.argv) == 4:
165+
if len(sys.argv) >= 4:
129166
if maestro_available:
130167
server, task_id, token = sys.argv[1:4]
131168
bot.maestro = BotMaestroSDK(server=server)

0 commit comments

Comments
 (0)