stockometer 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: stockometer
3
+ Version: 0.1.0
4
+ Summary: CLI wrapper that auto-updates exe from GitHub
5
+ Author: ALV!N
6
+ Requires-Dist: requests
@@ -0,0 +1,9 @@
1
+ [project]
2
+ name = "stockometer"
3
+ version = "0.1.0"
4
+ description = "CLI wrapper that auto-updates exe from GitHub"
5
+ authors = [{name = "ALV!N"}]
6
+ dependencies = ["requests"]
7
+
8
+ [project.scripts]
9
+ stockometer = "yourtool.main:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,13 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ APP_NAME = "stockometer"
5
+
6
+ BASE_DIR = Path.home() / f".{APP_NAME}"
7
+ EXE_PATH = BASE_DIR / "stockometer.exe"
8
+ NEW_EXE_PATH = BASE_DIR / "stockometer_latest.exe"
9
+ VERSION_FILE = BASE_DIR / "version.txt"
10
+
11
+ GITHUB_API = "https://api.github.com/repos/AlvinJoby/stockometer-desktop/releases/latest"
12
+ def ensure_dirs():
13
+ BASE_DIR.mkdir(parents=True, exist_ok=True)
@@ -0,0 +1,51 @@
1
+ import subprocess
2
+ import sys
3
+ import time
4
+
5
+ from .config import *
6
+ from .updater import *
7
+
8
+
9
+ def type_text(text, delay=0.002):
10
+ for char in text:
11
+ sys.stdout.write(char)
12
+ sys.stdout.flush()
13
+ time.sleep(delay)
14
+ print()
15
+
16
+
17
+ def show_banner():
18
+ banner = r"""
19
+ █████╗ ██╗ ██╗ ██╗██╗███╗ ██╗
20
+ ██╔══██╗██║ ██║ ██║██║████╗ ██║
21
+ ███████║██║ ██║ ██║██║██╔██╗ ██║
22
+ ██╔══██║██║ ╚██╗ ██╔╝██║██║╚██╗██║
23
+ ██║ ██║███████╗ ╚████╔╝ ██║██║ ╚████║
24
+ ╚═╝ ╚═╝╚══════╝ ╚═══╝ ╚═╝╚═╝ ╚═══╝
25
+ """
26
+
27
+ print("\n")
28
+ type_text(banner, 0.0015) # fast typing for big text
29
+ time.sleep(0.3)
30
+
31
+
32
+ def run_exe():
33
+ try:
34
+ subprocess.Popen([str(EXE_PATH)])
35
+ except FileNotFoundError:
36
+ print("[stockometer] Executable not found.")
37
+
38
+
39
+ def main():
40
+ show_banner()
41
+
42
+ ensure_dirs()
43
+ first_time_setup()
44
+ replace_exe()
45
+
46
+ run_exe()
47
+ start_background_update()
48
+
49
+
50
+ if __name__ == "__main__":
51
+ main()
@@ -0,0 +1,75 @@
1
+ import threading
2
+ import subprocess
3
+ import os
4
+ import requests
5
+
6
+ from .config import *
7
+ from .utils import download_file
8
+
9
+
10
+ def get_latest_release():
11
+ res = requests.get(GITHUB_API)
12
+ res.raise_for_status()
13
+ data = res.json()
14
+
15
+ version = data["tag_name"]
16
+
17
+ for asset in data["assets"]:
18
+ if asset["name"].endswith(".exe"):
19
+ return version, asset["browser_download_url"]
20
+
21
+ raise Exception("No .exe found in release assets")
22
+
23
+ def get_local_version():
24
+ if not VERSION_FILE.exists():
25
+ return None
26
+ return VERSION_FILE.read_text().strip()
27
+
28
+
29
+ def save_version(version):
30
+ VERSION_FILE.write_text(version)
31
+
32
+
33
+ def replace_exe():
34
+ if NEW_EXE_PATH.exists():
35
+ try:
36
+ os.replace(NEW_EXE_PATH, EXE_PATH)
37
+ except Exception:
38
+ pass # will retry next run
39
+
40
+
41
+ def update_if_needed():
42
+ try:
43
+ latest_version, url = get_latest_release()
44
+ local_version = get_local_version()
45
+
46
+ if local_version == latest_version:
47
+ return
48
+
49
+ print("[stockometer] Updating in background...")
50
+
51
+ download_file(url, NEW_EXE_PATH)
52
+
53
+ replace_exe()
54
+ save_version(latest_version)
55
+
56
+ print("[stockometer] Updated to", latest_version)
57
+
58
+ except Exception:
59
+ pass # silent fail
60
+
61
+
62
+ def start_background_update():
63
+ thread = threading.Thread(target=update_if_needed, daemon=True)
64
+ thread.start()
65
+
66
+
67
+ def first_time_setup():
68
+ if EXE_PATH.exists():
69
+ return
70
+
71
+ print("[yourtool] First time setup: downloading tool...")
72
+
73
+ latest_version, url = get_latest_release()
74
+ download_file(url, EXE_PATH)
75
+ save_version(latest_version)
@@ -0,0 +1,31 @@
1
+ import requests
2
+ import threading
3
+ import itertools
4
+ import sys
5
+ import time
6
+
7
+ def spinner(stop_event, message="Loading"):
8
+ for char in itertools.cycle("|/-\\"):
9
+ if stop_event.is_set():
10
+ break
11
+ sys.stdout.write(f"\r{message} {char}")
12
+ sys.stdout.flush()
13
+ time.sleep(0.1)
14
+ sys.stdout.write("\r")
15
+
16
+ def download_file(url, path):
17
+ stop_event = threading.Event()
18
+ t = threading.Thread(target=spinner, args=(stop_event, "Downloading"))
19
+ t.start()
20
+
21
+ r = requests.get(url, stream=True)
22
+ r.raise_for_status()
23
+
24
+ with open(path, "wb") as f:
25
+ for chunk in r.iter_content(chunk_size=8192):
26
+ f.write(chunk)
27
+
28
+ stop_event.set()
29
+ t.join()
30
+
31
+ print("> Download complete :)")
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: stockometer
3
+ Version: 0.1.0
4
+ Summary: CLI wrapper that auto-updates exe from GitHub
5
+ Author: ALV!N
6
+ Requires-Dist: requests
@@ -0,0 +1,12 @@
1
+ pyproject.toml
2
+ stockometer/__init__.py
3
+ stockometer/config.py
4
+ stockometer/main.py
5
+ stockometer/updater.py
6
+ stockometer/utils.py
7
+ stockometer.egg-info/PKG-INFO
8
+ stockometer.egg-info/SOURCES.txt
9
+ stockometer.egg-info/dependency_links.txt
10
+ stockometer.egg-info/entry_points.txt
11
+ stockometer.egg-info/requires.txt
12
+ stockometer.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ stockometer = yourtool.main:main
@@ -0,0 +1 @@
1
+ requests
@@ -0,0 +1 @@
1
+ stockometer