How to patch another package?

Hi there,

I would like to patch another package. This worked perfectly fine up to julia 1.9 but with 1.10 it broke. See this thread ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation

Concretely I would like to patch PythonCall’s serialize_py and deserialize_py methods to use dill instead of pickle.

It seems the only option is to make the package __precompile__(false), which is just a bit too much for me. The alternative sometimes suggested is to use __init__, but this does not work because @eval is buggy inside __init__, aka does not work, and you also aren’t allowed to define top-level functions inside __init__.

This is very crucial for the project I am working on. Any help is highly appreciated.

Fork and use your own fork?

1 Like

I was not thinking about this - yes, sounds like a workaround.

I still would prefer to stay on top of the original package for easier updates.

Can you contribute something to the underlying package (a keyword argument or something) that lets you choose the format?

2 Likes

Why is it “too much”? Overwriting a method works reliably in Julia, packages with the overwrite just cannot be precompiled.

And btw, even without this __precompile__ line, everything should just work! A scary error is printed, but the methods get overwritten properly. Not sure why it is printed as “error” instead of info or warning…

The new function Base.generating_output() in Julia 1.11 will help with this. Base.generating_output() is true if generating a pkgimage cache. You do not watn to perform patching then.

if !Base.generating_output()
    # hacky patching
end

If Julia 1.10, you can define it as follows:

generating_output() = ccall(:jl_generating_output, Cint, ()) != 0

__precompile__(false) regards the entire package as far as I understand it, well as all packages dependening on it, which results in bad user experience as the package time to first anything is quite slow

Thank you, this sounds interesting. Would this if !Base.generating_output() block be executed?

I mean is it like __init__ in that we have a guarantee that it will run? Or is it more like a normal if in the file where depending one the if clause on part is executed and the other maybe never.

Julia is “generating output” when it is “precompiling”. This helps us distinguish between the precompiling state and other states on module loading.

1 Like