Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Packaging
package/dist
package/build
package/_vendored
package/Output
package/inno_complie_script.iss

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -31,7 +38,6 @@ MANIFEST
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
Expand Down
5 changes: 4 additions & 1 deletion datashuttle/tui_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ def main() -> None:


if __name__ == "__main__":
main()
try:
main()
except:
input("hello")
33 changes: 27 additions & 6 deletions datashuttle/utils/rclone.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import platform
import subprocess
import sys
import tempfile
from pathlib import Path
from subprocess import CompletedProcess
Expand All @@ -11,6 +12,22 @@
from datashuttle.utils.custom_types import TopLevelFolder


def get_command(command: str) -> str:
""" """
if getattr(sys, "frozen", False):
# PyInstaller: binary extracted to _MEIPASS

if sys.platform == "win32":
format_command = f'"{sys._MEIPASS}/rclone.exe" {command}'
else:
format_command = f"{sys._MEIPASS}/rclone {command}"
else:
# Normal Python execution: use PATH or fixed path
format_command = f"rclone {command}" # or provide full path if needed

return format_command


def call_rclone(command: str, pipe_std: bool = False) -> CompletedProcess:
"""Call rclone with the specified command.

Expand All @@ -27,13 +44,17 @@ def call_rclone(command: str, pipe_std: bool = False) -> CompletedProcess:
subprocess.CompletedProcess with `stdout` and `stderr` attributes.

"""
command = "rclone " + command
format_command = get_command(command)

if pipe_std:
output = subprocess.run(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
format_command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
)
else:
output = subprocess.run(command, shell=True)
output = subprocess.run(format_command, shell=True)

return output

Expand All @@ -56,18 +77,18 @@ def call_rclone_through_script(command: str) -> CompletedProcess:
"""
system = platform.system()

command = "rclone " + command

if system == "Windows":
suffix = ".bat"
else:
suffix = ".sh"
command = "#!/bin/bash\n" + command

format_command = get_command(command)

with tempfile.NamedTemporaryFile(
mode="w", suffix=suffix, delete=False
) as tmp_script:
tmp_script.write(command)
tmp_script.write(format_command)
tmp_script_path = tmp_script.name

try:
Expand Down
Binary file added package/NeuroBlueprint_icon.ico
Binary file not shown.
79 changes: 79 additions & 0 deletions package/datashuttle.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# main.spec
# -*- mode: python ; coding: utf-8 -*-
import os
import sys
import platform
from glob import glob
from pathlib import Path

# Include .tcss files
tcss_files = [
(f, os.path.join("datashuttle", "tui", "css"))
for f in glob("../datashuttle/tui/css/*.tcss")
]

# Get current conda environment prefix
env_prefix = sys.prefix

# Detect OS and set rclone path
if platform.system() == "Windows":
rclone_src = os.path.join(env_prefix, "bin", "rclone.exe")
else:
rclone_src = os.path.join(env_prefix, "bin", "rclone")

# Verify rclone exists
if not os.path.isfile(rclone_src):
raise FileNotFoundError(f"rclone binary not found at: {rclone_src}")

# Add rclone as a binary to be bundled
binaries = [(rclone_src, '.')]

a = Analysis(
['datashuttle_launcher.py'], # terminal_launcher
pathex=[os.path.abspath('..')],
binaries=binaries,
datas=tcss_files,
hiddenimports=[
'datashuttle.tui_launcher',
'datashuttle.tui.app',
'textual.widgets._tab_pane',
'textual.widgets._input',
'textual.widgets._tree_control',
],
hookspath=['hooks'],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)

pyz = PYZ(a.pure)

exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='datashuttle',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)

coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='datashuttle'
)
24 changes: 24 additions & 0 deletions package/datashuttle_launcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import sys
from pathlib import Path

# Add project root to sys.path
project_root = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(project_root))

# Import main from tui_launcher
from datashuttle.tui_launcher import main as datashuttle_main


def run():
# Simulate: datashuttle launch
sys.argv = ["datashuttle", "launch"]
datashuttle_main()


if __name__ == "__main__":
try:
run()
except Exception as e:
print(f"\nError: {e}")
finally:
input("\nPress Enter to exit...")
1 change: 1 addition & 0 deletions package/license.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello world
4 changes: 4 additions & 0 deletions package/notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TODO:
1) write package script for macOS and organise code and outputs properly.
2) go back to windows and rework everything
3) text on linux
52 changes: 52 additions & 0 deletions package/package_macos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import shutil
import subprocess
from pathlib import Path

import packaging_utils

WEZTERM_VERSION = packaging_utils.get_wezterm_version()
WEZTERM_FOLDERNAME = f"WezTerm-macos-{WEZTERM_VERSION}"
WEZTERM_URL = f"https://github.com/wezterm/wezterm/releases/download/{WEZTERM_VERSION}/{WEZTERM_FOLDERNAME}.zip"

# Paths
project_root = Path(__file__).parent
vendored_dir = project_root / "_vendored"

if not (vendored_dir / WEZTERM_FOLDERNAME).exists():
packaging_utils.download_wezterm(vendored_dir, WEZTERM_FOLDERNAME)

if (build_path := project_root / "build").exists():
shutil.rmtree(build_path)

if (dist_path := project_root / "dist").exists():
shutil.rmtree(dist_path)

# Step 2: Run PyInstaller builds
subprocess.run(f"pyinstaller {project_root / 'datashuttle.spec'}", shell=True)
subprocess.run(
f"pyinstaller {project_root / 'terminal_launcher_macos.spec'}", shell=True
)

app_macos_path = (
project_root / "dist" / "Datashuttle.app" / "Contents" / "Resources"
)

shutil.copytree(
vendored_dir / f"{WEZTERM_FOLDERNAME}",
app_macos_path / "_vendored" / f"{WEZTERM_FOLDERNAME}",
)

shutil.copytree(
project_root / "dist" / "datashuttle" / "_internal",
app_macos_path.parent / "Resources" / "_internal",
)

shutil.copy(
project_root / "dist" / "datashuttle" / "datashuttle",
app_macos_path.parent / "Resources",
)

shutil.copy(
project_root / "wezterm_config.lua",
app_macos_path.parent / "Resources" / "_vendored" / WEZTERM_FOLDERNAME,
)
Loading
Loading