pythonlib: Add enable_cache, fixed font spacing, etc 0.3.9

- Enable bf cache with `enable_cache=True` #74
- Font spacing is now fixed per session #63
- Re-download (or raise error) when target install path is empty. Caused when the user cancels the download.
- Bumped minimum version to beta.15
This commit is contained in:
daijro 2024-11-11 22:11:43 -06:00
parent 476e119c4f
commit 3a33283cd2
5 changed files with 73 additions and 19 deletions

View file

@ -8,7 +8,7 @@ class CONSTRAINTS:
The minimum and maximum supported versions of the Camoufox browser.
"""
MIN_VERSION = 'beta.12'
MIN_VERSION = 'beta.15'
MAX_VERSION = '1'
@staticmethod

View file

@ -178,3 +178,11 @@ class VirtualDisplayNotSupported(VirtualDisplayError):
"""
...
class CamoufoxNotInstalled(FileNotFoundError):
"""
Raised when camoufox is not installed.
"""
...

View file

@ -21,7 +21,12 @@ from typing_extensions import TypeAlias
from yaml import CLoader, load
from .__version__ import CONSTRAINTS
from .exceptions import UnsupportedArchitecture, UnsupportedOS, UnsupportedVersion
from .exceptions import (
CamoufoxNotInstalled,
UnsupportedArchitecture,
UnsupportedOS,
UnsupportedVersion,
)
DownloadBuffer: TypeAlias = Union[BytesIO, tempfile._TemporaryFileWrapper, BufferedWriter]
@ -55,6 +60,13 @@ OS_ARCH_MATRIX: Dict[str, List[str]] = {
'lin': ['x86_64', 'arm64', 'i686'],
}
# The relative path to the camoufox executable
LAUNCH_FILE = {
'win': 'camoufox.exe',
'lin': 'camoufox-bin',
'mac': '../MacOS/camoufox',
}
def rprint(*a, **k):
click.secho(*a, **k, bold=True)
@ -102,7 +114,7 @@ class Version:
if not os.path.exists(version_path):
raise FileNotFoundError(
f"Version information not found at {version_path}. "
"You are likely using an unsupported version of Camoufox."
"Please run `camoufox fetch` to install."
)
with open(version_path, 'rb') as f:
version_data = orjson.loads(f.read())
@ -358,14 +370,16 @@ def camoufox_path(download_if_missing: bool = True) -> Path:
"""
Full path to the camoufox folder.
"""
if os.path.exists(INSTALL_DIR) and Version.from_path().is_supported():
return INSTALL_DIR
# Ensure the directory exists
if not os.path.exists(INSTALL_DIR):
# Ensure the directory exists and is not empty
if not os.path.exists(INSTALL_DIR) or not os.listdir(INSTALL_DIR):
if not download_if_missing:
raise FileNotFoundError(f"Camoufox executable not found at {INSTALL_DIR}")
# Camoufox exists and the the version is supported
elif os.path.exists(INSTALL_DIR) and Version.from_path().is_supported():
return INSTALL_DIR
# Ensure the version is supported
else:
if not download_if_missing:
@ -385,6 +399,19 @@ def get_path(file: str) -> str:
return str(camoufox_path() / file)
def launch_path() -> str:
"""
Get the path to the camoufox executable.
"""
launch_path = get_path(LAUNCH_FILE[OS_NAME])
if not os.path.exists(launch_path):
# Not installed error
raise CamoufoxNotInstalled(
f"Camoufox is not installed at {camoufox_path()}. Please run `camoufox fetch` to install."
)
return launch_path
def webdl(
url: str,
desc: Optional[str] = None,

View file

@ -4,7 +4,7 @@ from os import environ
from os.path import abspath
from pathlib import Path
from pprint import pprint
from random import randrange
from random import randint, randrange
from typing import Any, Dict, List, Literal, Optional, Tuple, Union, cast
import numpy as np
@ -29,19 +29,22 @@ from .exceptions import (
from .fingerprints import from_browserforge, generate_fingerprint
from .ip import Proxy, public_ip, valid_ipv4, valid_ipv6
from .locale import geoip_allowed, get_geolocation, handle_locales
from .pkgman import OS_NAME, get_path, installed_verstr
from .pkgman import OS_NAME, get_path, installed_verstr, launch_path
from .virtdisplay import VirtualDisplay
from .warnings import LeakWarning
from .xpi_dl import add_default_addons
LAUNCH_FILE = {
'win': 'camoufox.exe',
'lin': 'camoufox-bin',
'mac': '../MacOS/camoufox',
}
ListOrString: TypeAlias = Union[Tuple[str, ...], List[str], str]
# Camoufox preferences to cache previous pages and requests
CACHE_PREFS = {
'browser.sessionhistory.max_entries': 10,
'browser.sessionhistory.max_total_viewers': -1,
'browser.cache.memory.enable': True,
'browser.cache.disk_cache_ssl': True,
'browser.cache.disk.smart_size.enabled': True,
}
def get_env_vars(
config_map: Dict[str, str], user_agent_os: str
@ -354,9 +357,10 @@ def launch_options(
fingerprint: Optional[Fingerprint] = None,
ff_version: Optional[int] = None,
headless: Optional[bool] = None,
executable_path: Optional[str] = None,
executable_path: Optional[Union[str, Path]] = None,
firefox_user_prefs: Optional[Dict[str, Any]] = None,
proxy: Optional[Dict[str, str]] = None,
enable_cache: Optional[bool] = None,
args: Optional[List[str]] = None,
env: Optional[Dict[str, Union[str, float, bool]]] = None,
i_know_what_im_doing: Optional[bool] = None,
@ -413,13 +417,15 @@ def launch_options(
Whether to run the browser in headless mode. Defaults to False.
Note: If you are running linux, passing headless='virtual' to Camoufox & AsyncCamoufox
will use Xvfb.
executable_path (Optional[str]):
executable_path (Optional[Union[str, Path]]):
Custom Camoufox browser executable path.
firefox_user_prefs (Optional[Dict[str, Any]]):
Firefox user preferences to set.
proxy (Optional[Dict[str, str]]):
Proxy to use for the browser.
Note: If geoip is True, a request will be sent through this proxy to find the target IP.
enable_cache (Optional[bool]):
Cache previous pages, requests, etc (uses more memory).
args (Optional[List[str]]):
Arguments to pass to the browser.
env (Optional[Dict[str, Union[str, float, bool]]]):
@ -449,6 +455,7 @@ def launch_options(
if env is None:
env = cast(Dict[str, Union[str, float, bool]], environ)
if isinstance(executable_path, str):
# Convert executable path to a Path object
executable_path = Path(abspath(executable_path))
# Handle virtual display
@ -504,6 +511,8 @@ def launch_options(
if fonts:
config['fonts'] = fonts
update_fonts(config, target_os)
# Set a fixed font spacing seed
set_into(config, 'fonts:spacing_seed', randint(0, 2147483647)) # nosec
# Set geolocation
if geoip:
@ -563,6 +572,10 @@ def launch_options(
LeakWarning.warn('allow_webgl', i_know_what_im_doing)
firefox_user_prefs['webgl.disabled'] = False
# Cache previous pages, requests, etc (uses more memory)
if enable_cache:
firefox_user_prefs.update(CACHE_PREFS)
# Load the addons
threaded_try_load_addons(get_debug_port(args), addons)
@ -571,8 +584,14 @@ def launch_options(
**get_env_vars(config, target_os),
**env,
}
# Prepare the executable path
if executable_path:
executable_path = str(executable_path)
else:
executable_path = launch_path()
return {
"executable_path": executable_path or get_path(LAUNCH_FILE[OS_NAME]),
"executable_path": executable_path,
"args": args,
"env": env_vars,
"firefox_user_prefs": firefox_user_prefs,

View file

@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "camoufox"
version = "0.3.8"
version = "0.3.9"
description = "Wrapper around Playwright to help launch Camoufox"
authors = ["daijro <daijro.dev@gmail.com>"]
license = "MIT"