Bundler update
auto assets import
frdel committed
Oct 10, 2024 at 20:29 UTC
67f85b7ece187029f77dfc6a62bc9ea94aad173e
3 files changed
+63
-18
bundle.py
+59
-16
@@ -5,10 +5,46 @@ import site
5
import shutil
6
from pathlib import Path
7
import pathspec
8
+import pkg_resources
9
+import importlib
10
+
11
+def get_package_data_files(package_name):
12
+ """Discover data files for a given package."""
13
+ try:
14
+ package = importlib.import_module(package_name)
15
+ package_path = os.path.dirname(package.__file__) # type: ignore
16
+ data_files = []
17
+
18
+ for root, dirs, files in os.walk(package_path):
19
+ for file in files:
20
+ if file.endswith(('.json', '.txt', '.csv', '.yml', '.yaml')):
21
+ file_path = os.path.join(root, file)
22
+ relative_path = os.path.relpath(root, package_path)
23
+ data_files.append((file_path, os.path.join(package_name, relative_path)))
24
+
25
+ return data_files
26
+ except ImportError:
27
+ print(f"Warning: Unable to import {package_name}. Skipping data file discovery for this package.")
28
+ return []
29
+
30
+def get_add_data_args():
31
+ """Return an array of --add-data arguments for PyInstaller."""
32
+ add_data_args = []
33
+
34
+ # Get all installed packages
35
+ installed_packages = [d.project_name for d in pkg_resources.working_set]
36
+
37
+ # Discover data files for each package
38
+ for package in installed_packages:
39
+ data_files = get_package_data_files(package)
40
+ for file_path, dest_path in data_files:
41
+ add_data_args.append(f"--add-data={file_path}{os.pathsep}{dest_path}")
42
+
43
+ return add_data_args
44
45
def get_site_packages_path():
46
"""Get the path to the site-packages directory of the current environment."""
11
- if hasattr(site, 'getsitepackages'):
47
+ if hasattr(site, "getsitepackages"):
48
paths = site.getsitepackages()
49
else:
50
paths = [site.getusersitepackages()]
@@ -18,13 +54,15 @@ def get_site_packages_path():
54
else:
55
raise RuntimeError("Couldn't determine the site-packages path.")
56
57
+
58
def parse_gitignore(gitignore_path):
59
"""Parse .gitignore file and return a PathSpec object."""
60
if not os.path.exists(gitignore_path):
24
- return pathspec.PathSpec.from_lines('gitwildmatch', [])
25
-
26
- with open(gitignore_path, 'r') as f:
27
- return pathspec.PathSpec.from_lines('gitwildmatch', f)
61
+ return pathspec.PathSpec.from_lines("gitwildmatch", [])
62
+
63
+ with open(gitignore_path, "r") as f:
64
+ return pathspec.PathSpec.from_lines("gitwildmatch", f)
65
+
66
67
def copy_project_files(src_dir, dst_dir, spec):
68
"""Copy project files respecting .gitignore rules using pathspec."""
@@ -46,16 +84,17 @@ def copy_project_files(src_dir, dst_dir, spec):
84
85
def cleanup_directories(bundle_name, keep_dist=False):
86
"""Remove build directory and .spec file. Optionally keep dist."""
49
- if not keep_dist and os.path.exists('dist'):
50
- shutil.rmtree('dist')
51
-
52
- if os.path.exists('build'):
53
- shutil.rmtree('build')
54
-
87
+ if not keep_dist and os.path.exists("dist"):
88
+ shutil.rmtree("dist")
89
+
90
+ if os.path.exists("build"):
91
+ shutil.rmtree("build")
92
+
93
spec_file = f"{bundle_name}.spec"
94
if os.path.exists(spec_file):
95
os.remove(spec_file)
96
97
+
98
def build_executable(script_name, exe_name=None):
99
"""Run PyInstaller with the correct site-packages path, clean, and additional data."""
100
try:
@@ -66,11 +105,11 @@ def build_executable(script_name, exe_name=None):
105
print(f"Using site-packages path: {site_packages_path}")
106
107
# Parse .gitignore
69
- gitignore_path = os.path.join(os.getcwd(), '.gitignore')
108
+ gitignore_path = os.path.join(os.getcwd(), ".gitignore")
109
spec = parse_gitignore(gitignore_path)
110
111
# Create a temporary directory for project files
73
- temp_project_dir = os.path.join('build', 'temp_project')
112
+ temp_project_dir = os.path.join("build", "temp_project")
113
os.makedirs(temp_project_dir, exist_ok=True)
114
115
# Copy project files respecting .gitignore
@@ -86,6 +125,9 @@ def build_executable(script_name, exe_name=None):
125
"--workpath=build", # Specify the build directory
126
]
127
128
+ # Add data arguments
129
+ pyinstaller_command.extend(get_add_data_args())
130
+
131
# Add custom name if provided
132
if exe_name:
133
pyinstaller_command.append(f"--name={exe_name}")
@@ -100,8 +142,8 @@ def build_executable(script_name, exe_name=None):
142
subprocess.run(pyinstaller_command, check=True)
143
144
# Post-processing: Manually create the desired structure
103
- dist_dir = os.path.join('dist', exe_name)
104
- project_files_dir = os.path.join(dist_dir, exe_name+"-files")
145
+ dist_dir = os.path.join("dist", exe_name)
146
+ project_files_dir = os.path.join(dist_dir, exe_name + "-files")
147
148
# Move the executable to the root of dist/
149
# shutil.move(os.path.join(temp_exe_dir, exe_name), os.path.join(dist_dir, exe_name))
@@ -133,5 +175,6 @@ def build_executable(script_name, exe_name=None):
175
except Exception as e:
176
print(f"Error: {e}")
177
178
+
179
if __name__ == "__main__":
137
- build_executable("run_bundle.py", "agent-zero")
\ No newline at end of file
180
+ build_executable("run_bundle.py", "agent-zero")
requirements.txt
+1
-1
@@ -14,7 +14,7 @@ langchain-huggingface==0.0.3
14
langchain-mistralai==0.1.8
15
langchain-ollama==0.1.3
16
langchain-openai==0.1.15
17
-lxml-html-clean==0.2.0
17
+lxml_html_clean==0.3.1
18
markdown==3.7
19
newspaper3k==0.2.8
20
paramiko==3.4.0
run_bundle.py
+3
-1
@@ -19,7 +19,9 @@ import langchain_huggingface
19
import langchain_mistralai
20
import langchain_ollama
21
import langchain_openai
22
-import lxml.html.clean
22
+import lxml_html_clean
23
+import emoji
24
+from emoji import unicode_codes
25
import markdown
26
import newspaper
27
import paramiko