#94 Make installing and updating dependencies more user-friendly

Merged Seth Axen sethaxen

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.

Showing 5 of 7 files from the diff.

@@ -1,4 +1,4 @@
Loading
1 -
const SUPPORTED_GROUPS = map(Symbol, arviz.data.inference_data.SUPPORTED_GROUPS)
1 +
const SUPPORTED_GROUPS = Symbol[]
2 2
3 3
"""
4 4
    InferenceData(::PyObject)

@@ -8,10 +8,7 @@
Loading
8 8
using DataFrames
9 9
10 10
using PyCall
11 -
if PyCall.conda
12 -
    using Conda
13 -
    Conda.add_channel("conda-forge") # try to avoid mixing channels
14 -
end
11 +
using Conda
15 12
using PyPlot
16 13
17 14
import Base:
@@ -85,72 +82,20 @@
Loading
85 82
## rcParams
86 83
export rcParams, with_rc_context
87 84
85 +
const _min_arviz_version = v"0.8.0"
88 86
const arviz = PyNULL()
89 87
const xarray = PyNULL()
90 88
const bokeh = PyNULL()
91 89
const pandas = PyNULL()
92 90
const _rcParams = PyNULL()
93 -
const _min_arviz_version = v"0.8.0"
94 -
95 -
import_arviz() = pyimport_conda("arviz", "arviz", "conda-forge")
96 91
97 -
arviz_version() = VersionNumber(arviz.__version__)
98 -
99 -
function check_version()
100 -
    if arviz_version() < _min_arviz_version
101 -
        @warn "ArviZ.jl only officially supports arviz version $(_min_arviz_version) or greater but found version $(arviz_version()). Please update."
102 -
    end
103 -
    return nothing
104 -
end
92 +
include("setup.jl")
105 93
106 94
# Load ArviZ once at precompilation time for docstringS
107 95
copy!(arviz, import_arviz())
108 -
check_version()
96 +
check_needs_update(update = false)
109 97
const _precompile_arviz_version = arviz_version()
110 98
111 -
function initialize_arviz()
112 -
    ispynull(arviz) || return
113 -
    copy!(arviz, import_arviz())
114 -
    if arviz_version() != _precompile_arviz_version
115 -
        @warn "ArviZ.jl was precompiled using arviz version $(_precompile_version) but loaded with version $(arviz_version()). Please recompile with `using Pkg; Pkg.build('ArviZ')`."
116 -
    end
117 -
118 -
    pytype_mapping(arviz.InferenceData, InferenceData)
119 -
120 -
    # pytypemap-ing RcParams produces a Dict
121 -
    copy!(_rcParams, py"$(arviz).rcparams.rcParams"o)
122 -
123 -
    # use 1-based indexing by default within arviz
124 -
    rcParams["data.index_origin"] = 1
125 -
126 -
    # handle Bokeh showing ourselves
127 -
    rcParams["plot.bokeh.show"] = false
128 -
129 -
    initialize_xarray()
130 -
    initialize_numpy()
131 -
    return nothing
132 -
end
133 -
134 -
function initialize_xarray()
135 -
    ispynull(xarray) || return
136 -
    copy!(xarray, pyimport_conda("xarray", "xarray", "conda-forge"))
137 -
    pyimport_conda("dask", "dask", "conda-forge")
138 -
    pytype_mapping(xarray.Dataset, Dataset)
139 -
    return nothing
140 -
end
141 -
142 -
function initialize_numpy()
143 -
    # Trigger NumPy initialization, see https://github.com/JuliaPy/PyCall.jl/issues/744
144 -
    PyObject([true])
145 -
    return nothing
146 -
end
147 -
148 -
function initialize_pandas()
149 -
    ispynull(pandas) || return
150 -
    copy!(pandas, pyimport_conda("pandas", "pandas", "conda-forge"))
151 -
    return nothing
152 -
end
153 -
154 99
function __init__()
155 100
    initialize_arviz()
156 101
    @require MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" begin

@@ -0,0 +1,132 @@
Loading
1 +
import_arviz() = _import_dependency("arviz", "arviz"; channel = "conda-forge")
2 +
3 +
arviz_version() = VersionNumber(arviz.__version__)
4 +
5 +
function check_needs_update(; update = true)
6 +
    if arviz_version() < _min_arviz_version
7 +
        @warn "ArviZ.jl only officially supports arviz version $(_min_arviz_version) or " *
8 +
              "greater but found version $(arviz_version())."
9 +
        if update
10 +
            if update_arviz()
11 +
                # yay, but we still already imported the old version
12 +
                msg = """
13 +
                Please rebuild ArviZ.jl with `using Pkg; Pkg.build("ArviZ")` and re-launch Julia
14 +
                to continue.
15 +
                """
16 +
            else
17 +
                msg = """
18 +
                Could not automatically update arviz. Please manually update arviz, rebuild
19 +
                ArviZ.jl with `using Pkg; Pkg.build("ArviZ")`, and then re-launch Julia to
20 +
                continue.
21 +
                """
22 +
            end
23 +
            @warn msg
24 +
        end
25 +
    end
26 +
    return nothing
27 +
end
28 +
29 +
function check_needs_rebuild()
30 +
    if arviz_version() != _precompile_arviz_version
31 +
        msg = """
32 +
        ArviZ.jl was built using arviz version $(_precompile_arviz_version) but loaded with
33 +
        version $(arviz_version()). Please recompile with `using Pkg; Pkg.build("ArviZ")`
34 +
        and re-launch Julia to continue.
