Tips for updating code for 0.7


#1

I’ve recently been updating a lot of code to 0.7 and have found the process significantly more painful than the 0.5 to 0.6 transition. Of course, it is always much more difficult to get coding working on 2 different versions than it is to get it working on just the latest version, so, considering that there are no breaking changes after 0.7 until 2.0, I expect many packages to abandon 0.6 altogether as soon as that is feasible.

Here are a few things that you can anticipate dealing with:

  • uninitialized. Fortunately fixing this is mostly pretty trivial, but array constructors are a very core part of the language so it’ll feel like a substantial change. Probably the biggest effect this will have is that other AbstractArray types from packages for the most part won’t immediately use uninitialized, so you may wind up having arrays with unexpectedly inconsistent interfaces. This problem won’t go away in every case: sometimes the uninitialized constructors might just not make sense for an AbstractArray object so that their constructors will permanently diverge from Array, but I suppose that was the whole purpose of adding Uninitialized to the language.
  • stdlib moving to packages. You will need lots of using Compat.Random, using Compat.LinearAlgebra. This is all trivial stuff, but be aware Compat currently seems to be lagging a bit.
  • There are seemingly hundreds of tiny interface changes. Things like copyto! and axes as well as lots of more minor things like regex.
  • Default show behavior for lots of things seems to have changed. This becomes a problem if you are testing output strings (you should probably avoid these types of tests anyway, but sometimes you have no choice e.g. if you are testing the show behavior itself). You should get used to doing things like, e.g. "$DataFrame" instead of "DataFrames.DataFrame".
  • Writing good Compat code is hard. There are lots of "gotcha"s, and for this reason I’m guilty of not contributing to Compat when I really should have. I’ve even uncovered several bugs in Compat (now fixed) during my update processes.
  • This process will teach you the virtue of taking warnings seriously. If you already have tests with lots of unnecessary warnings, things are going to get much more difficult to parse when you try running them on 0.7. Unless your package is very small, I recommend getting 0.6 flawless before working on 0.7 updates.

Good luck everyone!


1.0 adoption path?
#2

I fervently hope that is going to be the case. The worst outcome would be to have many packages stuck at fixing up 0.6 long after 0.7 comes out because “users need 0.6”. We know how that went down in the Python world…


#3

This is responsible for 90% of the work related to updating to v0.7 for me. I wish there was a tool that would highlight or somehow mark lines which need review. Eg when encountering readuntil in a line, insert a line before like this:

## REVIEW: readuntil no longer includes delimiter in result
## use keep=true if you need it

an similarly for the other changes.


#4

The printouts of the deprecations and such for 0.7 are generally helpful in that they suggest how to fix a particular problem. I just wish there weren’t so copious. Sometimes it is hard to find the information one can use in all the text that gets printed out…


#5

Tips for updating code for 0.7

Wait for Femtocleaner to get a bunch of upgrades and open issues for @keno to solve for you.

I’m partially kidding.


#6

We just need enough cases to be caught.


#7

Julia is complaining about “JULIA_HOME”

Do I need the windows environment variable to be defined or is it a global string?

See below for the error I get.

Should I open an issue on WinRPM?
I am actually not sure if what I am seeing is related to WinRPM…

C:\Julia-0.7.X\bin>julia.exe
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: https://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.7.0-DEV.4474 (2018-03-06 17:45 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit e542b28ac2* (6 days old master)
|__/                   |  x86_64-w64-mingw32

julia> ENV["JULIA_HOME"]
"C:\\Julia-0.7.X\\bin\\"

julia> JULIA_HOME=ENV["JULIA_HOME"]
"C:\\Julia-0.7.X\\bin\\"

julia> versioninfo()
Julia Version 0.7.0-DEV.4474
Commit e542b28ac2* (2018-03-06 17:45 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, skylake)
Environment:
  JULIA_BINDIR = C:\JULIA-0.7.x\BIN
  JULIA_HOME = C:\Julia-0.7.X\bin\

julia> Pkg.buildWARNING: Base.Pkg is deprecated, run `using Pkg` instead
 in module Main
julia> Pkg.build("WinRPM")
WARNING: Base.Pkg is deprecated, run `using Pkg` instead
 in module Main
