pythonlib: Cleanup & bump to 0.4.6

- `camoufox test` will no longer highlight the cursor by default
- Fixed launch_options blocking async
- WebGL database cleanup & added ability to query all possible vendor/renderer pairs
This commit is contained in:
daijro 2024-12-04 19:35:54 -06:00
parent 31963aa83b
commit 4c52518dd2
7 changed files with 54 additions and 23 deletions

View file

@ -114,7 +114,7 @@ def test(url: Optional[str] = None) -> None:
"""
from .sync_api import Camoufox
with Camoufox(headless=False, env=environ) as browser:
with Camoufox(headless=False, env=environ, config={'showcursor': False}) as browser:
page = browser.new_page()
if url:
page.goto(url)

View file

@ -1,3 +1,5 @@
import asyncio
from functools import partial
from typing import Any, Dict, Optional, Union, overload
from playwright.async_api import (
@ -82,13 +84,17 @@ async def AsyncNewBrowser(
else:
virtual_display = None
opt = from_options or launch_options(headless=headless, debug=debug, **kwargs)
if not from_options:
from_options = await asyncio.get_event_loop().run_in_executor(
None,
partial(launch_options, headless=headless, debug=debug, **kwargs),
)
# Persistent context
if persistent_context:
context = await playwright.firefox.launch_persistent_context(**opt)
context = await playwright.firefox.launch_persistent_context(**from_options)
return await async_attach_vd(context, virtual_display)
# Browser
browser = await playwright.firefox.launch(**opt)
browser = await playwright.firefox.launch(**from_options)
return await async_attach_vd(browser, virtual_display)

View file

@ -55,16 +55,16 @@ LOCAL_DATA: Path = Path(os.path.abspath(__file__)).parent
# The supported architectures for each OS
OS_ARCH_MATRIX: Dict[str, List[str]] = {
'mac': ['x86_64', 'arm64'],
'win': ['x86_64', 'i686'],
'mac': ['x86_64', 'arm64'],
'lin': ['x86_64', 'arm64', 'i686'],
}
# The relative path to the camoufox executable
LAUNCH_FILE = {
'win': 'camoufox.exe',
'lin': 'camoufox-bin',
'mac': '../MacOS/camoufox',
'lin': 'camoufox-bin',
}

View file

@ -82,13 +82,14 @@ def NewBrowser(
else:
virtual_display = None
opt = from_options or launch_options(headless=headless, debug=debug, **kwargs)
if not from_options:
from_options = launch_options(headless=headless, debug=debug, **kwargs)
# Persistent context
if persistent_context:
context = playwright.firefox.launch_persistent_context(**opt)
context = playwright.firefox.launch_persistent_context(**from_options)
return sync_attach_vd(context, virtual_display)
# Browser
browser = playwright.firefox.launch(**opt)
browser = playwright.firefox.launch(**from_options)
return sync_attach_vd(browser, virtual_display)

View file

@ -1,10 +1,15 @@
import sqlite3
from pathlib import Path
from typing import Dict, Optional
from typing import Dict, List, Optional, Tuple
import numpy as np
import orjson
from camoufox.pkgman import OS_ARCH_MATRIX
# Get database path relative to this file
DB_PATH = Path(__file__).parent / 'webgl_data.db'
def sample_webgl(
os: str, vendor: Optional[str] = None, renderer: Optional[str] = None
@ -24,23 +29,19 @@ def sample_webgl(
Raises:
ValueError: If invalid OS provided or no data found for OS/vendor/renderer
"""
# Map OS to probability column
os_map = {'win': 'windows', 'mac': 'macos', 'lin': 'linux'}
if os not in os_map:
raise ValueError(f'Invalid OS: {os}. Must be one of: {", ".join(os_map)}')
os = os_map[os]
# Get database path relative to this file
db_path = Path(__file__).parent / 'webgl_data.db'
# Check that the OS is valid (avoid SQL injection)
if os not in OS_ARCH_MATRIX:
raise ValueError(f'Invalid OS: {os}. Must be one of: win, mac, lin')
# Connect to database
conn = sqlite3.connect(db_path)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
if vendor and renderer:
# Get specific vendor/renderer pair and verify it exists for this OS
cursor.execute(
f'SELECT vendor, renderer, data, {os} FROM webgl_fingerprints WHERE vendor = ? AND renderer = ?',
f'SELECT vendor, renderer, data, {os} FROM webgl_fingerprints ' # nosec
'WHERE vendor = ? AND renderer = ?',
(vendor, renderer),
)
result = cursor.fetchone()
@ -51,7 +52,7 @@ def sample_webgl(
if result[3] <= 0: # Check OS-specific probability
# Get a list of possible (vendor, renderer) pairs for this OS
cursor.execute(
f'SELECT DISTINCT vendor, renderer FROM webgl_fingerprints WHERE {os} > 0'
f'SELECT DISTINCT vendor, renderer FROM webgl_fingerprints WHERE {os} > 0' # nosec
)
possible_pairs = cursor.fetchall()
raise ValueError(
@ -63,7 +64,9 @@ def sample_webgl(
return orjson.loads(result[2])
# Get all vendor/renderer pairs and their probabilities for this OS
cursor.execute(f'SELECT vendor, renderer, data, {os} FROM webgl_fingerprints WHERE {os} > 0')
cursor.execute(
f'SELECT vendor, renderer, data, {os} FROM webgl_fingerprints WHERE {os} > 0' # nosec
)
results = cursor.fetchall()
conn.close()
@ -82,3 +85,24 @@ def sample_webgl(
# Parse the JSON data string
return orjson.loads(data_strs[idx])
def get_possible_pairs() -> Dict[str, List[Tuple[str, str]]]:
"""
Get all possible (vendor, renderer) pairs for all OS, where the probability is greater than 0.
"""
# Connect to database
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# Get all vendor/renderer pairs for each OS where probability > 0
result: Dict[str, List[Tuple[str, str]]] = {}
for os_type in OS_ARCH_MATRIX:
cursor.execute(
'SELECT DISTINCT vendor, renderer FROM webgl_fingerprints '
f'WHERE {os_type} > 0 ORDER BY {os_type} DESC', # nosec
)
result[os_type] = cursor.fetchall()
conn.close()
return result

View file

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