Closed mikedarcy closed 3 years ago
Changes Missing Coverage | Covered Lines | Changed/Added Lines | % | ||
---|---|---|---|---|---|
bdbag/fetch/transports/base_transport.py | 8 | 9 | 88.89% | ||
bdbag/bdbag_config.py | 30 | 32 | 93.75% | ||
bdbag/fetch/transports/fetch_ftp.py | 47 | 51 | 92.16% | ||
bdbag/fetch/transports/fetch_http.py | 140 | 148 | 94.59% | ||
<!-- | Total: | 347 | 362 | 95.86% | --> |
Totals | |
---|---|
Change from base Build 262: | 3.1% |
Covered Lines: | 3233 |
Relevant Lines: | 3360 |
This PR targets #37 and refactors the
bdbag.fetch.transports
module to support externally implemented transports that can be plugged-in (i.e., declared as run-time imports) via thefetch_config
configuration object in thebdbag.json
config file.This requires developers to perform the following integration tasks:
Create a class deriving from
bdbag.fetch.transports.base_transport.BaseFetchTransport
and implement three required functions:__init__(self, config, keychain, **kwargs)
: The class constructor. Derived classes should first callsuper(<derived class name>, self).__init__(config, keychain, **kwargs)
which sets theconfig
,keychain
, andkwargs
variables as class member variables with the same names.fetch(self, url, output_path, **kwargs)
: This method should implement the logic required to transfer a file referenced byurl
to the local path referenced byoutput_path
. The**kwargs
argument is an extensible argument dictionary that the framework may populate with extra data, for example: an integer argumentsize
may present (if it can be found infetch.txt
for a given fetch entry), representing the expected size of the remote file in bytes.cleanup(self)
: This method should implement any transport-specific release of resources. Note this function will be called only once per-transport at the end of a entire bag fetch, and not once per-file.Configure the usage of the external transport via the
fetch_config
object of thebdbag.json
configuration file. Thefetch_config
object is comprised of child configuration objects keyed by a lowercase string value representing the URL protocol scheme that is being configured. When configuring an external handler, the following applies:There is a single required top-level string parameter with the key name
handler
which maps to the fully-qualified class name implementing the required methods of thebdbag.fetch.transports.base_transport.BaseFetchTransport
base class. At runtime the bdbag fetch framework code will attempt to load this class viaimportlib.import_module
machinery and if successful, it will be instantiated and returned to the bdbag fetch framework code and the class instance cached for the duration of the bag fetch operation. Subsequently, whenever a URL is encountered infetch.txt
with a protocol scheme matching that of the installed handler, that handler'sfetch
method will be invoked.There is also an optional string parameter,
allow_keychain
, which must be present and set to "True" in order to toggle the propagation of the bdbagkeychain
into the handler code during the__init__
call. If theallow_keychain
parameter is missing or set to any other value that cannot be evaluated as a Python booleanTrue
, then the value of thekeychain
variable passed to the__init__
call will beNone
. In general, if the custom handler code has its own mechanism for managing credentials, then this parameter may be omitted. If the handler intends to make use of the bdbagkeychain
that is currently in context for the current user and fetch operation, then this parameter must be present and evaluate toTrue
.The remainder of the protocol scheme handler configuration object can consist of any valid JSON; the entire object value assigned to the scheme key will be passed as the
config
parameter to the__init__
method of the custom handler.For example, given the following
fetch_config
section:For the scheme
foo
, the following object will be passed as theconfig
parameter to the__init__
method ofmy.custom.FooTransport
upon class instantiation: