From 6fc5269d1be82838ffdee005007f2d137f1277f5 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Aug 2024 13:36:47 -0400 Subject: [PATCH 01/19] Refactor scraper --- source/threads/scraper.py | 112 ++++++++++++++++---------------- source/windows/update_window.py | 4 +- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/source/threads/scraper.py b/source/threads/scraper.py index c194dc6..4af69c2 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -34,69 +34,76 @@ logger = logging.getLogger() -def get_latest_tag( - connection_manager: ConnectionManager, - url, -) -> str | None: - r = connection_manager.request("GET", url) +def get_release_tag(connection_manager: ConnectionManager) -> str | None: + if get_use_pre_release_builds(): + url = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/releases" + latest_tag = get_tag(connection_manager, url, pre_release=True) + else: + url = "https://github.com/Victor-IX/Blender-Launcher-V2/releases/latest" + latest_tag = get_tag(connection_manager, url) - if r is None: - return None + logger.info(f"Latest release tag: {latest_tag}") + + return latest_tag - url = r.geturl() - tag = url.rsplit("/", 1)[-1] - r.release_conn() - r.close() - - return tag - - -def get_latest_pre_release_tag( +def get_tag( connection_manager: ConnectionManager, - url, + url: str, + pre_release=False, ) -> str | None: r = connection_manager.request("GET", url) if r is None: return None - try: - parsed_data = json.loads(r.data) - except json.JSONDecodeError: - return None + if pre_release: + try: + parsed_data = json.loads(r.data) + except json.JSONDecodeError as e: + logger.error(f"Failed to parse pre-release tag JSON data: {e}") + return None - platform = get_platform() + platform = get_platform() + + if platform.lower() == "linux": + for key in ( + distro.id().title(), + distro.like().title(), + distro.id(), + distro.like(), + ): + if "ubuntu" in key.lower(): + platform = "Ubuntu" + break + + platform_valid_tags = ( + release["tag_name"] + for release in parsed_data + for asset in release["assets"] + if asset["name"].endswith(".zip") and platform.lower() in asset["name"].lower() + ) + pre_release_tags = (release.lstrip("v") for release in platform_valid_tags) - if platform.lower() == "linux": - for key in ( - distro.id().title(), - distro.like().title(), - distro.id(), - distro.like(), - ): - if "ubuntu" in key.lower(): - platform = "Ubuntu" - break + valid_pre_release_tags = [tag for tag in pre_release_tags if Version.is_valid(tag)] - platform_valid_tags = ( - release["tag_name"] - for release in parsed_data - for asset in release["assets"] - if asset["name"].endswith(".zip") and platform.lower() in asset["name"].lower() - ) - pre_release_tags = (release.lstrip("v") for release in platform_valid_tags) + if valid_pre_release_tags: + tag = max(valid_pre_release_tags, key=Version.parse) + return f"v{tag}" - valid_pre_release_tags = [tag for tag in pre_release_tags if Version.is_valid(tag)] + r.release_conn() + r.close() - if valid_pre_release_tags: - tag = max(valid_pre_release_tags, key=Version.parse) - return f"v{tag}" + return None - r.release_conn() - r.close() + else: + url = r.geturl() + tag = url.rsplit("/", 1)[-1] - return None + r.release_conn() + r.close() + + return tag class Scraper(QThread): @@ -144,14 +151,11 @@ def __init__(self, parent, man: ConnectionManager): def run(self): self.get_download_links() + self.get_release_tag() + def get_release_tag(self): assert self.manager.manager is not None - if get_use_pre_release_builds(): - url = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/releases" - latest_tag = get_latest_pre_release_tag(self.manager, url) - else: - url = "https://github.com/Victor-IX/Blender-Launcher-V2/releases/latest" - latest_tag = get_latest_tag(self.manager, url) + latest_tag = get_release_tag(self.manager) if latest_tag is not None: self.new_bl_version.emit(latest_tag) @@ -325,9 +329,7 @@ def scrap_stable_releases(self): if not any(releases): logger.info("Failed to gather stable releases") logger.info(content) - self.stable_error.emit( - "No releases were scraped from the site!
check -debug logs for more details." - ) + self.stable_error.emit("No releases were scraped from the site!
check -debug logs for more details.") return # Convert string to Verison diff --git a/source/windows/update_window.py b/source/windows/update_window.py index 0279512..5d983ab 100644 --- a/source/windows/update_window.py +++ b/source/windows/update_window.py @@ -11,7 +11,7 @@ from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget from threads.downloader import DownloadTask from threads.extractor import ExtractTask -from threads.scraper import get_latest_tag +from threads.scraper import get_release_tag from widgets.base_progress_bar_widget import BaseProgressBarWidget from windows.base_window import BaseWindow @@ -63,7 +63,7 @@ def __init__(self, app: QApplication, version, release_tag: str | None = None): if release_tag is None: assert self.manager is not None - release_tag = get_latest_tag(self.cm, "https://github.com/Victor-IX/Blender-Launcher-V2/releases/latest") + release_tag = get_release_tag(self.cm) if release_tag is None: # This is ok because release_tag can only be None when # update is invoked from CLI without a release tag From 8a59ccdf48aac2f396388aba07490b69dac83440 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Aug 2024 13:39:00 -0400 Subject: [PATCH 02/19] Add blender launcher api json file --- api/blender_launcher_api.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 api/blender_launcher_api.json diff --git a/api/blender_launcher_api.json b/api/blender_launcher_api.json new file mode 100644 index 0000000..e0cfc10 --- /dev/null +++ b/api/blender_launcher_api.json @@ -0,0 +1,24 @@ +{ + "blender_versions": { + "4.2": "LTS", + "4.1": "non-LTS", + "4.0": "non-LTS", + "3.6": "LTS", + "3.5": "non-LTS", + "3.4": "non-LTS", + "3.3": "LTS", + "3.2": "non-LTS", + "3.1": "non-LTS", + "3.0": "non-LTS", + "2.93": "LTS", + "2.92": "non-LTS", + "2.91": "non-LTS", + "2.90": "non-LTS", + "2.83": "LTS", + "2.82": "non-LTS", + "2.81": "non-LTS", + "2.80": "non-LTS", + "2.79": "non-LTS", + "Custom":"non-LTS" + } +} From d3972beb3c58bdb1fcf978c6a868946b79cf7cb3 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Aug 2024 14:07:17 -0400 Subject: [PATCH 03/19] Add blender launcher API scraper --- source/threads/scraper.py | 40 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/source/threads/scraper.py b/source/threads/scraper.py index 4af69c2..89bb4ff 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -4,6 +4,7 @@ import json import logging import re +import base64 from datetime import datetime, timezone from itertools import chain from pathlib import Path @@ -43,7 +44,7 @@ def get_release_tag(connection_manager: ConnectionManager) -> str | None: latest_tag = get_tag(connection_manager, url) logger.info(f"Latest release tag: {latest_tag}") - + return latest_tag @@ -106,6 +107,30 @@ def get_tag( return tag +def get_bl_api_data(connection_manager: ConnectionManager) -> str | None: + url = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/contents/api/blender_launcher_api.json" + r = connection_manager.request("GET", url) + + if r is None: + return None + + try: + data = json.loads(r.data) + except json.JSONDecodeError as e: + logger.error(f"Failed to parse pre-release tag JSON data: {e}") + return None + + file_content = data["content"] + file_content_encoding = data.get("encoding") + + if file_content_encoding == "base64": + file_content = base64.b64decode(file_content).decode() + logger.info(f"Blender Launcher API data have been loaded successfully") + else: + file_content = None + logger.error(f"Failed to load Blender Launcher API data") + + class Scraper(QThread): links = pyqtSignal(BuildInfo) new_bl_version = pyqtSignal(str) @@ -150,10 +175,11 @@ def __init__(self, parent, man: ConnectionManager): self.scrape_automated = get_scrape_automated_builds() def run(self): + self.get_bl_api_data_manager() self.get_download_links() - self.get_release_tag() + self.get_release_tag_manager() - def get_release_tag(self): + def get_release_tag_manager(self): assert self.manager.manager is not None latest_tag = get_release_tag(self.manager) @@ -161,6 +187,14 @@ def get_release_tag(self): self.new_bl_version.emit(latest_tag) self.manager.manager.clear() + def get_bl_api_data_manager(self): + assert self.manager.manager is not None + bl_api_data = get_bl_api_data(self.manager) + + if bl_api_data is not None: + self.new_bl_version.emit(bl_api_data) + self.manager.manager.clear() + def get_download_links(self): set_locale() From 6992095575c1701f4b14ac391658f0035fe399b2 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Aug 2024 15:47:08 -0400 Subject: [PATCH 04/19] Add API manager --- api/blender_launcher_api.json | 24 -------------------- scripts/build_win.bat | 3 ++- source/modules/bl_api_manager.py | 39 ++++++++++++++++++++++++++++++++ source/threads/scraper.py | 26 ++++++++++++++------- 4 files changed, 59 insertions(+), 33 deletions(-) delete mode 100644 api/blender_launcher_api.json create mode 100644 source/modules/bl_api_manager.py diff --git a/api/blender_launcher_api.json b/api/blender_launcher_api.json deleted file mode 100644 index e0cfc10..0000000 --- a/api/blender_launcher_api.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "blender_versions": { - "4.2": "LTS", - "4.1": "non-LTS", - "4.0": "non-LTS", - "3.6": "LTS", - "3.5": "non-LTS", - "3.4": "non-LTS", - "3.3": "LTS", - "3.2": "non-LTS", - "3.1": "non-LTS", - "3.0": "non-LTS", - "2.93": "LTS", - "2.92": "non-LTS", - "2.91": "non-LTS", - "2.90": "non-LTS", - "2.83": "LTS", - "2.82": "non-LTS", - "2.81": "non-LTS", - "2.80": "non-LTS", - "2.79": "non-LTS", - "Custom":"non-LTS" - } -} diff --git a/scripts/build_win.bat b/scripts/build_win.bat index efd14b5..c8798da 100644 --- a/scripts/build_win.bat +++ b/scripts/build_win.bat @@ -19,7 +19,8 @@ python -OO -m PyInstaller ^ --name="Blender Launcher" ^ --version-file="version.txt" ^ --add-binary="source\resources\icons\winblender.ico;files" ^ ---add-data="source\resources\icons\bl\bl_file.ico;files" ^ +--add-binary="source\resources\icons\bl\bl_file.ico;files" ^ --add-binary="source\resources\certificates\custom.pem;files" ^ +--add-data="source\resources\api\blender_launcher_api.json;files" ^ --distpath="./dist/release" ^ source\main.py diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py new file mode 100644 index 0000000..3b779de --- /dev/null +++ b/source/modules/bl_api_manager.py @@ -0,0 +1,39 @@ +import os +import json +import logging + +from modules._platform import get_config_path, get_cwd + +logger = logging.getLogger() +api_path = os.path.join(get_config_path(), "Blender Launcher API.json") +internal_api_path = (get_cwd() / "source/resources/api/blender_launcher_api.json").as_posix() + +def update_local_api_files(data): + if not os.path.exists(get_config_path()): + os.makedirs(get_config_path()) + logger.info(f"Created config directory in {get_config_path()}") + + with open(api_path, "w") as f: + json.dump(data, f, indent=4) + logger.info(f"Updated API file in {api_path}") + +def read_blender_version(): + if not os.path.exists(api_path): + logger.error(f"API file not found in {api_path}") + api = internal_api_path + else: + api = api_path + + with open(api, "r") as f: + data = json.load(f) + + # Dictionary {"Verison Number" : "LTS"} + blender_vesrion = data["blender_versions"] + return blender_vesrion + +def read_lts_blender_version(): + blender_version = read_blender_version() + + for version, lts in blender_version.items(): + if lts == "LTS": + print (version) diff --git a/source/threads/scraper.py b/source/threads/scraper.py index 89bb4ff..e07189b 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -16,6 +16,7 @@ from modules._platform import get_architecture, get_platform, reset_locale, set_locale, stable_cache_path from modules.build_info import BuildInfo, parse_blender_ver from modules.scraper_cache import StableCache +from modules.bl_api_manager import update_local_api_files, read_lts_blender_version from modules.settings import ( blender_minimum_versions, get_minimum_blender_stable_version, @@ -108,27 +109,34 @@ def get_tag( def get_bl_api_data(connection_manager: ConnectionManager) -> str | None: - url = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/contents/api/blender_launcher_api.json" + url = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/contents/source/resources/api/blender_launcher_api.json" r = connection_manager.request("GET", url) if r is None: + logger.error("Failed to fetch data from the URL.") return None try: data = json.loads(r.data) except json.JSONDecodeError as e: - logger.error(f"Failed to parse pre-release tag JSON data: {e}") + logger.error(f"Failed to parse blender launcher API JSON data: {e}") return None file_content = data["content"] file_content_encoding = data.get("encoding") - if file_content_encoding == "base64": - file_content = base64.b64decode(file_content).decode() - logger.info(f"Blender Launcher API data have been loaded successfully") + if file_content_encoding == "base64" and file_content: + try: + file_content = base64.b64decode(file_content).decode("utf-8") + json_data = json.loads(file_content) + logger.info("Blender Launcher API data have been loaded successfully") + return json_data + except (base64.binascii.Error, json.JSONDecodeError) as e: + logger.error(f"Failed to decode or parse JSON data: {e}") + return None else: - file_content = None - logger.error(f"Failed to load Blender Launcher API data") + logger.error("Failed to load Blender Launcher API data or unsupported encoding.") + return None class Scraper(QThread): @@ -192,7 +200,9 @@ def get_bl_api_data_manager(self): bl_api_data = get_bl_api_data(self.manager) if bl_api_data is not None: - self.new_bl_version.emit(bl_api_data) + update_local_api_files(bl_api_data) + read_lts_blender_version() + self.manager.manager.clear() def get_download_links(self): From 79127053caf7c8959118a48a4e8025311218968c Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Aug 2024 21:51:28 -0400 Subject: [PATCH 05/19] Implement API for blender Version listing --- scripts/build_linux.sh | 1 + scripts/build_linux_debug.sh | 1 + scripts/build_mac.sh | 1 + scripts/build_win_debug.bat | 3 +- source/modules/bl_api_manager.py | 40 ++++++++++++++----- source/modules/build_info.py | 3 +- source/modules/settings.py | 26 +++--------- source/threads/scraper.py | 8 ++-- .../settings_window/blender_builds_tab.py | 4 +- 9 files changed, 47 insertions(+), 40 deletions(-) diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh index 2103fbd..79c0d5e 100644 --- a/scripts/build_linux.sh +++ b/scripts/build_linux.sh @@ -15,5 +15,6 @@ PYTHONOPTIMIZE=2 pyinstaller \ --onefile \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ + --add-data="source/resources/api/blender_launcher_api.json;files" \ --distpath="./dist/release" \ source/main.py diff --git a/scripts/build_linux_debug.sh b/scripts/build_linux_debug.sh index 29523f6..0a5ca95 100644 --- a/scripts/build_linux_debug.sh +++ b/scripts/build_linux_debug.sh @@ -16,5 +16,6 @@ PYTHONOPTIMIZE=2 pyinstaller \ --debug=all \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ + --add-data="source/resources/api/blender_launcher_api.json;files" \ --distpath="./dist/debug" \ source/main.py diff --git a/scripts/build_mac.sh b/scripts/build_mac.sh index 58c2bf7..3a4e43a 100644 --- a/scripts/build_mac.sh +++ b/scripts/build_mac.sh @@ -13,6 +13,7 @@ PYTHONOPTIMIZE=2 pyinstaller \ --hidden-import "pynput.mouse._darwin" \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ + --add-data="source/resources/api/blender_launcher_api.json;files" \ --distpath="./dist/release" \ source/main.py diff --git a/scripts/build_win_debug.bat b/scripts/build_win_debug.bat index 240c0bf..fc03906 100644 --- a/scripts/build_win_debug.bat +++ b/scripts/build_win_debug.bat @@ -19,7 +19,8 @@ python -OO -m PyInstaller ^ --name="Blender Launcher" ^ --version-file="version.txt" ^ --add-binary="source\resources\icons\winblender.ico;files" ^ ---add-data="source\resources\icons\bl\bl_file.ico;files" ^ +--add-binary="source\resources\icons\bl\bl_file.ico;files" ^ --add-binary="source\resources\certificates\custom.pem;files" ^ +--add-data="source\resources\api\blender_launcher_api.json;files" ^ --distpath="./dist/debug" ^ source\main.py diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index 3b779de..35f1fd4 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -8,7 +8,8 @@ api_path = os.path.join(get_config_path(), "Blender Launcher API.json") internal_api_path = (get_cwd() / "source/resources/api/blender_launcher_api.json").as_posix() -def update_local_api_files(data): + +def update_local_api_files(data): if not os.path.exists(get_config_path()): os.makedirs(get_config_path()) logger.info(f"Created config directory in {get_config_path()}") @@ -16,24 +17,41 @@ def update_local_api_files(data): with open(api_path, "w") as f: json.dump(data, f, indent=4) logger.info(f"Updated API file in {api_path}") - -def read_blender_version(): + + +def read_blender_version_list(): if not os.path.exists(api_path): logger.error(f"API file not found in {api_path}") api = internal_api_path else: api = api_path - + with open(api, "r") as f: data = json.load(f) - - # Dictionary {"Verison Number" : "LTS"} + + # Dictionary {"Verison Number" : "LTS"} blender_vesrion = data["blender_versions"] return blender_vesrion - -def read_lts_blender_version(): - blender_version = read_blender_version() - + + +def lts_blender_version(): + blender_version = read_blender_version_list() + lts_vesrion = [] for version, lts in blender_version.items(): if lts == "LTS": - print (version) + lts_vesrion.append(version) + + return tuple(lts_vesrion) + + +def dropdown_blender_version(): + blender_version = read_blender_version_list() + index = 0 + dropdown_blender_version = {} + + for key, _ in blender_version.items(): + dropdown_blender_version[key] = index + index += 1 + + # Dictionary {"Verison Number" : index} + return dropdown_blender_version diff --git a/source/modules/build_info.py b/source/modules/build_info.py index 623a92d..356fe86 100644 --- a/source/modules/build_info.py +++ b/source/modules/build_info.py @@ -10,6 +10,7 @@ from pathlib import Path from modules._platform import _check_output, _popen, get_platform, reset_locale, set_locale +from modules.bl_api_manager import lts_blender_version from modules.settings import ( get_bash_arguments, get_blender_startup_arguments, @@ -107,7 +108,7 @@ class BuildInfo: # Class variables file_version = "1.3" # https://www.blender.org/download/lts/ - lts_tags = ("2.83", "2.93", "3.3", "3.6", "4.2", "4.6", "5.2") + lts_tags = lts_blender_version() # Build variables link: str diff --git a/source/modules/settings.py b/source/modules/settings.py index 3c5c1f7..638f60c 100644 --- a/source/modules/settings.py +++ b/source/modules/settings.py @@ -4,13 +4,13 @@ import sys import uuid from datetime import datetime, timezone -from functools import cache from pathlib import Path +from semver import Version +from PyQt5.QtCore import QSettings from modules._platform import get_config_file, get_config_path, get_cwd, get_platform, local_config, user_config +from modules.bl_api_manager import dropdown_blender_version from modules.version_matcher import VersionSearchQuery -from PyQt5.QtCore import QSettings -from semver import Version EPOCH = datetime.fromtimestamp(0, tz=timezone.utc) ISO_EPOCH = EPOCH.isoformat() @@ -63,22 +63,6 @@ } -blender_minimum_versions = { - "4.0": 0, - "3.6": 1, - "3.5": 2, - "3.4": 3, - "3.3": 4, - "3.2": 5, - "3.1": 6, - "3.0": 7, - "2.90": 8, - "2.80": 9, - "2.79": 10, - "None": 11, -} - - def get_settings(): file = get_config_file() if not file.parent.is_dir(): @@ -449,13 +433,13 @@ def get_minimum_blender_stable_version(): value = get_settings().value("minimum_blender_stable_version") if value is not None and "." in value: - return blender_minimum_versions.get(value, 7) + return dropdown_blender_version().get(value, 7) return get_settings().value("minimum_blender_stable_version", defaultValue=7, type=int) def set_minimum_blender_stable_version(blender_minimum_version): - get_settings().setValue("minimum_blender_stable_version", blender_minimum_versions[blender_minimum_version]) + get_settings().setValue("minimum_blender_stable_version", dropdown_blender_version()[blender_minimum_version]) def get_scrape_stable_builds() -> bool: diff --git a/source/threads/scraper.py b/source/threads/scraper.py index e07189b..81c0b6c 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -16,9 +16,8 @@ from modules._platform import get_architecture, get_platform, reset_locale, set_locale, stable_cache_path from modules.build_info import BuildInfo, parse_blender_ver from modules.scraper_cache import StableCache -from modules.bl_api_manager import update_local_api_files, read_lts_blender_version +from modules.bl_api_manager import update_local_api_files, lts_blender_version, dropdown_blender_version from modules.settings import ( - blender_minimum_versions, get_minimum_blender_stable_version, get_scrape_automated_builds, get_scrape_stable_builds, @@ -201,7 +200,8 @@ def get_bl_api_data_manager(self): if bl_api_data is not None: update_local_api_files(bl_api_data) - read_lts_blender_version() + lts_blender_version() + dropdown_blender_version() self.manager.manager.clear() @@ -378,7 +378,7 @@ def scrap_stable_releases(self): # Convert string to Verison minimum_version_index = get_minimum_blender_stable_version() - version_at_index = list(blender_minimum_versions.keys())[minimum_version_index] + version_at_index = list(dropdown_blender_version().keys())[minimum_version_index] if version_at_index == "None": minimum_smver_version = Version(0, 0, 0) else: diff --git a/source/widgets/settings_window/blender_builds_tab.py b/source/widgets/settings_window/blender_builds_tab.py index 75ffc6f..172bc94 100644 --- a/source/widgets/settings_window/blender_builds_tab.py +++ b/source/widgets/settings_window/blender_builds_tab.py @@ -1,5 +1,4 @@ from modules.settings import ( - blender_minimum_versions, favorite_pages, get_bash_arguments, get_blender_startup_arguments, @@ -35,6 +34,7 @@ set_show_experimental_archive_builds, set_show_patch_archive_builds, ) +from modules.bl_api_manager import dropdown_blender_version from PyQt5 import QtGui from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( @@ -60,7 +60,7 @@ def __init__(self, parent=None): # Minimum stable blender download version (this is mainly for cleanliness and speed) self.MinStableBlenderVer = QComboBox() - self.MinStableBlenderVer.addItems(blender_minimum_versions.keys()) + self.MinStableBlenderVer.addItems(dropdown_blender_version().keys()) self.MinStableBlenderVer.setCurrentIndex(get_minimum_blender_stable_version()) self.MinStableBlenderVer.activated[str].connect(self.change_minimum_blender_stable_version) From 8b09b68bef40b08f9dbbc79d33151d9bc2c4de63 Mon Sep 17 00:00:00 2001 From: Victor Date: Sun, 25 Aug 2024 22:18:13 -0400 Subject: [PATCH 06/19] refactor --- source/modules/bl_api_manager.py | 58 +++++++++++++------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index 35f1fd4..2deb357 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -1,57 +1,45 @@ -import os import json import logging - +from pathlib import Path +from functools import lru_cache from modules._platform import get_config_path, get_cwd logger = logging.getLogger() -api_path = os.path.join(get_config_path(), "Blender Launcher API.json") -internal_api_path = (get_cwd() / "source/resources/api/blender_launcher_api.json").as_posix() + +config_path = Path(get_config_path()) +api_path = config_path / "Blender Launcher API.json" +internal_api_path = get_cwd() / "source/resources/api/blender_launcher_api.json" def update_local_api_files(data): - if not os.path.exists(get_config_path()): - os.makedirs(get_config_path()) - logger.info(f"Created config directory in {get_config_path()}") + if not config_path.exists(): + config_path.mkdir(parents=True) + logger.info(f"Created config directory in {config_path}") - with open(api_path, "w") as f: - json.dump(data, f, indent=4) - logger.info(f"Updated API file in {api_path}") + try: + with open(api_path, "w") as f: + json.dump(data, f, indent=4) + logger.info(f"Updated API file in {api_path}") + read_blender_version_list.cache_clear() + except IOError as e: + logger.error(f"Failed to write API file: {e}") +@lru_cache(maxsize=1) def read_blender_version_list(): - if not os.path.exists(api_path): - logger.error(f"API file not found in {api_path}") - api = internal_api_path - else: - api = api_path + api = api_path if api_path.exists() else internal_api_path + if api == internal_api_path: + logger.error(f"API file not found in {api_path}. Using internal API file.") with open(api, "r") as f: data = json.load(f) - # Dictionary {"Verison Number" : "LTS"} - blender_vesrion = data["blender_versions"] - return blender_vesrion + return data.get("blender_versions", {}) def lts_blender_version(): - blender_version = read_blender_version_list() - lts_vesrion = [] - for version, lts in blender_version.items(): - if lts == "LTS": - lts_vesrion.append(version) - - return tuple(lts_vesrion) + return tuple(version for version, lts in read_blender_version_list().items() if lts == "LTS") def dropdown_blender_version(): - blender_version = read_blender_version_list() - index = 0 - dropdown_blender_version = {} - - for key, _ in blender_version.items(): - dropdown_blender_version[key] = index - index += 1 - - # Dictionary {"Verison Number" : index} - return dropdown_blender_version + return {key: index for index, key in enumerate(read_blender_version_list().keys())} From 6b5aa75142d7256d4556795eff1798030c055ece Mon Sep 17 00:00:00 2001 From: zeptofine Date: Tue, 27 Aug 2024 15:12:05 -0400 Subject: [PATCH 07/19] move reading the bl api outside of read_blender_version_list --- source/modules/bl_api_manager.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index 2deb357..c9a5387 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -1,7 +1,8 @@ import json import logging -from pathlib import Path from functools import lru_cache +from pathlib import Path + from modules._platform import get_config_path, get_cwd logger = logging.getLogger() @@ -20,21 +21,22 @@ def update_local_api_files(data): with open(api_path, "w") as f: json.dump(data, f, indent=4) logger.info(f"Updated API file in {api_path}") - read_blender_version_list.cache_clear() - except IOError as e: + read_bl_api.cache_clear() + except OSError as e: logger.error(f"Failed to write API file: {e}") - @lru_cache(maxsize=1) -def read_blender_version_list(): +def read_bl_api()-> dict: api = api_path if api_path.exists() else internal_api_path if api == internal_api_path: logger.error(f"API file not found in {api_path}. Using internal API file.") - with open(api, "r") as f: - data = json.load(f) + with open(api) as f: + return json.load(f) + - return data.get("blender_versions", {}) +def read_blender_version_list() -> dict[str, str]: + return read_bl_api().get("blender_versions", {}) def lts_blender_version(): From f6a350a633dffec3ad199042f115b50288961643 Mon Sep 17 00:00:00 2001 From: zeptofine Date: Tue, 27 Aug 2024 15:45:36 -0400 Subject: [PATCH 08/19] Move minimum_blender_stable_version to store a string --- source/modules/bl_api_manager.py | 11 +++++++- source/modules/settings.py | 25 ++++++++++++------- source/threads/scraper.py | 11 ++++---- .../settings_window/blender_builds_tab.py | 15 +++++++---- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index c9a5387..1da1a30 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -43,5 +43,14 @@ def lts_blender_version(): return tuple(version for version, lts in read_blender_version_list().items() if lts == "LTS") -def dropdown_blender_version(): +def dropdown_blender_version() -> dict[str, int]: + """Ex: + + { + "4.0": 0, + "3.6": 1, + "3.5": 2, + "3.4": 3 + } + """ return {key: index for index, key in enumerate(read_blender_version_list().keys())} diff --git a/source/modules/settings.py b/source/modules/settings.py index 638f60c..f59f582 100644 --- a/source/modules/settings.py +++ b/source/modules/settings.py @@ -1,3 +1,4 @@ +from __future__ import annotations import contextlib import os import shutil @@ -5,12 +6,12 @@ import uuid from datetime import datetime, timezone from pathlib import Path -from semver import Version -from PyQt5.QtCore import QSettings from modules._platform import get_config_file, get_config_path, get_cwd, get_platform, local_config, user_config from modules.bl_api_manager import dropdown_blender_version from modules.version_matcher import VersionSearchQuery +from PyQt5.QtCore import QSettings +from semver import Version EPOCH = datetime.fromtimestamp(0, tz=timezone.utc) ISO_EPOCH = EPOCH.isoformat() @@ -429,17 +430,23 @@ def set_check_for_new_builds_on_startup(b: bool): get_settings().setValue("buildcheck_on_startup", b) -def get_minimum_blender_stable_version(): - value = get_settings().value("minimum_blender_stable_version") +def get_minimum_blender_stable_version() -> str: + value = get_settings().value("minimum_blender_stable_version", defaultValue="3.0", type=str) + # value can never be None + if value == "None": + return "3.0" - if value is not None and "." in value: - return dropdown_blender_version().get(value, 7) + # backwards compatibility for indexesq + # (This is not reccommended because it relies on the dropdown blender versions to be static) + with contextlib.suppress(ValueError, IndexError): + if "." not in value: + return list(dropdown_blender_version())[int(value)] - return get_settings().value("minimum_blender_stable_version", defaultValue=7, type=int) + return value -def set_minimum_blender_stable_version(blender_minimum_version): - get_settings().setValue("minimum_blender_stable_version", dropdown_blender_version()[blender_minimum_version]) +def set_minimum_blender_stable_version(blender_minimum_version: str): + get_settings().setValue("minimum_blender_stable_version", blender_minimum_version) def get_scrape_stable_builds() -> bool: diff --git a/source/threads/scraper.py b/source/threads/scraper.py index 81c0b6c..f533df5 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -1,10 +1,10 @@ from __future__ import annotations +import base64 import contextlib import json import logging import re -import base64 from datetime import datetime, timezone from itertools import chain from pathlib import Path @@ -14,9 +14,9 @@ import distro from bs4 import BeautifulSoup, SoupStrainer from modules._platform import get_architecture, get_platform, reset_locale, set_locale, stable_cache_path +from modules.bl_api_manager import dropdown_blender_version, lts_blender_version, update_local_api_files from modules.build_info import BuildInfo, parse_blender_ver from modules.scraper_cache import StableCache -from modules.bl_api_manager import update_local_api_files, lts_blender_version, dropdown_blender_version from modules.settings import ( get_minimum_blender_stable_version, get_scrape_automated_builds, @@ -377,12 +377,11 @@ def scrap_stable_releases(self): return # Convert string to Verison - minimum_version_index = get_minimum_blender_stable_version() - version_at_index = list(dropdown_blender_version().keys())[minimum_version_index] - if version_at_index == "None": + minimum_version_str = get_minimum_blender_stable_version() + if minimum_version_str == "None": minimum_smver_version = Version(0, 0, 0) else: - major, minor = version_at_index.split(".") + major, minor = minimum_version_str.split(".") minimum_smver_version = Version(int(major), int(minor), 0) cache_modified = False diff --git a/source/widgets/settings_window/blender_builds_tab.py b/source/widgets/settings_window/blender_builds_tab.py index 172bc94..24adfa3 100644 --- a/source/widgets/settings_window/blender_builds_tab.py +++ b/source/widgets/settings_window/blender_builds_tab.py @@ -1,3 +1,4 @@ +from modules.bl_api_manager import dropdown_blender_version from modules.settings import ( favorite_pages, get_bash_arguments, @@ -34,7 +35,6 @@ set_show_experimental_archive_builds, set_show_patch_archive_builds, ) -from modules.bl_api_manager import dropdown_blender_version from PyQt5 import QtGui from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( @@ -60,8 +60,13 @@ def __init__(self, parent=None): # Minimum stable blender download version (this is mainly for cleanliness and speed) self.MinStableBlenderVer = QComboBox() - self.MinStableBlenderVer.addItems(dropdown_blender_version().keys()) - self.MinStableBlenderVer.setCurrentIndex(get_minimum_blender_stable_version()) + keys = list(dropdown_blender_version().keys()) + if keys[-1] == "Custom": # this should always be the case, but just to be safe + keys.remove("Custom") + + keys.append("None") + self.MinStableBlenderVer.addItems(keys) + self.MinStableBlenderVer.setCurrentText(get_minimum_blender_stable_version()) self.MinStableBlenderVer.activated[str].connect(self.change_minimum_blender_stable_version) # Whether to check for new builds based on a timer @@ -202,8 +207,8 @@ def __init__(self, parent=None): def change_mark_as_favorite(self, page): set_mark_as_favorite(page) - def change_minimum_blender_stable_version(self, proxy_type): - set_minimum_blender_stable_version(proxy_type) + def change_minimum_blender_stable_version(self, minimum): + set_minimum_blender_stable_version(minimum) def update_blender_startup_arguments(self): args = self.BlenderStartupArguments.text() From adc09537077efb38df6575a23dc56ecc49d49a27 Mon Sep 17 00:00:00 2001 From: zeptofine Date: Tue, 27 Aug 2024 16:16:06 -0400 Subject: [PATCH 09/19] remove MinStableBlenderVer "custom" check --- source/widgets/settings_window/blender_builds_tab.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/widgets/settings_window/blender_builds_tab.py b/source/widgets/settings_window/blender_builds_tab.py index 24adfa3..3846fec 100644 --- a/source/widgets/settings_window/blender_builds_tab.py +++ b/source/widgets/settings_window/blender_builds_tab.py @@ -61,9 +61,6 @@ def __init__(self, parent=None): # Minimum stable blender download version (this is mainly for cleanliness and speed) self.MinStableBlenderVer = QComboBox() keys = list(dropdown_blender_version().keys()) - if keys[-1] == "Custom": # this should always be the case, but just to be safe - keys.remove("Custom") - keys.append("None") self.MinStableBlenderVer.addItems(keys) self.MinStableBlenderVer.setCurrentText(get_minimum_blender_stable_version()) From 6158bda430a525ed674d528e7f04b96d33cd97fc Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 21:09:28 -0400 Subject: [PATCH 10/19] Remove Custom from API file and None from version selection --- source/modules/settings.py | 5 ++--- source/resources/api/blender_launcher_api.json | 3 +-- source/widgets/settings_window/blender_builds_tab.py | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/source/modules/settings.py b/source/modules/settings.py index f59f582..758e23b 100644 --- a/source/modules/settings.py +++ b/source/modules/settings.py @@ -436,12 +436,11 @@ def get_minimum_blender_stable_version() -> str: if value == "None": return "3.0" - # backwards compatibility for indexesq - # (This is not reccommended because it relies on the dropdown blender versions to be static) + # backwards compatibility for indexes + # (This is not recommended because it relies on the dropdown blender versions to be static) with contextlib.suppress(ValueError, IndexError): if "." not in value: return list(dropdown_blender_version())[int(value)] - return value diff --git a/source/resources/api/blender_launcher_api.json b/source/resources/api/blender_launcher_api.json index e0cfc10..e2d2178 100644 --- a/source/resources/api/blender_launcher_api.json +++ b/source/resources/api/blender_launcher_api.json @@ -18,7 +18,6 @@ "2.82": "non-LTS", "2.81": "non-LTS", "2.80": "non-LTS", - "2.79": "non-LTS", - "Custom":"non-LTS" + "2.79": "non-LTS" } } diff --git a/source/widgets/settings_window/blender_builds_tab.py b/source/widgets/settings_window/blender_builds_tab.py index 3846fec..6c86979 100644 --- a/source/widgets/settings_window/blender_builds_tab.py +++ b/source/widgets/settings_window/blender_builds_tab.py @@ -61,7 +61,6 @@ def __init__(self, parent=None): # Minimum stable blender download version (this is mainly for cleanliness and speed) self.MinStableBlenderVer = QComboBox() keys = list(dropdown_blender_version().keys()) - keys.append("None") self.MinStableBlenderVer.addItems(keys) self.MinStableBlenderVer.setCurrentText(get_minimum_blender_stable_version()) self.MinStableBlenderVer.activated[str].connect(self.change_minimum_blender_stable_version) From 84acb7ac78988c02fb16a218653aff5886179082 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 21:52:57 -0400 Subject: [PATCH 11/19] Add Stable Build info as an API file and add a file version to API files --- .../resources/api/blender_launcher_api.json | 3 +- source/resources/api/stable_builds_api.json | 1970 +++++++++++++++++ 2 files changed, 1972 insertions(+), 1 deletion(-) create mode 100644 source/resources/api/stable_builds_api.json diff --git a/source/resources/api/blender_launcher_api.json b/source/resources/api/blender_launcher_api.json index e2d2178..9add71d 100644 --- a/source/resources/api/blender_launcher_api.json +++ b/source/resources/api/blender_launcher_api.json @@ -1,4 +1,5 @@ { + "api_file_version": "1.0", "blender_versions": { "4.2": "LTS", "4.1": "non-LTS", @@ -20,4 +21,4 @@ "2.80": "non-LTS", "2.79": "non-LTS" } -} +} \ No newline at end of file diff --git a/source/resources/api/stable_builds_api.json b/source/resources/api/stable_builds_api.json new file mode 100644 index 0000000..b9cc54e --- /dev/null +++ b/source/resources/api/stable_builds_api.json @@ -0,0 +1,1970 @@ +{ + "api_file_version": "1.0", + "folders": { + "3.3.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.0", + "build_hash": null, + "commit_time": "2022-09-07T08:24:02-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.1", + "build_hash": null, + "commit_time": "2022-10-05T08:32:48-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.10-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.10", + "build_hash": null, + "commit_time": "2023-08-17T07:46:33-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.11-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.11", + "build_hash": null, + "commit_time": "2023-09-21T08:54:08-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.12-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.12", + "build_hash": null, + "commit_time": "2023-10-19T10:02:53-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.14-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.14", + "build_hash": null, + "commit_time": "2023-12-12T12:06:03-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.15-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.15", + "build_hash": null, + "commit_time": "2024-01-16T09:28:13-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.16-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.16", + "build_hash": null, + "commit_time": "2024-02-20T09:34:03-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.17-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.17", + "build_hash": null, + "commit_time": "2024-03-19T10:16:13-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.18-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.18", + "build_hash": null, + "commit_time": "2024-04-16T08:20:05-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.19-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.19", + "build_hash": null, + "commit_time": "2024-05-21T10:07:20-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.2-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.2", + "build_hash": null, + "commit_time": "2022-12-07T09:24:46-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.20-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.20", + "build_hash": null, + "commit_time": "2024-06-25T10:11:46-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.21-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.21", + "build_hash": null, + "commit_time": "2024-07-16T07:39:30-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.3-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.3", + "build_hash": null, + "commit_time": "2023-01-17T11:39:10-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.4-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.4", + "build_hash": null, + "commit_time": "2023-02-21T08:46:42-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.5-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.5", + "build_hash": null, + "commit_time": "2023-03-21T09:09:59-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.6-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.6", + "build_hash": null, + "commit_time": "2023-04-18T08:25:03-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.7-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.7", + "build_hash": null, + "commit_time": "2023-05-23T08:26:41-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.8-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.8", + "build_hash": null, + "commit_time": "2023-06-20T10:10:58-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.3/blender-3.3.9-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.3.9", + "build_hash": null, + "commit_time": "2023-07-18T08:37:14-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2024-07-16T11:39:00+00:00" + }, + "3.4.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.4/blender-3.4.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.4.0", + "build_hash": null, + "commit_time": "2022-12-07T09:50:16-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.4/blender-3.4.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.4.1", + "build_hash": null, + "commit_time": "2022-12-20T09:39:31-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2022-12-20T14:39:00+00:00" + }, + "3.5.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.5/blender-3.5.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.5.0", + "build_hash": null, + "commit_time": "2023-03-29T09:00:15-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.5/blender-3.5.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.5.1", + "build_hash": null, + "commit_time": "2023-04-25T11:41:09-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2023-04-25T15:41:00+00:00" + }, + "3.6.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.0", + "build_hash": null, + "commit_time": "2023-06-27T09:53:57-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.1", + "build_hash": null, + "commit_time": "2023-07-18T08:42:19-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.10-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.10", + "build_hash": null, + "commit_time": "2024-03-19T08:14:57-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.11-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.11", + "build_hash": null, + "commit_time": "2024-04-16T08:07:19-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.12-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.12", + "build_hash": null, + "commit_time": "2024-05-21T10:48:11-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.13-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.13", + "build_hash": null, + "commit_time": "2024-06-25T10:12:52-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.14-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.14", + "build_hash": null, + "commit_time": "2024-07-16T07:41:18-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.15-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.15", + "build_hash": null, + "commit_time": "2024-08-20T07:37:56-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.2-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.2", + "build_hash": null, + "commit_time": "2023-08-17T07:51:06-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.3-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.3", + "build_hash": null, + "commit_time": "2023-09-21T08:54:54-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.4-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.4", + "build_hash": null, + "commit_time": "2023-09-26T08:47:17-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.5-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.5", + "build_hash": null, + "commit_time": "2023-10-19T09:59:59-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.7-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.7", + "build_hash": null, + "commit_time": "2023-12-12T12:31:08-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.8-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.8", + "build_hash": null, + "commit_time": "2024-01-16T09:29:23-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.6/blender-3.6.9-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "3.6.9", + "build_hash": null, + "commit_time": "2024-02-20T09:37:18-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2024-08-20T11:37:00+00:00" + }, + "4.0.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender4.0/blender-4.0.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "4.0.0", + "build_hash": null, + "commit_time": "2023-11-14T08:54:43-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender4.0/blender-4.0.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "4.0.1", + "build_hash": null, + "commit_time": "2023-11-17T10:04:11-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender4.0/blender-4.0.2-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "4.0.2", + "build_hash": null, + "commit_time": "2023-12-05T14:19:55-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2023-12-05T19:19:00+00:00" + }, + "4.1.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender4.1/blender-4.1.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "4.1.0", + "build_hash": null, + "commit_time": "2024-03-26T10:57:11-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender4.1/blender-4.1.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "4.1.1", + "build_hash": null, + "commit_time": "2024-04-16T08:41:55-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2024-04-16T12:42:00+00:00" + }, + "4.2.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender4.2/blender-4.2.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "4.2.0", + "build_hash": null, + "commit_time": "2024-07-16T08:53:20-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender4.2/blender-4.2.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "4.2.1", + "build_hash": null, + "commit_time": "2024-08-20T07:37:57-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2024-08-20T11:38:00+00:00" + }, + "2.79.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.79/blender-2.79-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.79.0", + "build_hash": null, + "commit_time": "2017-09-11T15:42:37-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.79/blender-2.79a-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.79.0-a", + "build_hash": null, + "commit_time": "2018-02-27T15:30:55-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.79/blender-2.79b-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.79.0-b", + "build_hash": null, + "commit_time": "2018-03-22T16:58:21-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2019-07-29T17:11:00+00:00" + }, + "2.80.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.80/blender-2.80-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.80.0", + "build_hash": null, + "commit_time": "2019-07-29T17:21:25-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.80/blender-2.80rc1-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.80.0-rc1", + "build_hash": null, + "commit_time": "2019-07-11T16:59:00-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.80/blender-2.80rc2-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.80.0-rc2", + "build_hash": null, + "commit_time": "2019-07-18T17:20:21-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.80/blender-2.80rc3-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.80.0-rc3", + "build_hash": null, + "commit_time": "2019-07-24T16:36:07-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2019-07-29T21:23:00+00:00" + }, + "2.81.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.81/blender-2.81-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.81.0", + "build_hash": null, + "commit_time": "2019-11-21T08:08:30-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.81/blender-2.81a-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.81.0-a", + "build_hash": null, + "commit_time": "2019-12-05T11:51:04-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2019-12-05T16:52:00+00:00" + }, + "2.82.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.82/blender-2.82-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.82.0", + "build_hash": null, + "commit_time": "2020-02-13T09:17:36-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.82/blender-2.82a-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.82.0-a", + "build_hash": null, + "commit_time": "2020-03-12T10:45:32-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2020-03-12T14:48:00+00:00" + }, + "2.83.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.0-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.0", + "build_hash": null, + "commit_time": "2020-06-03T15:28:39-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.1-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.1", + "build_hash": null, + "commit_time": "2020-06-25T11:59:39-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.10-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.10", + "build_hash": null, + "commit_time": "2020-12-09T09:12:48-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.12-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.12", + "build_hash": null, + "commit_time": "2021-01-27T09:03:13-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.13-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.13", + "build_hash": null, + "commit_time": "2021-03-10T09:26:21-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.14-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.14", + "build_hash": null, + "commit_time": "2021-05-12T14:37:02-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.15-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.15", + "build_hash": null, + "commit_time": "2021-05-20T06:54:52-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.16-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.16", + "build_hash": null, + "commit_time": "2021-06-16T09:28:40-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.17-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.17", + "build_hash": null, + "commit_time": "2021-08-11T09:11:37-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.18-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.18", + "build_hash": null, + "commit_time": "2021-09-29T10:42:05-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.19-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.19", + "build_hash": null, + "commit_time": "2022-02-02T09:42:30-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.2-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.2", + "build_hash": null, + "commit_time": "2020-07-09T06:45:37-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.20-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.20", + "build_hash": null, + "commit_time": "2022-04-20T09:26:43-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.3-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.3", + "build_hash": null, + "commit_time": "2020-07-22T06:37:38-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.4-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.4", + "build_hash": null, + "commit_time": "2020-08-05T06:28:04-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.5-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.5", + "build_hash": null, + "commit_time": "2020-08-19T06:41:36-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.6-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.6", + "build_hash": null, + "commit_time": "2020-09-09T08:22:24-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.7-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.7", + "build_hash": null, + "commit_time": "2020-09-30T06:42:42-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.8-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.8", + "build_hash": null, + "commit_time": "2020-10-21T09:06:03-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.83/blender-2.83.9-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.83.9", + "build_hash": null, + "commit_time": "2020-11-11T15:54:52-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2022-04-20T13:26:00+00:00" + }, + "2.90.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.90/blender-2.90.0-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.90.0", + "build_hash": null, + "commit_time": "2020-08-31T12:33:28-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.90/blender-2.90.1-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.90.1", + "build_hash": null, + "commit_time": "2020-09-23T08:54:44-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2020-09-23T13:13:00+00:00" + }, + "2.91.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.91/blender-2.91.0-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.91.0", + "build_hash": null, + "commit_time": "2020-11-25T09:24:23-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.91/blender-2.91.2-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.91.2", + "build_hash": null, + "commit_time": "2021-01-20T12:05:06-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2021-02-02T00:47:00+00:00" + }, + "2.92.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.92/blender-2.92.0-windows64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "2.92.0", + "build_hash": null, + "commit_time": "2021-02-25T12:04:18-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2021-02-25T17:03:00+00:00" + }, + "2.93.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.0", + "build_hash": null, + "commit_time": "2021-06-02T14:23:33-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.1", + "build_hash": null, + "commit_time": "2021-06-23T07:41:28-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.10-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.10", + "build_hash": null, + "commit_time": "2022-08-03T08:58:16-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.11-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.11", + "build_hash": null, + "commit_time": "2022-10-05T08:30:01-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.12-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.12", + "build_hash": null, + "commit_time": "2022-12-20T10:08:21-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.13-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.13", + "build_hash": null, + "commit_time": "2022-12-21T08:39:10-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.14-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.14", + "build_hash": null, + "commit_time": "2023-01-17T11:04:06-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.15-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.15", + "build_hash": null, + "commit_time": "2023-02-21T09:05:30-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.16-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.16", + "build_hash": null, + "commit_time": "2023-03-21T09:06:40-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.17-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.17", + "build_hash": null, + "commit_time": "2023-04-18T08:21:40-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.18-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.18", + "build_hash": null, + "commit_time": "2023-05-23T08:23:40-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.2-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.2", + "build_hash": null, + "commit_time": "2021-08-04T10:40:36-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.3-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.3", + "build_hash": null, + "commit_time": "2021-08-18T09:06:12-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.4-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.4", + "build_hash": null, + "commit_time": "2021-09-01T09:29:46-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.5-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.5", + "build_hash": null, + "commit_time": "2021-10-06T09:26:14-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.6-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.6", + "build_hash": null, + "commit_time": "2021-11-17T12:47:04-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.7-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.7", + "build_hash": null, + "commit_time": "2021-12-15T10:46:31-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.8-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.8", + "build_hash": null, + "commit_time": "2022-02-02T09:42:48-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender2.93/blender-2.93.9-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "lts", + "subversion": "2.93.9", + "build_hash": null, + "commit_time": "2022-04-20T08:59:03-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2023-05-23T12:23:00+00:00" + }, + "3.0.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.0/blender-3.0.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.0.0", + "build_hash": null, + "commit_time": "2021-12-03T10:06:33-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.0/blender-3.0.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.0.1", + "build_hash": null, + "commit_time": "2022-01-26T13:17:15-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2022-01-26T18:21:00+00:00" + }, + "3.1.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.1/blender-3.1.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.1.0", + "build_hash": null, + "commit_time": "2022-03-09T10:10:40-05:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.1/blender-3.1.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.1.1", + "build_hash": null, + "commit_time": "2022-03-30T09:29:10-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.1/blender-3.1.2-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.1.2", + "build_hash": null, + "commit_time": "2022-04-01T08:22:57-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2022-04-01T12:23:00+00:00" + }, + "3.2.0": { + "assets": [ + [ + "https://download.blender.org/release/Blender3.2/blender-3.2.0-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.2.0", + "build_hash": null, + "commit_time": "2022-06-08T12:14:06-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.2/blender-3.2.1-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.2.1", + "build_hash": null, + "commit_time": "2022-07-06T10:08:53-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ], + [ + "https://download.blender.org/release/Blender3.2/blender-3.2.2-windows-x64.zip", + { + "file_version": "1.3", + "blinfo": [ + { + "branch": "stable", + "subversion": "3.2.2", + "build_hash": null, + "commit_time": "2022-08-03T08:58:32-04:00", + "custom_name": "", + "is_favorite": false, + "custom_executable": null + } + ] + } + ] + ], + "modified_date": "2022-08-03T12:58:00+00:00" + } + } +} \ No newline at end of file From 488110fe63314c78f50b5d912b9b526eaf58afa1 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 21:54:08 -0400 Subject: [PATCH 12/19] WIP Start implementing stable build info API --- scripts/build_linux.sh | 1 + scripts/build_linux_debug.sh | 1 + scripts/build_mac.sh | 1 + scripts/build_win.bat | 1 + scripts/build_win_debug.bat | 1 + source/modules/connection_manager.py | 2 +- source/threads/scraper.py | 23 +++++++++++-------- .../settings_window/blender_builds_tab.py | 1 + 8 files changed, 21 insertions(+), 10 deletions(-) diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh index 79c0d5e..f8747d7 100644 --- a/scripts/build_linux.sh +++ b/scripts/build_linux.sh @@ -16,5 +16,6 @@ PYTHONOPTIMIZE=2 pyinstaller \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ --add-data="source/resources/api/blender_launcher_api.json;files" \ + --add-data="source/resources/api/stable_builds_api.json;files" \ --distpath="./dist/release" \ source/main.py diff --git a/scripts/build_linux_debug.sh b/scripts/build_linux_debug.sh index 0a5ca95..42c8876 100644 --- a/scripts/build_linux_debug.sh +++ b/scripts/build_linux_debug.sh @@ -17,5 +17,6 @@ PYTHONOPTIMIZE=2 pyinstaller \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ --add-data="source/resources/api/blender_launcher_api.json;files" \ + --add-data="source/resources/api/stable_builds_api.json;files" \ --distpath="./dist/debug" \ source/main.py diff --git a/scripts/build_mac.sh b/scripts/build_mac.sh index 3a4e43a..1b817a2 100644 --- a/scripts/build_mac.sh +++ b/scripts/build_mac.sh @@ -14,6 +14,7 @@ PYTHONOPTIMIZE=2 pyinstaller \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ --add-data="source/resources/api/blender_launcher_api.json;files" \ + --add-data="source/resources/api/stable_builds_api.json;files" \ --distpath="./dist/release" \ source/main.py diff --git a/scripts/build_win.bat b/scripts/build_win.bat index c8798da..f678537 100644 --- a/scripts/build_win.bat +++ b/scripts/build_win.bat @@ -22,5 +22,6 @@ python -OO -m PyInstaller ^ --add-binary="source\resources\icons\bl\bl_file.ico;files" ^ --add-binary="source\resources\certificates\custom.pem;files" ^ --add-data="source\resources\api\blender_launcher_api.json;files" ^ +--add-data="source\resources\api\stable_builds_api.json;files" ^ --distpath="./dist/release" ^ source\main.py diff --git a/scripts/build_win_debug.bat b/scripts/build_win_debug.bat index fc03906..c51881e 100644 --- a/scripts/build_win_debug.bat +++ b/scripts/build_win_debug.bat @@ -22,5 +22,6 @@ python -OO -m PyInstaller ^ --add-binary="source\resources\icons\bl\bl_file.ico;files" ^ --add-binary="source\resources\certificates\custom.pem;files" ^ --add-data="source\resources\api\blender_launcher_api.json;files" ^ +--add-data="source\resources\api\stable_builds_api.json;files" ^ --distpath="./dist/debug" ^ source\main.py diff --git a/source/modules/connection_manager.py b/source/modules/connection_manager.py index a446c19..c2a717c 100644 --- a/source/modules/connection_manager.py +++ b/source/modules/connection_manager.py @@ -51,7 +51,7 @@ def __init__(self, version: Version, proxy_type=None) -> None: self.manager: REQUEST_MANAGER | None = None # Basic Headers - agent = f"Blender-Launcher-v2/v.{self.version!s}/{get_platform_full()}/UserID-{get_user_id()}" + agent = f"BL-v2/v.{self.version!s}/{get_platform_full()}/UserID-{get_user_id()}" self._headers = {"user-agent": agent} logger.info(f"Connection Manager Header: {agent}") # Get custom certificates file path diff --git a/source/threads/scraper.py b/source/threads/scraper.py index f533df5..e5fd67a 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -2,6 +2,7 @@ import base64 import contextlib +from importlib.metadata import files import json import logging import re @@ -107,18 +108,20 @@ def get_tag( return tag -def get_bl_api_data(connection_manager: ConnectionManager) -> str | None: - url = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/contents/source/resources/api/blender_launcher_api.json" +def get_api_data(connection_manager: ConnectionManager, file: str) -> str | None: + base_fmt = "https://api.github.com/repos/Victor-IX/Blender-Launcher-V2/contents/source/resources/api/{}.json" + url = base_fmt.format(file) + logger.debug(f"Start fetching API data from: {url}") r = connection_manager.request("GET", url) if r is None: - logger.error("Failed to fetch data from the URL.") + logger.error(f"Failed to fetch data from: {url}.") return None try: data = json.loads(r.data) except json.JSONDecodeError as e: - logger.error(f"Failed to parse blender launcher API JSON data: {e}") + logger.error(f"Failed to parse {file} API JSON data: {e}") return None file_content = data["content"] @@ -128,13 +131,13 @@ def get_bl_api_data(connection_manager: ConnectionManager) -> str | None: try: file_content = base64.b64decode(file_content).decode("utf-8") json_data = json.loads(file_content) - logger.info("Blender Launcher API data have been loaded successfully") + logger.info(f"API data form {file} have been loaded successfully") return json_data except (base64.binascii.Error, json.JSONDecodeError) as e: logger.error(f"Failed to decode or parse JSON data: {e}") return None else: - logger.error("Failed to load Blender Launcher API data or unsupported encoding.") + logger.error(f"Failed to load API data from {file} or unsupported encoding.") return None @@ -182,7 +185,7 @@ def __init__(self, parent, man: ConnectionManager): self.scrape_automated = get_scrape_automated_builds() def run(self): - self.get_bl_api_data_manager() + self.get_api_data_manager() self.get_download_links() self.get_release_tag_manager() @@ -194,9 +197,11 @@ def get_release_tag_manager(self): self.new_bl_version.emit(latest_tag) self.manager.manager.clear() - def get_bl_api_data_manager(self): + def get_api_data_manager(self): assert self.manager.manager is not None - bl_api_data = get_bl_api_data(self.manager) + + bl_api_data = get_api_data(self.manager, "blender_launcher_api") + blender_version_api_data = get_api_data(self.manager, "stable_builds_api") if bl_api_data is not None: update_local_api_files(bl_api_data) diff --git a/source/widgets/settings_window/blender_builds_tab.py b/source/widgets/settings_window/blender_builds_tab.py index 6c86979..5b837c7 100644 --- a/source/widgets/settings_window/blender_builds_tab.py +++ b/source/widgets/settings_window/blender_builds_tab.py @@ -60,6 +60,7 @@ def __init__(self, parent=None): # Minimum stable blender download version (this is mainly for cleanliness and speed) self.MinStableBlenderVer = QComboBox() + # TODO: Add a "custom" key with a new section for custom min version input (useful if you want to fetch very old versions) keys = list(dropdown_blender_version().keys()) self.MinStableBlenderVer.addItems(keys) self.MinStableBlenderVer.setCurrentText(get_minimum_blender_stable_version()) From 1f1b4e64384bc71a6af17ce1083f338cfc5f3e4c Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 22:19:27 -0400 Subject: [PATCH 13/19] Make version API file platform based --- .../{stable_builds_api.json => stable_builds_api_windows.json} | 0 source/threads/scraper.py | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) rename source/resources/api/{stable_builds_api.json => stable_builds_api_windows.json} (100%) diff --git a/source/resources/api/stable_builds_api.json b/source/resources/api/stable_builds_api_windows.json similarity index 100% rename from source/resources/api/stable_builds_api.json rename to source/resources/api/stable_builds_api_windows.json diff --git a/source/threads/scraper.py b/source/threads/scraper.py index e5fd67a..b807122 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -2,7 +2,6 @@ import base64 import contextlib -from importlib.metadata import files import json import logging import re @@ -201,7 +200,7 @@ def get_api_data_manager(self): assert self.manager.manager is not None bl_api_data = get_api_data(self.manager, "blender_launcher_api") - blender_version_api_data = get_api_data(self.manager, "stable_builds_api") + blender_version_api_data = get_api_data(self.manager, f"stable_builds_api_{get_platform().lower()}") if bl_api_data is not None: update_local_api_files(bl_api_data) From 29c529af7e693401a71c313f278e1d2862407c5d Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 22:44:14 -0400 Subject: [PATCH 14/19] Update cache file --- source/modules/bl_api_manager.py | 48 ++++++++++++++++++++++++++------ source/threads/scraper.py | 11 ++++++-- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index 1da1a30..1a59fe7 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -1,15 +1,18 @@ +import os import json import logging from functools import lru_cache from pathlib import Path -from modules._platform import get_config_path, get_cwd +from modules._platform import get_config_path, get_cwd, get_platform logger = logging.getLogger() config_path = Path(get_config_path()) -api_path = config_path / "Blender Launcher API.json" -internal_api_path = get_cwd() / "source/resources/api/blender_launcher_api.json" +bl_api_path = config_path / "Blender Launcher API.json" +stable_build_path = config_path / "stable_builds.json" +internal_bl_api_path = get_cwd() / "source/resources/api/blender_launcher_api.json" +internal_stable_build_path = get_cwd() / f"source/resources/api/stable_builds_api_{get_platform().lower()}.json" def update_local_api_files(data): @@ -18,18 +21,45 @@ def update_local_api_files(data): logger.info(f"Created config directory in {config_path}") try: - with open(api_path, "w") as f: + with open(bl_api_path, "w") as f: json.dump(data, f, indent=4) - logger.info(f"Updated API file in {api_path}") + logger.info(f"Updated API file in {bl_api_path}") read_bl_api.cache_clear() except OSError as e: logger.error(f"Failed to write API file: {e}") + +def update_stable_builds_cache(data): + if not config_path.exists(): + config_path.mkdir(parents=True) + logger.info(f"Created config directory in {config_path}") + + if not os.path.isfile(stable_build_path): + try: + with open(stable_build_path, "w") as f: + json.dump(data, f, indent=4) + logger.info(f"Updated API file in {bl_api_path}") + read_bl_api.cache_clear() + except OSError as e: + logger.error(f"Failed to write API file: {e}") + else: + try: + with open(stable_build_path, "r") as f: + current_data = json.load(f) + current_data.update(data) + with open(stable_build_path, "w") as f: + json.dump(current_data, f, indent=4) + logger.info(f"Updated API file in {bl_api_path}") + read_bl_api.cache_clear() + except OSError as e: + logger.error(f"Failed to write API file: {e}") + + @lru_cache(maxsize=1) -def read_bl_api()-> dict: - api = api_path if api_path.exists() else internal_api_path - if api == internal_api_path: - logger.error(f"API file not found in {api_path}. Using internal API file.") +def read_bl_api() -> dict: + api = bl_api_path if bl_api_path.exists() else internal_bl_api_path + if api == internal_bl_api_path: + logger.error(f"API file not found in {bl_api_path}. Using internal API file.") with open(api) as f: return json.load(f) diff --git a/source/threads/scraper.py b/source/threads/scraper.py index b807122..e36cf9c 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -14,7 +14,12 @@ import distro from bs4 import BeautifulSoup, SoupStrainer from modules._platform import get_architecture, get_platform, reset_locale, set_locale, stable_cache_path -from modules.bl_api_manager import dropdown_blender_version, lts_blender_version, update_local_api_files +from modules.bl_api_manager import ( + dropdown_blender_version, + lts_blender_version, + update_local_api_files, + update_stable_builds_cache, +) from modules.build_info import BuildInfo, parse_blender_ver from modules.scraper_cache import StableCache from modules.settings import ( @@ -200,12 +205,14 @@ def get_api_data_manager(self): assert self.manager.manager is not None bl_api_data = get_api_data(self.manager, "blender_launcher_api") - blender_version_api_data = get_api_data(self.manager, f"stable_builds_api_{get_platform().lower()}") + blender_version_api_data = get_api_data(self.manager, f"stable_builds_api_{self.platform.lower()}") if bl_api_data is not None: update_local_api_files(bl_api_data) lts_blender_version() dropdown_blender_version() + if blender_version_api_data is not None: + update_stable_builds_cache(blender_version_api_data) self.manager.manager.clear() From abc689e75077ac44462de17dd2d000ae7a3bf9d2 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 22:45:53 -0400 Subject: [PATCH 15/19] add platform specific build info api files --- scripts/build_linux.sh | 2 +- scripts/build_linux_debug.sh | 2 +- scripts/build_win.bat | 2 +- scripts/build_win_debug.bat | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh index f8747d7..9238cb7 100644 --- a/scripts/build_linux.sh +++ b/scripts/build_linux.sh @@ -16,6 +16,6 @@ PYTHONOPTIMIZE=2 pyinstaller \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ --add-data="source/resources/api/blender_launcher_api.json;files" \ - --add-data="source/resources/api/stable_builds_api.json;files" \ + --add-data="source/resources/api/stable_builds_api_linux.json;files" \ --distpath="./dist/release" \ source/main.py diff --git a/scripts/build_linux_debug.sh b/scripts/build_linux_debug.sh index 42c8876..5cbd67b 100644 --- a/scripts/build_linux_debug.sh +++ b/scripts/build_linux_debug.sh @@ -17,6 +17,6 @@ PYTHONOPTIMIZE=2 pyinstaller \ --name="Blender Launcher" \ --add-binary="source/resources/certificates/custom.pem:files" \ --add-data="source/resources/api/blender_launcher_api.json;files" \ - --add-data="source/resources/api/stable_builds_api.json;files" \ + --add-data="source/resources/api/stable_builds_api_linux.json;files" \ --distpath="./dist/debug" \ source/main.py diff --git a/scripts/build_win.bat b/scripts/build_win.bat index f678537..7966916 100644 --- a/scripts/build_win.bat +++ b/scripts/build_win.bat @@ -22,6 +22,6 @@ python -OO -m PyInstaller ^ --add-binary="source\resources\icons\bl\bl_file.ico;files" ^ --add-binary="source\resources\certificates\custom.pem;files" ^ --add-data="source\resources\api\blender_launcher_api.json;files" ^ ---add-data="source\resources\api\stable_builds_api.json;files" ^ +--add-data="source\resources\api\stable_builds_api_windows.json;files" ^ --distpath="./dist/release" ^ source\main.py diff --git a/scripts/build_win_debug.bat b/scripts/build_win_debug.bat index c51881e..10e4d1b 100644 --- a/scripts/build_win_debug.bat +++ b/scripts/build_win_debug.bat @@ -22,6 +22,6 @@ python -OO -m PyInstaller ^ --add-binary="source\resources\icons\bl\bl_file.ico;files" ^ --add-binary="source\resources\certificates\custom.pem;files" ^ --add-data="source\resources\api\blender_launcher_api.json;files" ^ ---add-data="source\resources\api\stable_builds_api.json;files" ^ +--add-data="source\resources\api\stable_builds_api_windows.json;files" ^ --distpath="./dist/debug" ^ source\main.py From 8aaf35e159508cec33b8a36eee7e87146f5dc623 Mon Sep 17 00:00:00 2001 From: Victor Date: Tue, 3 Sep 2024 23:03:16 -0400 Subject: [PATCH 16/19] Improve handling for missing API file --- source/modules/bl_api_manager.py | 16 ++++++++++++---- source/threads/scraper.py | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index 1a59fe7..5ec156a 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -1,4 +1,3 @@ -import os import json import logging from functools import lru_cache @@ -34,12 +33,22 @@ def update_stable_builds_cache(data): config_path.mkdir(parents=True) logger.info(f"Created config directory in {config_path}") - if not os.path.isfile(stable_build_path): + # If data no data from the API have been retrieve, read from the internal API file + if data is None and internal_stable_build_path.is_file(): + try: + with open(stable_build_path, "r") as f: + data = json.load(f) + except OSError as e: + logger.error(f"Failed to write API file: {e}") + else: + logger.error(f"Unable to retrieve online build API data and no internal API file found.") + return + + if not stable_build_path.is_file(): try: with open(stable_build_path, "w") as f: json.dump(data, f, indent=4) logger.info(f"Updated API file in {bl_api_path}") - read_bl_api.cache_clear() except OSError as e: logger.error(f"Failed to write API file: {e}") else: @@ -50,7 +59,6 @@ def update_stable_builds_cache(data): with open(stable_build_path, "w") as f: json.dump(current_data, f, indent=4) logger.info(f"Updated API file in {bl_api_path}") - read_bl_api.cache_clear() except OSError as e: logger.error(f"Failed to write API file: {e}") diff --git a/source/threads/scraper.py b/source/threads/scraper.py index e36cf9c..e187d03 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -211,8 +211,8 @@ def get_api_data_manager(self): update_local_api_files(bl_api_data) lts_blender_version() dropdown_blender_version() - if blender_version_api_data is not None: - update_stable_builds_cache(blender_version_api_data) + + update_stable_builds_cache(blender_version_api_data) self.manager.manager.clear() From f2bcaefb8eaa16aeddd951d5cc0c8a84ee224778 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 4 Sep 2024 21:02:30 -0400 Subject: [PATCH 17/19] Add if check if API file is not present --- source/threads/scraper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/threads/scraper.py b/source/threads/scraper.py index e187d03..1f2ca37 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -128,7 +128,7 @@ def get_api_data(connection_manager: ConnectionManager, file: str) -> str | None logger.error(f"Failed to parse {file} API JSON data: {e}") return None - file_content = data["content"] + file_content = data["content"] if "content" in data else None file_content_encoding = data.get("encoding") if file_content_encoding == "base64" and file_content: From 254ecce364b74dd0ef5dbe301851336d00458d8d Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 4 Sep 2024 22:16:26 -0400 Subject: [PATCH 18/19] Fix some Bug --- source/modules/bl_api_manager.py | 7 +++---- source/modules/connection_manager.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/source/modules/bl_api_manager.py b/source/modules/bl_api_manager.py index 5ec156a..af2d331 100644 --- a/source/modules/bl_api_manager.py +++ b/source/modules/bl_api_manager.py @@ -40,15 +40,14 @@ def update_stable_builds_cache(data): data = json.load(f) except OSError as e: logger.error(f"Failed to write API file: {e}") - else: + if data is None: logger.error(f"Unable to retrieve online build API data and no internal API file found.") return - if not stable_build_path.is_file(): try: with open(stable_build_path, "w") as f: json.dump(data, f, indent=4) - logger.info(f"Updated API file in {bl_api_path}") + logger.info(f"Create Build Cache file in {stable_build_path}") except OSError as e: logger.error(f"Failed to write API file: {e}") else: @@ -58,7 +57,7 @@ def update_stable_builds_cache(data): current_data.update(data) with open(stable_build_path, "w") as f: json.dump(current_data, f, indent=4) - logger.info(f"Updated API file in {bl_api_path}") + logger.info(f"Updated Build Cache file in {stable_build_path}") except OSError as e: logger.error(f"Failed to write API file: {e}") diff --git a/source/modules/connection_manager.py b/source/modules/connection_manager.py index c2a717c..ed8f780 100644 --- a/source/modules/connection_manager.py +++ b/source/modules/connection_manager.py @@ -51,7 +51,7 @@ def __init__(self, version: Version, proxy_type=None) -> None: self.manager: REQUEST_MANAGER | None = None # Basic Headers - agent = f"BL-v2/v.{self.version!s}/{get_platform_full()}/UserID-{get_user_id()}" + agent = f"BlenderLauncherV2/v.{self.version!s}/{get_platform_full()}/UserID-{get_user_id()}" self._headers = {"user-agent": agent} logger.info(f"Connection Manager Header: {agent}") # Get custom certificates file path From 2cbfb4bde2f33af96c0895e65679ea5d373cf9f3 Mon Sep 17 00:00:00 2001 From: Victor Date: Wed, 4 Sep 2024 22:35:15 -0400 Subject: [PATCH 19/19] Add Request counter --- source/modules/connection_manager.py | 12 ++++++++++++ source/threads/scraper.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/source/modules/connection_manager.py b/source/modules/connection_manager.py index ed8f780..152a37f 100644 --- a/source/modules/connection_manager.py +++ b/source/modules/connection_manager.py @@ -60,6 +60,8 @@ def __init__(self, version: Version, proxy_type=None) -> None: else: self.cacert = (get_cwd() / "source/resources/certificates/custom.pem").as_posix() + self.request_counter = 0 + def setup(self): if self.proxy_type == 0: # Use generic requests if get_use_custom_tls_certificates(): @@ -130,6 +132,16 @@ def setup(self): def request(self, _method, _url, fields=None, headers=None, **urlopen_kw): try: assert self.manager is not None + + """ + Counter for request. Not supposed to exceed 7 requests + 4 requests for Blender Builder + 1 requests for Blender Download + 3 requests for GitHub + """ + self.request_counter += 1 + logger.debug(f"Request Counter: {self.request_counter}") + return self.manager.request(_method, _url, fields, headers, **urlopen_kw) except Exception: self.error.emit() diff --git a/source/threads/scraper.py b/source/threads/scraper.py index 1f2ca37..6c80376 100644 --- a/source/threads/scraper.py +++ b/source/threads/scraper.py @@ -211,7 +211,7 @@ def get_api_data_manager(self): update_local_api_files(bl_api_data) lts_blender_version() dropdown_blender_version() - + update_stable_builds_cache(blender_version_api_data) self.manager.manager.clear()