Skip to content

Commit

Permalink
fix: maintain previous py310 requirement (#310)
Browse files Browse the repository at this point in the history
* umu_consts: add enum for http method

* umu_util: add hashlib.file_digest

* umu_runtime: use new enum and hashlib.file_digest

* umu_proton: use new enum and hashlib.file_digest

* workflows: test against py310 as minimum

* workflows: fix e2e config test
  • Loading branch information
R1kaB3rN authored Dec 14, 2024
1 parent 9ad889e commit 6189d0d
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 20 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
shellcheck tests/*.sh
- name: Setup venv
run: |
uv venv --python 3.11
uv venv --python 3.10
- name: Test steamrt install
run: |
source .venv/bin/activate
Expand Down Expand Up @@ -62,6 +62,7 @@ jobs:
rm -rf "$HOME/.local/share/umu" "$HOME/.local/share/Steam/compatibilitytools.d"
- name: Test configuration file
run: |
uv venv --python 3.11
source .venv/bin/activate
sh tests/test_config.sh
rm -rf "$HOME/.local/share/umu" "$HOME/Games/umu" "$HOME/.local/share/Steam/compatibilitytools.d" "$HOME/.cache/umu"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
build:
strategy:
matrix:
version: ["3.11"]
version: ["3.10"]

runs-on: ubuntu-latest

Expand All @@ -28,10 +28,10 @@ jobs:
python3 -m pip install --upgrade pip uv mypy
- name: Setup venv
run: |
uv venv --python 3.11
uv venv --python 3.10
source .venv/bin/activate
uv pip install -r requirements.in
- name: Check types with mypy
run: |
source .venv/bin/activate
mypy --python-version 3.11 .
mypy .
2 changes: 1 addition & 1 deletion .github/workflows/umu-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
matrix:
# tomllib requires Python 3.11
# Ubuntu latest (Jammy) provides Python 3.10
version: ["3.11", "3.12", "3.13"]
version: ["3.10", "3.11", "3.12", "3.13"]

runs-on: ubuntu-latest

Expand Down
26 changes: 26 additions & 0 deletions umu/umu_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@
from pathlib import Path


# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023
# Python Software Foundation;
# Source: https://raw.githubusercontent.com/python/cpython/refs/heads/3.11/Lib/http/__init__.py
# License: https://raw.githubusercontent.com/python/cpython/refs/heads/3.11/LICENSE
class HTTPMethod(Enum):
"""HTTP methods and descriptions.
Methods from the following RFCs are all observed:
* RFF 9110: HTTP Semantics, obsoletes 7231, which obsoleted 2616
* RFC 5789: PATCH Method for HTTP
"""

CONNECT = "CONNECT"
DELETE = "DELETE"
GET = "GET"
HEAD = "HEAD"
OPTIONS = "OPTIONS"
PATCH = "PATCH"
POST = "POST"
PUT = "PUT"
TRACE = "TRACE"


class GamescopeAtom(Enum):
"""Represent Gamescope-specific X11 atom names."""

Expand Down
24 changes: 17 additions & 7 deletions umu/umu_proton.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from concurrent.futures import Future, ThreadPoolExecutor
from hashlib import file_digest, sha512
from http import HTTPMethod, HTTPStatus
from hashlib import sha512
from http import HTTPStatus
from pathlib import Path
from re import split as resplit
from shutil import move, rmtree
Expand All @@ -14,9 +14,14 @@
from urllib3.poolmanager import PoolManager
from urllib3.response import BaseHTTPResponse

from umu.umu_consts import STEAM_COMPAT, UMU_CACHE, UMU_LOCAL
from umu.umu_consts import STEAM_COMPAT, UMU_CACHE, UMU_LOCAL, HTTPMethod
from umu.umu_log import log
from umu.umu_util import extract_tarfile, run_zenity, write_file_chunks
from umu.umu_util import (
extract_tarfile,
file_digest,
run_zenity,
write_file_chunks,
)

SessionPools = tuple[ThreadPoolExecutor, PoolManager]

Expand Down Expand Up @@ -95,7 +100,9 @@ def _fetch_releases(
if os.environ.get("PROTONPATH") == "GE-Proton":
repo = "/repos/GloriousEggroll/proton-ge-custom/releases/latest"

resp = http_pool.request(HTTPMethod.GET, f"{url}{repo}", headers=headers)
resp = http_pool.request(
HTTPMethod.GET.value, f"{url}{repo}", headers=headers
)
if resp.status != HTTPStatus.OK:
return ()

Expand Down Expand Up @@ -159,7 +166,7 @@ def _fetch_proton(
# See https://github.com/astral-sh/ruff/issues/7918
log.info("Downloading %s...", proton_hash)

resp = http_pool.request(HTTPMethod.GET, proton_hash_url)
resp = http_pool.request(HTTPMethod.GET.value, proton_hash_url)
if resp.status != HTTPStatus.OK:
err: str = (
f"Unable to download {proton_hash}\n"
Expand Down Expand Up @@ -208,7 +215,10 @@ def _fetch_proton(
log.info("Downloading %s...", tarball)

resp = http_pool.request(
HTTPMethod.GET, tar_url, preload_content=False, headers=headers
HTTPMethod.GET.value,
tar_url,
preload_content=False,
headers=headers,
)

# Bail out for unexpected status codes
Expand Down
17 changes: 9 additions & 8 deletions umu/umu_runtime.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import os
from collections.abc import Callable
from concurrent.futures import Future, ThreadPoolExecutor
from hashlib import file_digest, sha256
from hashlib import sha256

try:
from importlib.resources.abc import Traversable
except ModuleNotFoundError:
from importlib.abc import Traversable

from http import HTTPMethod, HTTPStatus
from http import HTTPStatus
from pathlib import Path
from secrets import token_urlsafe
from shutil import move, rmtree
Expand All @@ -21,10 +21,11 @@
from urllib3.poolmanager import PoolManager
from urllib3.response import BaseHTTPResponse

from umu.umu_consts import UMU_CACHE, UMU_LOCAL
from umu.umu_consts import UMU_CACHE, UMU_LOCAL, HTTPMethod
from umu.umu_log import log
from umu.umu_util import (
extract_tarfile,
file_digest,
has_umu_setup,
run_zenity,
write_file_chunks,
Expand Down Expand Up @@ -139,7 +140,7 @@ def _install_umu(

# Get the digest for the runtime archive
resp = http_pool.request(
HTTPMethod.GET, f"{host}{endpoint}/SHA256SUMS{token}"
HTTPMethod.GET.value, f"{host}{endpoint}/SHA256SUMS{token}"
)
if resp.status != HTTPStatus.OK:
err: str = (
Expand All @@ -155,7 +156,7 @@ def _install_umu(
# Get BUILD_ID.txt. We'll use the value to identify the file when cached.
# This will guarantee we'll be picking up the correct file when resuming
resp = http_pool.request(
HTTPMethod.GET, f"{host}{endpoint}/BUILD_ID.txt{token}"
HTTPMethod.GET.value, f"{host}{endpoint}/BUILD_ID.txt{token}"
)
if resp.status != HTTPStatus.OK:
err: str = (
Expand Down Expand Up @@ -185,7 +186,7 @@ def _install_umu(
log.info("Downloading %s (latest), please wait...", variant)

resp = http_pool.request(
HTTPMethod.GET,
HTTPMethod.GET.value,
f"{host}{endpoint}/{archive}{token}",
preload_content=False,
headers=headers,
Expand Down Expand Up @@ -401,7 +402,7 @@ def _update_umu(
f"{host}{endpoint}/SteamLinuxRuntime_{codename}.VERSIONS.txt{token}"
)
log.debug("Sending request to '%s' for 'VERSIONS.txt'...", url)
resp = http_pool.request(HTTPMethod.GET, url)
resp = http_pool.request(HTTPMethod.GET.value, url)
if resp.status != HTTPStatus.OK:
log.error(
"%s returned the status: %s", resp.getheader("Host"), resp.status
Expand Down Expand Up @@ -539,7 +540,7 @@ def _restore_umu_platformid(

# Make the request to the VERSIONS.txt endpoint. It's fine to hit the
# cache for this endpoint, as it differs to the latest-beta endpoint
resp = http_pool.request(HTTPMethod.GET, f"{host}{url}{versions}")
resp = http_pool.request(HTTPMethod.GET.value, f"{host}{url}{versions}")
if resp.status != HTTPStatus.OK:
log.error(
"%s returned the status: %s",
Expand Down
49 changes: 49 additions & 0 deletions umu/umu_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from contextlib import contextmanager
from ctypes.util import find_library
from functools import lru_cache
from hashlib import new as hashnew
from io import BufferedIOBase
from pathlib import Path
from re import Pattern
Expand Down Expand Up @@ -254,3 +255,51 @@ def has_umu_setup(path: Path = UMU_LOCAL) -> bool:
return path.exists() and any(
file for file in path.glob("*") if not file.name.endswith("lock")
)


# Copyright (C) 2005-2010 Gregory P. Smith ([email protected])
# Licensed to PSF under a Contributor Agreement.
# Source: https://raw.githubusercontent.com/python/cpython/refs/heads/3.11/Lib/hashlib.py
# License: https://raw.githubusercontent.com/python/cpython/refs/heads/3.11/LICENSE
def file_digest(fileobj, digest, /, *, _bufsize=2**18): # noqa: ANN001
"""Hash the contents of a file-like object. Returns a digest object.
*fileobj* must be a file-like object opened for reading in binary mode.
It accepts file objects from open(), io.BytesIO(), and SocketIO objects.
The function may bypass Python's I/O and use the file descriptor *fileno*
directly.
*digest* must either be a hash algorithm name as a *str*, a hash
constructor, or a callable that returns a hash object.
"""
# On Linux we could use AF_ALG sockets and sendfile() to archive zero-copy
# hashing with hardware acceleration.
digestobj = hashnew(digest) if isinstance(digest, str) else digest()

if hasattr(fileobj, "getbuffer"):
# io.BytesIO object, use zero-copy buffer
digestobj.update(fileobj.getbuffer())
return digestobj

# Only binary files implement readinto().
if not (
hasattr(fileobj, "readinto")
and hasattr(fileobj, "readable")
and fileobj.readable()
):
err = (
f"'{fileobj!r}' is not a file-like object in binary reading mode."
)
raise ValueError(err)

# binary file, socket.SocketIO object
# Note: socket I/O uses different syscalls than file I/O.
buf = bytearray(_bufsize) # Reusable buffer to reduce allocations.
view = memoryview(buf)
while True:
size = fileobj.readinto(buf)
if size == 0:
break # EOF
digestobj.update(view[:size])

return digestobj

0 comments on commit 6189d0d

Please sign in to comment.