How do I use Downloads.download to download to a custom location?

In the docs for Downloads.download, there are no examples and the errors don’t help.

For instance, I’m trying to download a Projects.toml file from another repository.

julia> project_url = "https://raw.githubusercontent.com/JuliaDynamics/DrWatson.jl/master/Project.toml"
julia> project_file = Downloads.download(project_url)

This goes to an auto-created temporary path, as the docs say. But I can’t understand the following to put it in a custom path:

download(url, [ output = tempfile() ];
    [ method = "GET", ]
    [ headers = <none>, ]
    [ timeout = <none>, ]
    [ progress = <none>, ]
    [ verbose = false, ]
    [ downloader = <default>, ]
) -> output

    url        :: AbstractString
    output     :: Union{AbstractString, AbstractCmd, IO}
    method     :: AbstractString
    headers    :: Union{AbstractVector, AbstractDict}
    timeout    :: Real
    progress   :: (total::Integer, now::Integer) --> Any
    verbose    :: Bool
    downloader :: Downloader

For instance, typing the following gives an error:

julia> project_file = Downloads.download(project_url, [output=tempfile()])
ERROR: syntax: misplaced assignment statement in "[output = tempfile()]" around REPL[16]:1
Stacktrace:
 [1] top-level scope
   @ REPL[16]:1

The docs say " Download a file from the given url, saving it to output or if not specified, a temporary path."

How do I change where output is?

[] means optional arguments, what you’re looking to do is:

project_file = Downloads.download(project_url)

or

project_file = Downloads.download(project_url, "path/to/somewhere")

in the first case, project_file will be a string to the downloaded file’s path (/tmp/ something), in the second case it will just be "path/to/somewhere"

2 Likes

output is not a named keyword argument, it is just the second positional argument to the function (note it occurs before the semicolon ;).

2 Likes

Is there documentation on how to read the Julia documentation? These points aren’t self-evident just looking at a page in these docs.

https://docs.julialang.org/en/v1/manual/functions/#Optional-Arguments

For example, the function Date(y, [m, d]) from Dates module constructs a Date type for a given year y , month m and day d . However, m and d arguments are optional and their default value is 1 . This behavior can be expressed concisely as:

perhaps you have defined it elsewhere but tempfile() is not a Julia function

(path, io) = mktemp() is though so tempfile = ()->mktemp()[1] would define it

You might consider making a PR to fix https://github.com/JuliaLang/Downloads.jl/blob/43899e71eed709866f96dd624f1c369a1c8e26a3/src/Downloads.jl#L162
Most likely tempfile was a typo for tempname. (The implementation has been changed to indirectly do this via mktemp, so the full story is somewhat different today.)

2 Likes

yes, it does look like a bug worth investigating

Not really a bug, just a typo in the docs.

2 Likes

What does the [output = ... ] syntax mean? I understand that [] indicates it’s optional, but what does the assignment mean?

I’m having some trouble figuring out how to parse the output :: Union{AbstractString, AbstractCmd, IO} line too.

What does AbstractCmd mean?

That’s the default value of the optional argument.

What does AbstractCmd mean?

AbstractCmd is defined here, it includes commands and pipelines of commands. Basically anything that can be run with the run command.

I’m having some trouble figuring out how to parse the output :: Union{AbstractString, AbstractCmd, IO} line too.

It means the argument can be a string, in which case it’s the path of a file to write; a command, in which case it is run as a command that consumes the download output; or an IO object, in which case it is written to.

2 Likes

The Julia code base is unfortunately quite inconsistent in how optional arguments are documented which might be part of the confusion.

https://github.com/JuliaLang/julia/issues/42319
https://github.com/JuliaLang/julia/issues/4902

1 Like

That’s what happens when a lot of different people write docs. If someone wants to pick a standard format and go and apply it everywhere that would accomplish consistency.

1 Like

@StefanKarpinski, thanks for the explanation! Very helpful.

Regarding your last post, I feel this is an appropriate place to plug Julia’s GSoD:
Julia’s Google Season of Docs for the main documentation

1 Like