Commit Graph

11 Commits

Author SHA1 Message Date
ItsAllAboutTheCode
80e6c46ee8 Fixed Lutris UnitTest when run on github
The primary causes of the issue is the manipulation of how the gog_cloud.py and gog_cloud_hooks.py was getting imported in UnitTest via the importlib mechanism. That seemed to have broken the resolution of paths to `lutris.services.*`.
As the GTK issues that it was trying to side step has been fixed at the `tests` root level, the workaround is no longer needed.

Additional changes have been added to help harden any potentially UnitTest environment and  circular import issues.
* Updated the github unit test run to use a virtual env to install the package dependencies and run the test
* Moved the imports of `lutris.services` subpackage to the method calls inside of the `__init__.py` script which will defer any potential circular imports until after the `lutris/services/__init__.py` script is fully imported.
2026-04-11 09:47:37 -05:00
Daniel Johnson
4d0641e50b Rename the world! All unit tests will start with '_test_' to avoid ambiguity. This means stuff like 'test_config.py' will no longer be loaded as test module.
This means that very module must be explicitly loaded by various tests that need the 'gi.requires_versions' part- they no longer sometimes get this by accident (sometimes).

In turn, _test_cloud_save_progress will no longer stub stuff in sys.modules, which is awful- it breaks later tests. That in turns makes it much chattier since it now actually logs stuff. But it seems to pass for all that.

Yikes!

Resolves #6570

Much research and drudgery done by Claude Code 🤖 before it clocked out.
2026-03-24 09:20:25 -04:00
Mathieu Comandon
e98326ec2d Add GOG depot-based downloads via gogdl integration
Integrate heroic-gogdl as a runtime component to download GOG games
directly from GOG's depot/CDN system (the same backend GOG Galaxy uses),
offering faster downloads and incremental updates compared to offline
installers.

Changes:
- New `gogdl_setup` installer command for depot downloads
- Auth bridge between Lutris GOG tokens and gogdl's format
- Depot installer offered as primary, offline installer as fallback
- Post-install game detection from goggame-*.info (DOSBox, ScummVM,
  Wine, native)
- Progress bar in the installer window during depot downloads
- Incremental depot updates for depot-installed games
- Handle expired GOG tokens gracefully (auto re-login via
  AuthTokenExpiredError)
- Wine prefix set to $GAMEDIR/pfx, separate from game files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 23:33:19 -07:00
Daniel Johnson
e9dcd9922d Add type annotations to DownloadCollectionProgressBox and test helpers to satisfy mypy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 18:34:12 -04:00
e88z4
6eb1f994d5 feat: Optimize GOG download speeds with parallel connections and resume support
Phase 1 - Chunk size & cache protection:
- Increase download chunk size from 8KB to 512KB (64x improvement)
- Add connection pooling support to Downloader (session + chunk_size params)
- Add lutris/util/download_cache.py: prevents deletion of in-progress files
  before installation completes; lifecycle states DOWNLOADING -> DOWNLOADED
  -> INSTALLING -> INSTALLED/FAILED; preserves failed installs for 7 days
- Integrate cache protection into interpreter.py cleanup, download progress
  boxes, and installation commands

Phase 2 - Multi-connection parallel downloader:
- New GOGDownloader (lutris/util/gog_downloader.py): parallel HTTP Range
  requests (4 workers by default) for large GOG installer files
- HTTP Range support detection with automatic single-stream fallback
- Connection pooling via requests.Session + HTTPAdapter
- Per-worker retry with exponential backoff (3 attempts)
- Thread-safe progress tracking for UI integration
- InstallerFile.downloader_class property for service-specific injection
- GOG service injects GOGDownloader via _format_links()

Phase 3 - Download resume with persistent byte-range tracking:
- New lutris/util/download_progress.py: atomic JSON sidecar (.progress)
  tracks completed byte ranges across crashes, hibernate, network errors
- GOGDownloader resumes from remaining ranges on restart; skips entirely
  if all ranges complete; starts fresh on file_size mismatch
- Atomic write (os.replace) for crash-safe progress file updates

Phase 4 - Concurrent file downloads, stall detection, pipelined I/O:
- DownloadCollectionProgressBox: concurrent downloads (MAX_CONCURRENT_FILES=2,
  prefetch-one), _ActiveDownload per-file state, aggregate progress/ETA,
  per-download independent retry
- Downloader: DownloadStallError, stall detection (LOW_SPEED_LIMIT=200 B/s,
  LOW_SPEED_TIME=30s), retry loop, _do_download()/_prepare_retry()
- GOGDownloader: pipelined writer thread (_writer_loop) decouples disk I/O
  from download workers; eliminates disk-write latency

Quality gates:
- ruff check: all checks passed
- ruff format: all files formatted
- mypy: success, no issues
- pytest: all tests passed
2026-03-09 06:23:03 +00:00
Sebastien Duthil
c13a6af1e1 util: rewrite cache_single as class decorator
Why:

* remove type-checking issues
* seems more appropriate than using nonlocal and monkey-patching
  cache_clear()
2026-02-22 12:01:23 -08:00
Dan Johnson
949ed354f2 MyPy fixes
My MyPy complains about the use of a Python 3.9 feature (why?) and then does not detect any type errors! I fix the test so MyPy will detect my actual type annotation error.

And then I fix that.
2025-06-17 09:30:03 -04:00
wrightgabriel0220
df6a1c9f3d Fixes formatting in BIOS config changes 2024-12-28 11:43:44 -08:00
Mathieu Comandon
38fbe9f05e Ruff reformat 2024-02-24 21:02:06 -08:00
Mathieu Comandon
bdfb77771f Reorder display options and simplify driver version logging 2024-02-01 03:55:25 -08:00
Alex Lowe
5415015f6f Typing additions for drivers file 2023-05-20 22:27:16 -04:00