[ Info: Building WinRPM
WARNING: importing deprecated binding Base.Void into WinRPM.
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:55
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:55
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:128
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:128
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:128
in consume_function at C:\Users\bernhard.konig\.julia\v0.7\LibExpat\src\xpath.jl
┌ Warning: `assert` is deprecated, use `@assert` instead.
│   caller = xpath_parse(::String, ::Int64, ::Bool) at xpath.jl:216
└ @ LibExpat xpath.jl:216
┌ Warning: `nb_available` is deprecated, use `bytesavailable` instead.
│   caller = xpath_parse_expr(::String, ::Int64, ::Int64, ::Bool) at xpath.jl:473
└ @ LibExpat xpath.jl:473
┌ Warning: `nb_available` is deprecated, use `bytesavailable` instead.
│   caller = xpath_parse_expr(::String, ::Int64, ::Int64, ::Bool) at xpath.jl:463
└ @ LibExpat xpath.jl:463
┌ Warning: `nb_available` is deprecated, use `bytesavailable` instead.
│   caller = xpath_parse_expr(::String, ::Int64, ::Int64, ::Bool) at xpath.jl:428
└ @ LibExpat xpath.jl:428
┌ Warning: `isalnum(c::Char)` is deprecated, use `isalpha(c) || isnumeric(c)` instead.
│   caller = xpath_parse_expr(::String, ::Int64, ::Int64, ::Bool) at xpath.jl:438
└ @ LibExpat xpath.jl:438
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:330
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:330
WARNING: Base.Void is deprecated, use Nothing instead.
  likely near C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:330
in consume_function at C:\Users\bernhard.konig\.julia\v0.7\LibExpat\src\xpath.jl
┌ Warning: `assert` is deprecated, use `@assert` instead.
│   caller = xpath_parse(::String, ::Int64, ::Bool) at xpath.jl:216
└ @ LibExpat xpath.jl:216
┌ Warning: Loop variable `installed` around C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:424 overwrites a variable in an enclosing scope. In the future the variable will be local to the loop instead.
└ @ nothing WinRPM.jl:424
ERROR: LoadError: UndefVarError: JULIA_HOME not defined
Stacktrace:
 [1] top-level scope
 [2] include(::Module, ::String) at .\boot.jl:305
 [3] include_relative(::Module, ::String) at .\loading.jl:1072
 [4] include(::Module, ::String) at .\sysimg.jl:29
 [5] top-level scope
 [6] eval at .\boot.jl:308 [inlined]
 [7] top-level scope at .\<missing>:3
in expression starting at C:\Users\bernhard.konig\.julia\v0.7\WinRPM\src\WinRPM.jl:449
┌ Error: ------------------------------------------------------------
│ # Build failed for WinRPM
│   exception =
│    LoadError: Failed to precompile WinRPM to C:\Users\bernhard.konig\.julia\compiled\v0.7\WinRPM.ji.
│    Stacktrace:
│     [1] error at .\error.jl:33 [inlined]
│     [2] compilecache(::Base.PkgId) at .\loading.jl:1206
│     [3] _require(::Base.PkgId) at .\loading.jl:1008
│     [4] require(::Base.PkgId) at .\loading.jl:879
│     [5] require(::Module, ::Symbol) at .\loading.jl:874
│     [6] include(::Module, ::String) at .\boot.jl:305
│     [7] include_relative(::Module, ::String) at .\loading.jl:1072
│     [8] include at .\sysimg.jl:29 [inlined]
│     [9] include(::String) at .\loading.jl:1106
│     [10] top-level scope
│     [11] eval at .\boot.jl:308 [inlined]
│     [12] eval at .\sysimg.jl:74 [inlined]
│     [13] evalfile(::String, ::Array{String,1}) at .\loading.jl:1101 (repeats 2 times)
│     [14] #6 at .\none:13 [inlined]
│     [15] cd(::getfield(, Symbol("##6#8")){String}, ::String) at .\file.jl:61
│     [16] (::getfield(, Symbol("##5#7")))(::IOStream) at .\none:12
│     [17] #open#318(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::getfield(, Symbol("##5#7")), ::String, ::Vararg{String,N} where N) at .\iostream.jl:369
│     [18] open(::Function, ::String, ::String) at .\iostream.jl:367
│     [19] top-level scope
│     [20] eval at .\boot.jl:308 [inlined]
│     [21] eval(::Module, ::Expr) at .\sysimg.jl:74
│     [22] exec_options(::Base.JLOptions) at .\client.jl:304
│     [23] _start() at .\client.jl:455
│    in expression starting at C:\Users\bernhard.konig\.julia\v0.7\WinRPM\deps\build.jl:1
└ @ Main none:16
┌ Warning: ------------------------------------------------------------
│ # Build error summary
│
│ WinRPM had build errors.
│
│  - packages with build errors remain installed in C:\Users\bernhard.konig\.julia\v0.7
│  - build the package(s) and all dependencies with `Pkg.build("WinRPM")`
│  - build a single package by running its `deps/build.jl` script
└ @ Pkg.Entry entry.jl:649

julia> 


#8

Yes, you should define JULIA_BINDIR (the directory containing the binary).


#9

I have done that. At least julia tells me so. Please see my screenshot…


#10

Hm, not sure, I don’t use Windows so I’m unfamiliar with what’s going on here.

My guess would be that the WinRPM package uses the deprecated environment variables JULIA_HOME. The simplest way of resolving this would probably be to define JULIA_HOME in addition to JULIA_BINDIR. It’s probably also worth filing an issue with WinRPM if there isn’t one, though I suspect they are well-aware they will have to change a bunch of things for 0.7. I’d imagine a PR would be appreciated but I don’t know how much has to be done there.


#11

I have actually defined JULIA_HOME (see first lines of the screenshot), but I still get the error.
I just noted that there is already an issue on this. I suppose I should have checked there first (https://github.com/JuliaPackaging/WinRPM.jl/issues/135)
Thanks for the support.


#12

Thinking about this some more I have two more questions:

  1. what is the easiest way to have julia 0.6 and 0.7 both installed under windows?
    is there anything I need to change when switching between the two besides JULIA_HOME?

  2. is it an issue if the 0.6 executable is in my path? I.e. are any of the Pkg.update/build commands invoking julia itself and therefore may revert to julia 0.6 even though it should be 0.7?

Maybe the answer to question 2 resolves my issues (although it is cumbersome to change many environment variables forth and back).


#13

I don’t even think you need to set JULIA_HOME at all, as Julia will automatically use the path of its own binary as appropriate. See: Julia 0.6 and 0.7 living together in harmony in one environment


#14

You just need to do Pkg.checkout("WinRPM") to fix those issues.


#15

sadly there are multiple issues reporting the FemtoCleaner is not currently working


#16

It’s far too early to matter though.


#17

FWIW, It is very easy to run Femtocleaner.jl locally as described in the Readme.