Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic API Implementation #136

Merged
merged 22 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scripts/build_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ 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" \
--add-data="source/resources/api/stable_builds_api_linux.json;files" \
--distpath="./dist/release" \
source/main.py
2 changes: 2 additions & 0 deletions scripts/build_linux_debug.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ 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" \
--add-data="source/resources/api/stable_builds_api_linux.json;files" \
--distpath="./dist/debug" \
source/main.py
2 changes: 2 additions & 0 deletions scripts/build_mac.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ 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" \
--add-data="source/resources/api/stable_builds_api.json;files" \
--distpath="./dist/release" \
source/main.py

Expand Down
4 changes: 3 additions & 1 deletion scripts/build_win.bat
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ 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" ^
--add-data="source\resources\api\stable_builds_api_windows.json;files" ^
--distpath="./dist/release" ^
source\main.py
4 changes: 3 additions & 1 deletion scripts/build_win_debug.bat
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ 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" ^
--add-data="source\resources\api\stable_builds_api_windows.json;files" ^
--distpath="./dist/debug" ^
source\main.py
93 changes: 93 additions & 0 deletions source/modules/bl_api_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import json
import logging
from functools import lru_cache
from pathlib import Path

from modules._platform import get_config_path, get_cwd, get_platform

logger = logging.getLogger()

config_path = Path(get_config_path())
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):
if not config_path.exists():
config_path.mkdir(parents=True)
logger.info(f"Created config directory in {config_path}")

try:
with open(bl_api_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}")


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 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}")
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"Create Build Cache file in {stable_build_path}")
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 Build Cache file in {stable_build_path}")
except OSError as e:
logger.error(f"Failed to write API file: {e}")


@lru_cache(maxsize=1)
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)


def read_blender_version_list() -> dict[str, str]:
return read_bl_api().get("blender_versions", {})


def lts_blender_version():
return tuple(version for version, lts in read_blender_version_list().items() if lts == "LTS")


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())}
3 changes: 2 additions & 1 deletion source/modules/build_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
14 changes: 13 additions & 1 deletion source/modules/connection_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"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
Expand All @@ -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():
Expand Down Expand Up @@ -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()
Expand Down
40 changes: 15 additions & 25 deletions source/modules/settings.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from __future__ import annotations
import contextlib
import os
import shutil
import sys
import uuid
from datetime import datetime, timezone
from functools import cache
from pathlib import Path

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
Expand Down Expand Up @@ -63,22 +64,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():
Expand Down Expand Up @@ -445,17 +430,22 @@ 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")

if value is not None and "." in value:
return blender_minimum_versions.get(value, 7)
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"

return get_settings().value("minimum_blender_stable_version", defaultValue=7, type=int)
# 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


def set_minimum_blender_stable_version(blender_minimum_version):
get_settings().setValue("minimum_blender_stable_version", blender_minimum_versions[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:
Expand Down
3 changes: 2 additions & 1 deletion source/resources/api/blender_launcher_api.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"api_file_version": "1.0",
"blender_versions": {
"4.2": "LTS",
"4.1": "non-LTS",
Expand All @@ -20,4 +21,4 @@
"2.80": "non-LTS",
"2.79": "non-LTS"
}
}
}
Loading