mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
148 lines
No EOL
4.3 KiB
Python
148 lines
No EOL
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import requests
|
|
from os import environ
|
|
from functools import cached_property, lru_cache
|
|
from importlib.metadata import version as get_package_version, PackageNotFoundError
|
|
from subprocess import check_output, CalledProcessError, PIPE
|
|
|
|
from .errors import VersionNotFoundError
|
|
from .config import PACKAGE_NAME, GITHUB_REPOSITORY
|
|
from . import debug
|
|
|
|
# Default request timeout (seconds)
|
|
REQUEST_TIMEOUT = 5
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def get_pypi_version(package_name: str) -> str:
|
|
"""
|
|
Retrieves the latest version of a package from PyPI.
|
|
|
|
Raises:
|
|
VersionNotFoundError: If there is a network or parsing error.
|
|
"""
|
|
try:
|
|
response = requests.get(
|
|
f"https://pypi.org/pypi/{package_name}/json",
|
|
timeout=REQUEST_TIMEOUT
|
|
)
|
|
response.raise_for_status()
|
|
return response.json()["info"]["version"]
|
|
except requests.RequestException as e:
|
|
raise VersionNotFoundError(
|
|
f"Failed to get PyPI version for '{package_name}'"
|
|
) from e
|
|
|
|
|
|
@lru_cache(maxsize=1)
|
|
def get_github_version(repo: str) -> str:
|
|
"""
|
|
Retrieves the latest release version from a GitHub repository.
|
|
|
|
Raises:
|
|
VersionNotFoundError: If there is a network or parsing error.
|
|
"""
|
|
try:
|
|
response = requests.get(
|
|
f"https://api.github.com/repos/{repo}/releases/latest",
|
|
timeout=REQUEST_TIMEOUT
|
|
)
|
|
response.raise_for_status()
|
|
data = response.json()
|
|
if "tag_name" not in data:
|
|
raise VersionNotFoundError(f"No tag_name found in latest GitHub release for '{repo}'")
|
|
return data["tag_name"]
|
|
except requests.RequestException as e:
|
|
raise VersionNotFoundError(
|
|
f"Failed to get GitHub release version for '{repo}'"
|
|
) from e
|
|
|
|
|
|
def get_git_version() -> str | None:
|
|
"""Return latest Git tag if available, else None."""
|
|
try:
|
|
return check_output(
|
|
["git", "describe", "--tags", "--abbrev=0"],
|
|
text=True,
|
|
stderr=PIPE
|
|
).strip()
|
|
except CalledProcessError:
|
|
return None
|
|
|
|
|
|
class VersionUtils:
|
|
"""
|
|
Utility class for managing and comparing package versions of 'g4f'.
|
|
"""
|
|
|
|
@cached_property
|
|
def current_version(self) -> str:
|
|
"""
|
|
Returns the current installed version of g4f from:
|
|
- debug override
|
|
- package metadata
|
|
- environment variable (Docker)
|
|
- git tags
|
|
"""
|
|
if debug.version:
|
|
return debug.version
|
|
|
|
try:
|
|
return get_package_version(PACKAGE_NAME)
|
|
except PackageNotFoundError:
|
|
pass
|
|
|
|
version_env = environ.get("G4F_VERSION")
|
|
if version_env:
|
|
return version_env
|
|
|
|
git_version = get_git_version()
|
|
if git_version:
|
|
return git_version
|
|
|
|
return None
|
|
|
|
@property
|
|
def latest_version(self) -> str:
|
|
"""
|
|
Returns the latest available version of g4f.
|
|
If not installed via PyPI, falls back to GitHub releases.
|
|
"""
|
|
try:
|
|
get_package_version(PACKAGE_NAME)
|
|
except PackageNotFoundError:
|
|
return get_github_version(GITHUB_REPOSITORY)
|
|
return get_pypi_version(PACKAGE_NAME)
|
|
|
|
@cached_property
|
|
def latest_version_cached(self) -> str:
|
|
return self.latest_version
|
|
|
|
def check_version(self, silent: bool = False) -> bool:
|
|
"""
|
|
Checks if the current version is up-to-date.
|
|
Returns:
|
|
bool: True if current version is the latest, False otherwise.
|
|
"""
|
|
try:
|
|
current = self.current_version
|
|
latest = self.latest_version
|
|
up_to_date = current == latest
|
|
if not silent:
|
|
if up_to_date:
|
|
print(f"g4f is up-to-date (version {current}).")
|
|
else:
|
|
print(
|
|
f"New g4f version available: {latest} "
|
|
f"(current: {current}) | pip install -U g4f"
|
|
)
|
|
return up_to_date
|
|
except Exception as e:
|
|
if not silent:
|
|
print(f"Failed to check g4f version: {e}")
|
|
return True # Assume up-to-date if check fails
|
|
|
|
|
|
# Singleton instance
|
|
utils = VersionUtils() |