35 +
        """
36 +
        @warn msg
37 +
    end
38 +
    return nothing
39 +
end
40 +
41 +
function initialize_arviz()
42 +
    ispynull(arviz) || return
43 +
    copy!(arviz, import_arviz())
44 +
    check_needs_update(update = true)
45 +
    check_needs_rebuild()
46 +
47 +
    append!(SUPPORTED_GROUPS, map(Symbol, arviz.data.inference_data.SUPPORTED_GROUPS))
48 +
49 +
    pytype_mapping(arviz.InferenceData, InferenceData)
50 +
51 +
    # pytypemap-ing RcParams produces a Dict
52 +
    copy!(_rcParams, py"$(arviz).rcparams.rcParams"o)
53 +
54 +
    # use 1-based indexing by default within arviz
55 +
    rcParams["data.index_origin"] = 1
56 +
57 +
    # handle Bokeh showing ourselves
58 +
    rcParams["plot.bokeh.show"] = false
59 +
60 +
    initialize_xarray()
61 +
    initialize_numpy()
62 +
    return nothing
63 +
end
64 +
65 +
function initialize_xarray()
66 +
    ispynull(xarray) || return
67 +
    copy!(xarray, _import_dependency("xarray", "xarray"; channel = "conda-forge"))
68 +
    _import_dependency("dask", "dask"; channel = "conda-forge")
69 +
    pytype_mapping(xarray.Dataset, Dataset)
70 +
    return nothing
71 +
end
72 +
73 +
function initialize_numpy()
74 +
    # Trigger NumPy initialization, see https://github.com/JuliaPy/PyCall.jl/issues/744
75 +
    PyObject([true])
76 +
    return nothing
77 +
end
78 +
79 +
function initialize_pandas()
80 +
    ispynull(pandas) || return
81 +
    copy!(pandas, _import_dependency("pandas", "pandas"; channel = "conda-forge"))
82 +
    return nothing
83 +
end
84 +
85 +
function update_arviz()
86 +
    # updating arviz can change other packages, so we always ask for permission
87 +
    if _using_conda() && _isyes(Base.prompt("Try updating arviz using conda? [Y/n]"))
88 +
        # this syntax isn't officially supported, but it works (for now)
89 +
        try
90 +
            Conda.add("arviz>=$_min_arviz_version"; channel = "conda-forge")
91 +
            return true
92 +
        catch e
93 +
            println(e.msg)
94 +
        end
95 +
    end
96 +
    if _has_pip() && _isyes(Base.prompt("Try updating arviz using pip? [Y/n]"))
97 +
        # can't specify version lower bound, so update to latest
98 +
        try
99 +
            run(`$(PyCall.pyprogramname) -m pip install --upgrade -- arviz`)
100 +
            return true
101 +
        catch e
102 +
            println(e.msg)
103 +
        end
104 +
    end
105 +
    return false
106 +
end
107 +
108 +
function _import_dependency(modulename, pkgname; channel = nothing)
109 +
    _has_pymodule(modulename) && return pyimport(modulename)
110 +
    return if _using_conda()
111 +
        # auto-installing with conda is safe and convenient
112 +
        if channel === nothing
113 +
            pyimport_conda(modulename, pkgname)
114 +
        else
115 +
            pyimport_conda(modulename, pkgname, channel)
116 +
        end
117 +
    elseif _has_pip() && _isyes(Base.prompt("Try installing $pkgname using pip? [Y/n]"))
118 +
        # installing with pip is riskier, so we ask for permission
119 +
        run(`$(PyCall.pyprogramname) -m pip install -- $pkgname`)
120 +
        pyimport(modulename)
121 +
    else
122 +
        error("Dependency $modulename cannot be imported. Install manually to continue.")
123 +
    end
124 +
end
125 +
126 +
_isyes(s) = isempty(s) || lowercase(strip(s)) ∈ ("y", "yes")
127 +
128 +
_using_conda() = PyCall.conda
129 +
130 +
_has_pip() = ispynull(pyimport_e("pip"))
131 +
132 +
_has_pymodule(modulename) = !ispynull(pyimport_e(modulename))

@@ -3,7 +3,7 @@
Loading
3 3
function initialize_bokeh()
4 4
    ispynull(bokeh) || return
5 5
    try
6 -
        copy!(bokeh, pyimport_conda("bokeh", "bokeh", "conda-forge"))
6 +
        copy!(bokeh, _import_dependency("bokeh", "bokeh"; channel = "conda-forge"))
7 7
    catch err
8 8
        copy!(bokeh, PyNULL())
9 9
        throw(err)
@@ -15,7 +15,7 @@
Loading
15 15
function initialize_bokeh_png_deps()
16 16
    has_bokeh_png_deps && return
17 17
    try
18 -
        pyimport_conda("selenium", "selenium", "conda-forge")
18 +
        _import_dependency("selenium", "selenium"; channel = "conda-forge")
19 19
        has_bokeh_png_deps = true
20 20
    catch err
21 21
        has_bokeh_png_deps = false

@@ -74,7 +74,7 @@
Loading
74 74
load_backend(backend) = nothing
75 75
76 76
function forwarddoc(f::Symbol)
77 -
    return "See documentation for [`arviz.$(f)`](https://arviz-devs.github.io/arviz/generated/arviz.$(f).html)."
77 +
    return "See documentation for [`arviz.$(f)`](https://arviz-devs.github.io/arviz/api/generated/arviz.$(f).html)."
78 78
end
79 79
80 80
forwardgetdoc(f::Symbol) = Docs.getdoc(getproperty(arviz, f))

Learn more Showing 1 files with coverage changes found.

New file src/setup.jl
New
Loading file...
Files Coverage
src -4.34% 87.71%
Project Totals (13 files) 87.71%
Loading