Add a new package `scripts/modules/_bpy_internal/http`, containing classes to download files via HTTP. The code is intentionally put into the `_bpy_internal` package, as I don't intend it to be the end-all-be-all of downloaders for general use in add-ons. It's been written to support the Remote Asset Library project (#134495), where it will be used to download JSON files (to get the list of assets on the server) as well as the asset files themselves. The module consists of several parts. The main ones are: `class ConditionalDownloader` : File downloader, which downloads a URL to a file on disk. It supports conditional requests via `ETag`/`If-None-Match` and `Last-Modified`/`If-Modified-Since` HTTP headers (RFC 7273, section 3. Precondition Header Fields). A `304 Not Modified` response is treated as a succesful download. Metadata of the request (the response length in bytes, and the above headers) are stored on disk, in a location that is determined by the user of the class. Probably in the future it would be nice to have a single sqlite database for this (there's a TODO in the code about this). The downloader uses the Requests library, and manages its own HTTP session object. This way it can handle TCP/IP connection reuse, automatically retry failing connections, and in the future HTTP-level authentication. `class BackgroundDownloader` : Wrapper for a `ConditionalDownloader` that manages a background process for the actual downloading. It runs the downloader in a background process, while ensuring that its reporters (see below) get called on the main process. This way it's possible to do background downloading, while still receiving progress reports in a modal operator, which in turn can directly call Blender's Python API. Care was taken to [not use Python threads][1] `class DownloadReporter` : Protocol class. Objects adhering to the protocol can be given to a `ConditionalDownloader` or `BackgroundDownloader`. The protocol has functions like `download_starts(…)`, `download_progress(…)`, `download_error(…)`, which will be called by the downloader to report on what it's doing. I chose to make this a protocol, rather than an abstract superclass, because then it's possible to make an Operator a DownloadReporter without requiring multi-classing. [1]: https://docs.blender.org/api/main/info_gotchas_threading.html Pull Request: https://projects.blender.org/blender/blender/pulls/138327
4 lines
93 B
Python
4 lines
93 B
Python
# SPDX-FileCopyrightText: 2025 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|