diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c5ea33e..89964b47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ * Renamed `pydel!` to `unsafe_pydel` and exported. A `Py` is now always a valid, fixed, non-NULL Python object in the documented API. * Python errors no longer automatically set `sys.last_traceback` etc. when displayed from Julia. - * Removed `CONFIG.auto_sys_last_traceback`. + * Added [`fix_qt_plugin_path` preference](@ref pythoncall-config), replacing `CONFIG.auto_fix_qt_plugin_path`. + * Removed `PythonCall.CONFIG`. * Changes to `PythonCall.GC` (now more like `Base.GC`): * `enable(true)` replaces `enable()`. * `enable(false)` replaces `disable()`. diff --git a/docs/src/pythoncall.md b/docs/src/pythoncall.md index 7c604b9a..c2cd2aac 100644 --- a/docs/src/pythoncall.md +++ b/docs/src/pythoncall.md @@ -289,6 +289,7 @@ variables. | `exe` | `JULIA_PYTHONCALL_EXE` | Path to the Python executable, or special values (see below). | | `lib` | `JULIA_PYTHONCALL_LIB` | Path to the Python library (usually inferred automatically). | | `pickle` | `JULIA_PYTHONCALL_PICKLE` | Pickle module to use for serialization (`pickle` or `dill`). | +| `fix_qt_plugin_path=` | `JULIA_PYTHONCALL_FIX_QT_PLUGIN_PATH=` | When true (the default), automatically [fix the Qt plugin path](@ref `PythonCall.fix_qt_plugin_path`) when activating a Qt-based event loop. | The easiest way to set these preferences is with the [`PreferenceTools`](https://github.com/cjdoris/PreferenceTools.jl) diff --git a/docs/src/v1-migration-guide.md b/docs/src/v1-migration-guide.md index 123e6f4c..3300df85 100644 --- a/docs/src/v1-migration-guide.md +++ b/docs/src/v1-migration-guide.md @@ -70,6 +70,13 @@ work. * Instead of `pdb.pm()` use `pdb.post_mortem(err[1].exception)`. +The `PythonCall.CONFIG.auto_fix_qt_plugin_path` config has been replaced with the +[`fix_qt_plugin_path` preference](@ref pythoncall-config). + +* Instead of `PythonCall.CONFIG.auto_fix_qt_plugin_path = false`, set preference + `pkg> preference add PythonCall fix_qt_plugin_path=false` or the env var + `JULIA_PYTHONCALL_FIX_QT_PLUGIN_PATH=0`. + ## `PythonCall.GC` This submodule has been changed to closer mimic the `Base.GC` API. diff --git a/src/API/publics.jl b/src/API/publics.jl index 74db3538..bda0fc47 100644 --- a/src/API/publics.jl +++ b/src/API/publics.jl @@ -10,9 +10,6 @@ if Base.VERSION ≥ v"1.11" python_library_handle, python_library_path, python_version, - - # Core - CONFIG, # Compat event_loop_off, diff --git a/src/Compat/gui.jl b/src/Compat/gui.jl index b0be9363..ed8957b5 100644 --- a/src/Compat/gui.jl +++ b/src/Compat/gui.jl @@ -7,7 +7,7 @@ This fixes the problem that Qt does not know where to find its `qt.conf` file, b always looks relative to `sys.executable`, which can be the Julia executable not the Python one when using this package. -If `CONFIG.auto_fix_qt_plugin_path` is true, then this is run automatically before `PyQt4`, `PyQt5`, `PySide`, `PySide2` or `PySide6` are imported. +If the `fix_qt_plugin_path` preference is true, then this is run automatically before `PyQt4`, `PyQt5`, `PySide`, `PySide2` or `PySide6` are imported. """ function fix_qt_plugin_path() C.CTX.exe_path === nothing && return false @@ -53,30 +53,6 @@ function fix_qt_plugin_path() return false end -# """ -# pyinteract(; force=false, sleep=0.1) - -# Some Python GUIs can work interactively, meaning the GUI is available but the interactive prompt is returned (e.g. after calling `matplotlib.pyplot.ion()`). -# To use these from Julia, currently you must manually call `pyinteract()` each time you want to interact. - -# Internally, this is calling the `PyOS_InputHook` asynchronously. Only one copy is run at a time unless `force` is true. - -# The asynchronous task waits for `sleep` seconds before calling the hook function. -# This gives time for the next prompt to be printed and waiting for input. -# As a result, there will be a small delay before the GUI becomes interactive. -# """ -# pyinteract(; force::Bool = false, sleep::Real = 0.1) = -# if !CONFIG.inputhookrunning || force -# CONFIG.inputhookrunning = true -# @async begin -# sleep > 0 && Base.sleep(sleep) -# C.PyOS_RunInputHook() -# CONFIG.inputhookrunning = false -# end -# nothing -# end -# export pyinteract - const EVENT_LOOPS = Dict{Symbol,Base.Timer}() const new_event_loop_callback = pynew() @@ -158,13 +134,14 @@ function init_gui() pycopy!(new_event_loop_callback, g["new_event_loop_callback"]) # add a hook to automatically call fix_qt_plugin_path() - fixqthook = - Py(() -> (PythonCall.CONFIG.auto_fix_qt_plugin_path && fix_qt_plugin_path(); nothing)) - pymodulehooks.add_hook("PyQt4", fixqthook) - pymodulehooks.add_hook("PyQt5", fixqthook) - pymodulehooks.add_hook("PySide", fixqthook) - pymodulehooks.add_hook("PySide2", fixqthook) - pymodulehooks.add_hook("PySide6", fixqthook) + if Utils.getpref_fix_qt_plugin_path() + fixqthook = Py(fix_qt_plugin_path) + pymodulehooks.add_hook("PyQt4", fixqthook) + pymodulehooks.add_hook("PyQt5", fixqthook) + pymodulehooks.add_hook("PySide", fixqthook) + pymodulehooks.add_hook("PySide2", fixqthook) + pymodulehooks.add_hook("PySide6", fixqthook) + end end end diff --git a/src/Core/Core.jl b/src/Core/Core.jl index 118bec2a..be053f29 100644 --- a/src/Core/Core.jl +++ b/src/Core/Core.jl @@ -196,7 +196,6 @@ export include("Py.jl") include("err.jl") -include("config.jl") include("consts.jl") include("builtins.jl") include("stdlib.jl") diff --git a/src/Core/config.jl b/src/Core/config.jl deleted file mode 100644 index 967bd33e..00000000 --- a/src/Core/config.jl +++ /dev/null @@ -1,6 +0,0 @@ -@kwdef mutable struct Config - meta::String = "" - auto_fix_qt_plugin_path::Bool = true -end - -const CONFIG = Config() diff --git a/src/PythonCall.jl b/src/PythonCall.jl index a689e43d..c6b166bd 100644 --- a/src/PythonCall.jl +++ b/src/PythonCall.jl @@ -15,9 +15,6 @@ include("Wrap/Wrap.jl") include("JlWrap/JlWrap.jl") include("Compat/Compat.jl") -# non-exported API -using .Core: CONFIG - # not API but used in tests for k in [ :pyjlanytype, diff --git a/src/Utils/Utils.jl b/src/Utils/Utils.jl index a26b3198..ea10a115 100644 --- a/src/Utils/Utils.jl +++ b/src/Utils/Utils.jl @@ -12,11 +12,14 @@ end checkpref(::Type{String}, x) = error("invalid preference of type $(type(x)), expecting a string") checkpref(::Type{String}, x::AbstractString) = convert(String, x) +checkpref(::Type{Bool}, x::Bool) = x +checkpref(::Type{Bool}, x::AbstractString) = x in ("1", "yes", "true") ? true : x in ("0", "no", "false") ? false : error("expecting '0', 'no', 'false', '1', 'yes' or 'true'") # Specific preference functions getpref_exe() = getpref(String, "exe", "JULIA_PYTHONCALL_EXE", "") getpref_lib() = getpref(String, "lib", "JULIA_PYTHONCALL_LIB", nothing) getpref_pickle() = getpref(String, "pickle", "JULIA_PYTHONCALL_PICKLE", "pickle") +getpref_fix_qt_plugin_path() = getpref(Bool, "fix_qt_plugin_path", "JULIA_PYTHONCALL_FIX_QT_PLUGIN_PATH", true) function explode_union(T) @nospecialize T