Resources#

Fetching input artifacts (datasets, source code) and declaring them as command dependencies.

Register a resource type#

Declare how to acquire an input artifact with knit_register_resource and a download decorator.

APIs: knit_register_resource, knit_with_local, knit_with_git, knit_with_url

A resource is a named, downloadable input artifact — a dataset or a piece of third-party source code. knit_register_resource declares a resource type: what the artifact is and, through exactly one download decorator, how to acquire it. There is no body to write; knit supplies the download itself.

# A resource TYPE declares HOW to acquire an artifact --- exactly one download
# decorator selects the backend. The local backend links (or, with --copy, snapshots)
# a path already on disk; swap in @with_git <url> <ref> or @with_url <url>
# to download instead. There is no body: knit supplies the download itself.
@resource "dataset" "An input dataset staged from a local path."
@with_local "./data"
@done
# A resource TYPE declares HOW to acquire an artifact --- exactly one download
# decorator selects the backend. The local backend links (or, with --copy, snapshots)
# a path already on disk; swap in @with_git <url> <ref> or @with_url <url>
# to download instead. There is no body: knit supplies the download itself.
knit_register_resource "dataset" "An input dataset staged from a local path."
knit_with_local "./data"
knit_done

Pick the decorator that matches the source: knit_with_local <path> links or copies a path already on disk, knit_with_git <url> <ref> clones a repository at a ref, and knit_with_url <url> downloads (and optionally uncompresses) an archive. Add knit_with_checksum <sha256> to pin the artifact’s integrity.

Fetch a resource instance#

Acquire a named instance of a resource type with the knit fetch dispatcher.

APIs: fetch

knit fetch acquires a named instance of a registered resource type. Like knit setup, it is a dispatcher: options before -- configure the fetch, and everything after -- selects the resource type and its own arguments.

$ ./exp.sh fetch --name sample -- dataset --path ./data
/path/to/experiment/resources/sample

The instance lands at resources/<name> and is recorded in the type’s table for provenance. Fetching is idempotent by name: re-fetching sample from the same source does nothing, while a different source under the same name is refused. A downloaded or copied instance is made read-only so a shared input cannot be mutated. knit fetch prints the instance path on stdout (logging is on stderr), but commands normally consume a resource by name (see Consume a resource in a command).

Consume a resource in a command#

Declare a resource dependency with knit_with_resource and resolve it with knit_resource_path.

APIs: knit_with_resource, knit_resource_path

A command declares the resources it needs with knit_with_resource "<param>:<type>". The value the user passes is the instance name; knit checks that the named instance exists and is of the declared type before the body runs, then records a used_by provenance edge from the resource to the command. Inside the body, knit_resource_path turns the name into an on-disk path.

# A command declares the resources it needs with @with_resource
# "<param>:<type>". The value the user passes is the instance NAME, not a path;
# knit validates that the named instance exists and is of the right type before the
# body runs, then knit_resource_path turns the name into an on-disk directory.
@command "summarize" "Summarize a fetched dataset."
@with_resource "data:dataset" "Name of the dataset instance to read."
@with_table
@with_output "lines:integer" "0" "Number of lines in the dataset."
_summarize() {
    local dir
    dir="$(knit_resource_path "$(knit_get_parameter data "$@")")"

    local n
    n=$(wc -l < "${dir}/values.txt")
    knit_output "lines" "${n}"
    printf 'dataset %s has %s line(s)\n' "${dir}" "${n}"
}
@done
# A command declares the resources it needs with @with_resource
# "<param>:<type>". The value the user passes is the instance NAME, not a path;
# knit validates that the named instance exists and is of the right type before the
# body runs, then knit_resource_path turns the name into an on-disk directory.
knit_register "summarize" _summarize "Summarize a fetched dataset."
knit_with_resource "data:dataset" "Name of the dataset instance to read."
knit_with_table
knit_with_output "lines:integer" "0" "Number of lines in the dataset."
_summarize() {
    local dir
    dir="$(knit_resource_path "$(knit_get_parameter data "$@")")"

    local n
    n=$(wc -l < "${dir}/values.txt")
    knit_output "lines" "${n}"
    printf 'dataset %s has %s line(s)\n' "${dir}" "${n}"
}
knit_done

Any command can depend on a resource — including a setup, which is the usual place to process a fetched artifact (build fetched source, index a dataset). The user supplies the instance name on the command line, e.g. ./exp.sh summarize --data sample.