napari / napari-plugin-manager

napari plugin manager to provide a graphical user interface for installing napari plugins.
https://napari.org/napari-plugin-manager
BSD 3-Clause "New" or "Revised" License
5 stars 5 forks source link

Update lists without refreshing and other fixes #45

Closed goanpeca closed 2 months ago

goanpeca commented 4 months ago

Fixes #29 Fixes #61

napari-dialog

Screenshot 2024-06-06 at 8 48 54 PM
codecov[bot] commented 3 months ago

Codecov Report

Attention: Patch coverage is 89.17836% with 54 lines in your changes missing coverage. Please review.

Project coverage is 91.91%. Comparing base (5027417) to head (14d0c8a).

Files Patch % Lines
napari_plugin_manager/qt_plugin_dialog.py 85.27% 38 Missing :warning:
...ri_plugin_manager/_tests/test_installer_process.py 90.62% 6 Missing :warning:
...ari_plugin_manager/_tests/test_qt_plugin_dialog.py 94.79% 5 Missing :warning:
napari_plugin_manager/_tests/conftest.py 78.94% 4 Missing :warning:
napari_plugin_manager/qt_package_installer.py 96.77% 1 Missing :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #45 +/- ## ========================================== + Coverage 87.11% 91.91% +4.79% ========================================== Files 9 10 +1 Lines 1366 1669 +303 ========================================== + Hits 1190 1534 +344 + Misses 176 135 -41 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

goanpeca commented 3 months ago

@psobolewskiPhD I tried to use the qdebounce from superqt but it does not exactly work as it is needed.

psobolewskiPhD commented 3 months ago

Works well. I think the tooltip is too long and technical? No user has any idea what npe2api is or whatever. How about just Refresh plugin listings? or something like that? Honestly, refresh alone is probably clear enough.

Also, off topic: oh, pip 🙄 :

ERROR: Cannot install zarpaint==0.3.1 because these package versions have conflicting dependencies.

The conflict is caused by:
    zarpaint 0.3.1 depends on napari>=0.4.11.dev80
    The user requested (constraint) napari==0.5.0a2.dev720+gb00d7381b

Edit: I see now that Jaime requested this. 😬 I think it's just too much of an implementation detail... 🤷

goanpeca commented 3 months ago

@jaimergp what do you think. Maybe we could simplify the message a bit :) ?

goanpeca commented 3 months ago

Hi @Czaki thanks for the review. Will fixe your suggestions and try to increase coverage!

goanpeca commented 3 months ago

@Czaki added more testing as requested. I think we are in much better shape now :)

jaimergp commented 3 months ago

@jaimergp what do you think. Maybe we could simplify the message a bit :) ?

Yep, no strong feelings. Go ahead.

dalthviz commented 3 months ago

Hi there, gave this a check and seems like after installing a plugin the only way for it to show up over the installed list is to hit Refresh a couple of times:

install_plugin_refresh

Maybe something in my setup is causing that (checking this on Windows) 🤔

goanpeca commented 3 months ago

Hi @dalthviz thanks for checking. Is this something that happens consistently every time or only some of the time? I have seen it sometimes on my end and I am trying to see what can be done.

dalthviz commented 3 months ago

Is this something that happens consistently every time or only some of the time?

I checked just a couple of times (launched napari, installed a plugin, saw the behavior, uninstalled the plugin and then relaunched napari to check again to record the GIF), so not sure if I can call that being able to reproduce consistenly 😅, but I will check again and define more detailed steps to reproduce :+1:

psobolewskiPhD commented 3 months ago

I also get the issue Daniel posted. Fresh napari dev install (python 3.12), installed this branch. Launch napari, open manager. Filter and install napari-threedee. Success, but doesn't show:

image

Clicking refresh once briefly showed all installed plugins, then blank again. Clicking refresh again shows the correct result of the filter:

image
dalthviz commented 3 months ago

Gave this another check and I would say I can reproduce the issue consistently:

Steps/Behavior

Setup info

``` napari: 0.5.0a2.dev761+g1a5362af Platform: Windows-10-10.0.19045-SP0 Python: 3.10.14 | packaged by conda-forge | (main, Mar 20 2024, 12:40:08) [MSC v.1938 64 bit (AMD64)] Qt: 5.15.2 PyQt5: 5.15.10 NumPy: 1.26.4 SciPy: 1.13.1 Dask: 2024.6.1 VisPy: 0.14.3 magicgui: 0.8.3 superqt: 0.6.7 in-n-out: 0.2.1 app-model: 0.2.7 npe2: 0.7.5 OpenGL: - GL version: 4.5.0 - Build 25.20.100.6444 - MAX_TEXTURE_SIZE: 16384 - GL_MAX_3D_TEXTURE_SIZE: 2048 Screens: - screen 1: resolution 1366x768, scale 1.0 - screen 2: resolution 1920x1080, scale 1.0 Optional: - numba: 0.60.0 - triangle not installed Settings path: - C:\Users\dalth\AppData\Local\napari\napari-dev_4454fdbf170edefe23827a4bf512389a6806af69\settings.yaml ```
``` # packages in environment at C:\Users\dalth\anaconda3\envs\napari-dev: # # Name Version Build Channel alabaster 0.7.16 pypi_0 pypi annotated-types 0.7.0 pypi_0 pypi anyio 4.4.0 pypi_0 pypi app-model 0.2.7 pypi_0 pypi appdirs 1.4.4 pypi_0 pypi argon2-cffi 23.1.0 pypi_0 pypi argon2-cffi-bindings 21.2.0 pypi_0 pypi arrow 1.3.0 pypi_0 pypi asciitree 0.3.3 pypi_0 pypi asttokens 2.4.1 pypi_0 pypi async-lru 2.0.4 pypi_0 pypi attrs 23.2.0 pypi_0 pypi babel 2.15.0 pypi_0 pypi beautifulsoup4 4.12.3 pypi_0 pypi bleach 6.1.0 pypi_0 pypi build 1.2.1 pypi_0 pypi bzip2 1.0.8 hcfcfb64_5 conda-forge ca-certificates 2024.6.2 h56e8100_0 conda-forge cachey 0.2.1 pypi_0 pypi certifi 2024.6.2 pypi_0 pypi cffi 1.16.0 pypi_0 pypi cfgv 3.4.0 pypi_0 pypi charset-normalizer 3.3.2 pypi_0 pypi check-manifest 0.49 pypi_0 pypi click 8.1.7 pypi_0 pypi cloudpickle 3.0.0 pypi_0 pypi colorama 0.4.6 pypi_0 pypi comm 0.2.2 pypi_0 pypi contourpy 1.2.1 pypi_0 pypi coverage 7.5.3 pypi_0 pypi cycler 0.12.1 pypi_0 pypi dask 2024.6.1 pypi_0 pypi debugpy 1.8.1 pypi_0 pypi decorator 5.1.1 pypi_0 pypi defusedxml 0.7.1 pypi_0 pypi distlib 0.3.8 pypi_0 pypi docstring-parser 0.16 pypi_0 pypi docutils 0.21.2 pypi_0 pypi exceptiongroup 1.2.1 pypi_0 pypi executing 2.0.1 pypi_0 pypi fasteners 0.19 pypi_0 pypi fastjsonschema 2.20.0 pypi_0 pypi filelock 3.15.3 pypi_0 pypi fire 0.6.0 pypi_0 pypi flexcache 0.3 pypi_0 pypi flexparser 0.3.1 pypi_0 pypi fonttools 4.53.0 pypi_0 pypi fqdn 1.5.1 pypi_0 pypi freetype-py 2.4.0 pypi_0 pypi fsspec 2024.6.0 pypi_0 pypi h11 0.14.0 pypi_0 pypi heapdict 1.0.1 pypi_0 pypi hsluv 5.0.4 pypi_0 pypi httpcore 1.0.5 pypi_0 pypi httpx 0.27.0 pypi_0 pypi humanize 4.9.0 pypi_0 pypi hypothesis 6.103.2 pypi_0 pypi identify 2.5.36 pypi_0 pypi idna 3.7 pypi_0 pypi imageio 2.34.1 pypi_0 pypi imagesize 1.4.1 pypi_0 pypi importlib-metadata 7.1.0 pypi_0 pypi in-n-out 0.2.1 pypi_0 pypi iniconfig 2.0.0 pypi_0 pypi ipykernel 6.29.4 pypi_0 pypi ipython 8.25.0 pypi_0 pypi isoduration 20.11.0 pypi_0 pypi jedi 0.19.1 pypi_0 pypi jinja2 3.1.4 pypi_0 pypi json5 0.9.25 pypi_0 pypi jsonpointer 3.0.0 pypi_0 pypi jsonschema 4.22.0 pypi_0 pypi jsonschema-specifications 2023.12.1 pypi_0 pypi jupyter-client 8.6.2 pypi_0 pypi jupyter-core 5.7.2 pypi_0 pypi jupyter-events 0.10.0 pypi_0 pypi jupyter-lsp 2.2.5 pypi_0 pypi jupyter-server 2.14.1 pypi_0 pypi jupyter-server-terminals 0.5.3 pypi_0 pypi jupyterlab 4.2.2 pypi_0 pypi jupyterlab-pygments 0.3.0 pypi_0 pypi jupyterlab-server 2.27.2 pypi_0 pypi kiwisolver 1.4.5 pypi_0 pypi lazy-loader 0.4 pypi_0 pypi libffi 3.4.2 h8ffe710_5 conda-forge libsqlite 3.46.0 h2466b09_0 conda-forge libzlib 1.3.1 h2466b09_1 conda-forge llvmlite 0.43.0 pypi_0 pypi locket 1.0.0 pypi_0 pypi lxml 5.2.2 pypi_0 pypi lxml-html-clean 0.1.1 pypi_0 pypi magicgui 0.8.3 pypi_0 pypi markdown-it-py 3.0.0 pypi_0 pypi markupsafe 2.1.5 pypi_0 pypi matplotlib 3.9.0 pypi_0 pypi matplotlib-inline 0.1.7 pypi_0 pypi mdurl 0.1.2 pypi_0 pypi mistune 3.0.2 pypi_0 pypi ml-dtypes 0.4.0 pypi_0 pypi mouseinfo 0.1.3 pypi_0 pypi napari 0.5.0a2.dev761+g1a5362af pypi_0 pypi napari-console 0.0.9 pypi_0 pypi napari-plugin-engine 0.2.0 pypi_0 pypi napari-plugin-manager 0.1.dev212+g4a9aa84 pypi_0 pypi napari-svg 0.1.10 pypi_0 pypi nbclient 0.10.0 pypi_0 pypi nbconvert 7.16.4 pypi_0 pypi nbformat 5.10.4 pypi_0 pypi nd2 0.10.1 pypi_0 pypi nest-asyncio 1.6.0 pypi_0 pypi networkx 3.3 pypi_0 pypi nodeenv 1.9.1 pypi_0 pypi notebook-shim 0.2.4 pypi_0 pypi npe2 0.7.5 pypi_0 pypi numba 0.60.0 pypi_0 pypi numcodecs 0.12.1 pypi_0 pypi numpy 1.26.4 pypi_0 pypi numpydoc 1.7.0 pypi_0 pypi ome-types 0.5.1.post1 pypi_0 pypi openssl 3.3.1 h2466b09_0 conda-forge overrides 7.7.0 pypi_0 pypi packaging 24.1 pypi_0 pypi pandas 2.2.2 pypi_0 pypi pandocfilters 1.5.1 pypi_0 pypi parso 0.8.4 pypi_0 pypi partd 1.4.2 pypi_0 pypi pillow 10.3.0 pypi_0 pypi pint 0.24 pypi_0 pypi pip 24.0 pyhd8ed1ab_0 conda-forge platformdirs 4.2.2 pypi_0 pypi pluggy 1.5.0 pypi_0 pypi pooch 1.8.2 pypi_0 pypi pre-commit 3.7.1 pypi_0 pypi pretend 1.0.9 pypi_0 pypi prometheus-client 0.20.0 pypi_0 pypi prompt-toolkit 3.0.47 pypi_0 pypi psutil 6.0.0 pypi_0 pypi psygnal 0.11.1 pypi_0 pypi pure-eval 0.2.2 pypi_0 pypi pyautogui 0.9.54 pypi_0 pypi pyconify 0.1.6 pypi_0 pypi pycparser 2.22 pypi_0 pypi pydantic 1.10.17 pypi_0 pypi pydantic-compat 0.1.2 pypi_0 pypi pydantic-core 2.18.4 pypi_0 pypi pygetwindow 0.0.9 pypi_0 pypi pygments 2.18.0 pypi_0 pypi pymsgbox 1.0.9 pypi_0 pypi pyopengl 3.1.7 pypi_0 pypi pyparsing 3.1.2 pypi_0 pypi pyperclip 1.9.0 pypi_0 pypi pyproject-hooks 1.1.0 pypi_0 pypi pyqt5 5.15.10 pypi_0 pypi pyqt5-qt5 5.15.2 pypi_0 pypi pyqt5-sip 12.13.0 pypi_0 pypi pyqt6 6.7.0 pypi_0 pypi pyqt6-qt6 6.7.2 pypi_0 pypi pyqt6-sip 13.6.0 pypi_0 pypi pyrect 0.2.0 pypi_0 pypi pyscreeze 0.1.30 pypi_0 pypi pytest 8.2.2 pypi_0 pypi pytest-pretty 1.2.0 pypi_0 pypi pytest-qt 4.4.0 pypi_0 pypi python 3.10.14 h4de0772_0_cpython conda-forge python-dateutil 2.9.0.post0 pypi_0 pypi python-json-logger 2.0.7 pypi_0 pypi pytweening 1.2.0 pypi_0 pypi pytz 2024.1 pypi_0 pypi pywin32 306 pypi_0 pypi pywinpty 2.0.13 pypi_0 pypi pyyaml 6.0.1 pypi_0 pypi pyzmq 26.0.3 pypi_0 pypi qtconsole 5.5.2 pypi_0 pypi qtpy 2.4.1 pypi_0 pypi referencing 0.35.1 pypi_0 pypi requests 2.32.3 pypi_0 pypi resource-backed-dask-array 0.1.0 pypi_0 pypi rfc3339-validator 0.1.4 pypi_0 pypi rfc3986-validator 0.1.1 pypi_0 pypi rich 13.7.1 pypi_0 pypi rpds-py 0.18.1 pypi_0 pypi ruff 0.4.9 pypi_0 pypi scikit-image 0.24.0 pypi_0 pypi scipy 1.13.1 pypi_0 pypi seaborn 0.13.2 pypi_0 pypi send2trash 1.8.3 pypi_0 pypi setuptools 70.1.0 pyhd8ed1ab_0 conda-forge shellingham 1.5.4 pypi_0 pypi six 1.16.0 pypi_0 pypi sniffio 1.3.1 pypi_0 pypi snowballstemmer 2.2.0 pypi_0 pypi sortedcontainers 2.4.0 pypi_0 pypi soupsieve 2.5 pypi_0 pypi sphinx 7.3.7 pypi_0 pypi sphinxcontrib-applehelp 1.0.8 pypi_0 pypi sphinxcontrib-devhelp 1.0.6 pypi_0 pypi sphinxcontrib-htmlhelp 2.0.5 pypi_0 pypi sphinxcontrib-jsmath 1.0.1 pypi_0 pypi sphinxcontrib-qthelp 1.0.7 pypi_0 pypi sphinxcontrib-serializinghtml 1.1.10 pypi_0 pypi stack-data 0.6.3 pypi_0 pypi superqt 0.6.7 pypi_0 pypi tabulate 0.9.0 pypi_0 pypi tensorstore 0.1.62 pypi_0 pypi termcolor 2.4.0 pypi_0 pypi terminado 0.18.1 pypi_0 pypi tifffile 2024.6.18 pypi_0 pypi tinycss2 1.3.0 pypi_0 pypi tk 8.6.13 h5226925_1 conda-forge tomli 2.0.1 pypi_0 pypi tomli-w 1.0.0 pypi_0 pypi toolz 0.12.1 pypi_0 pypi tornado 6.4.1 pypi_0 pypi tqdm 4.66.4 pypi_0 pypi traitlets 5.14.3 pypi_0 pypi typer 0.12.3 pypi_0 pypi types-python-dateutil 2.9.0.20240316 pypi_0 pypi typing-extensions 4.12.2 pypi_0 pypi tzdata 2024.1 pypi_0 pypi ucrt 10.0.22621.0 h57928b3_0 conda-forge uri-template 1.3.0 pypi_0 pypi urllib3 2.2.2 pypi_0 pypi vc 14.3 h8a93ad2_20 conda-forge vc14_runtime 14.40.33810 ha82c5b3_20 conda-forge virtualenv 20.26.2 pypi_0 pypi vispy 0.14.3 pypi_0 pypi vs2015_runtime 14.40.33810 h3bf8584_20 conda-forge wcwidth 0.2.13 pypi_0 pypi webcolors 24.6.0 pypi_0 pypi webencodings 0.5.1 pypi_0 pypi websocket-client 1.8.0 pypi_0 pypi wget 3.2 pypi_0 pypi wheel 0.43.0 pyhd8ed1ab_1 conda-forge wrapt 1.16.0 pypi_0 pypi xarray 2024.6.0 pypi_0 pypi xsdata 24.3.1 pypi_0 pypi xz 5.2.6 h8d14728_0 conda-forge zarr 2.18.2 pypi_0 pypi zarr-tools 0.4.5 pypi_0 pypi zenodo-get 1.6.1 pypi_0 pypi zipp 3.19.2 pypi_0 pypi ```
goanpeca commented 3 months ago

Indeed, I can now reporduce, I will add a timer to refresh the installed plugins list after a while, not sure why it does not get pikcedup immediately. The popup not showing inside the dialog, and it also being modal, sounds weird. Will check the position when showing it and perhaps make it not modal.

Thanks for the reviews @dalthviz @psobolewskiPhD

goanpeca commented 2 months ago

@dalthviz @psobolewskiPhD I think I found the culprit and should now be working as expected. Could you test again?


@dalthviz I added a fix to https://github.com/napari/napari-plugin-manager/issues/61 since this PR was already fixing part of what you reported. Could you check :) ?

Cheers!

dalthviz commented 2 months ago

Gave another check and seems like the installed plugin is now visible after the install finishes without having to click Refresh :+1: However, seems like now the popup after installation doesn't appear even after clicking Refresh?:

refresh_dialog

Also seems like this fixes #61 :+1: See https://github.com/napari/napari-plugin-manager/issues/61#issuecomment-2220784637

goanpeca commented 2 months ago

👍 However, seems like now the popup after installation doesn't appear even after clicking Refresh?:

What popup 🤔 ?

jaimergp commented 2 months ago

Probably the one discussed at https://github.com/napari/napari-plugin-manager/pull/68?

dalthviz commented 2 months ago

What popup 🤔 ?

Probably the one discussed at https://github.com/napari/napari-plugin-manager/pull/68?

Exactly! Checking this I see that when uninstalling a plugin the popup keeps appearing but when installing it doesn't appear anymore:

refresh_popup

goanpeca commented 2 months ago

@dalthviz I think there is a misunderstanding.

There is no way for us to know if a plugin is npe2 before installing and the code has only displayed the message when uninstalling because at that moment we actually know the type of plugin (npe2 in this case). There is a comment # TODO: NPE version unknown before installing and there are actually 2 places where the popup is displayed, so the code is duplicated and wonky


        # TODO: NPE version unknown before installing
        if item.npe_version != 1 and action_name == InstallerActions.UNINSTALL:
            # show warning pop up dialog
            message = trans._(
                'When installing/uninstalling npe2 plugins, you must '
                'restart napari for UI changes to take effect.'
            )
            self._warn_dialog = WarnPopup(text=message)

            delta_x = 75
            global_point = widget.action_button.mapToGlobal(
                widget.action_button.rect().topLeft()
            )
            global_point = QPoint(global_point.x() - delta_x, global_point.y())
            self._warn_dialog.move(global_point)

The other popup you were seeing in your PR "after install" was not really appearing after install, but it was appearing after refresh which was the previous behavior after a package was instaled, the lists refreshed completely. Also the check in the code was looking at any discovered npe2 plugins, and if they were indeed discovered, then the popup appeared in a global generic position next to the error indicator. That was the previous behavior.

The code in your PR https://github.com/napari/napari-plugin-manager/pull/68/files#diff-c4a932d5522a5a713957223899c8991682affd18d838b197d3c508ea32333a1eR921

I will change the popup to not be modal and unify under a single helper method.

goanpeca commented 2 months ago

@dalthviz I made changes could check again :) ?

goanpeca commented 2 months ago

I am not sute why the test are now failing for py3.11 on mac.

 SKIPPED [2] napari_plugin_manager/_tests/test_qt_plugin_dialog.py:480: pyside specific bug
  ================== 42 passed, 9 skipped, 4 warnings in 21.68s ==================

I do not see a fail or error on the test run :-\

jaimergp commented 2 months ago

I think we might need this constraint too:

pyside6_experimental = [
    "PySide6 < 6.5 ; python_version < '3.12'"
]
dalthviz commented 2 months ago

Gave another check to this and seems like now the uninstall pop up gets placed under the application window? I'm seeing this:

uninstall_popup

Seems like not closing the pop up prevents continuing with the uninstall action. Maybe that's way the pop up was being shown with modal properties? 🤔

dalthviz commented 2 months ago

I do not see a fail or error on the test run :-\

Just in case, although the tests are passing, when finishing seems like the process is segfaulting (exit 11 - https://github.com/napari/napari-plugin-manager/actions/runs/9904959061/job/27363858135?pr=45#step:7:3225). As mentioned above, constraining the PySide6 version could help :+1:

goanpeca commented 2 months ago

Thanks for the review @dalthviz pushing a fix

goanpeca commented 2 months ago

So it seems that the latest napari dev is using numpy 2 for py 3.11 and above and that is causing problems here. I added numpy<2 in the package dependencies just to check...and tests are not segfaulting anymore.

What do you think we should do @jaimergp ?

jaimergp commented 2 months ago

Hm, that's interesting. AFAIK we are not using numpy ourselves, are we? Maybe @Czaki or @jni know more about this tricky pyside x numpy interaction 😬

goanpeca commented 2 months ago

This message was appearing when running the tests

pytest -v --color=yes --cov=napari_plugin_manager --cov-report=xml [tox/tox_env/api.py:426]

  A module that was compiled using NumPy 1.x cannot be run in
  NumPy 2.0.0 as it may crash. To support both 1.x and 2.x
  versions of NumPy, modules must be compiled with NumPy 2.0.
  Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.

  If you are a user of the module, the easiest solution will be to
  downgrade to 'numpy<2' or try to upgrade the affected module.
  We expect that some modules will need time to support NumPy 2.
goanpeca commented 2 months ago

Created https://github.com/napari/napari-plugin-manager/issues/72 to track the problem, in the meantime this can be merged as soon as all tests pass!

Thanks everyone for your comments

psobolewskiPhD commented 2 months ago

Maybe we should use constraints files from napari/napari for the test env? Here's how it's used in napari/docs https://github.com/napari/docs/blob/9dabb9e6598d286851cd97abf12a9cb858f8b65b/.github/workflows/build_and_deploy.yml#L54-L59

psobolewskiPhD commented 2 months ago

I'd like to avoid the numpy <2 pin. I think the issue can be resolved with the PySide6 pin. napari/PySide6 is both experimental and rather broken, so I'd not have that be driving stuff like numpy version.

psobolewskiPhD commented 2 months ago

Here's the deny list, which include a lot of PySide6: https://github.com/napari/napari/blob/5e685a20c9563a42576ead39a4f0286337a52ce6/resources/constraints/version_denylist.txt#L3

goanpeca commented 2 months ago

Hi @psobolewskiPhD thanks for the info, let me push something with what you suggest to check.

However there is a problem with numpy>2 at the moment as displayed by the error message

psobolewskiPhD commented 2 months ago

Yeah, I saw that. But napari tests do pass with the constraints. So unless it's something specific the manager uses, I think the constraints should get this to pass too? Looked promising here: https://github.com/napari/napari-plugin-manager/pull/75

goanpeca commented 2 months ago

Since we are skipping tests for py3.9 on the github workflow anyway I only added

PySide6: PySide6 != 6.4.3, !=6.5.0, !=6.5.1, !=6.5.1.1, !=6.5.2, != 6.5.3, != 6.6.0, != 6.6.1, != 6.6.2 ; python_version >= '3.10' and python_version < '3.12'

Seems to be working fine now :) thanks for the help @psobolewskiPhD

Merging after tests pass, fingers crossed 🤞🏼

goanpeca commented 2 months ago

@dalthviz could you check that the modal pop on install and uninstall is working as expected. I think that was the only missing part (besides the pyside6 shenanigans)

dalthviz commented 2 months ago

Gave this another check and seems like now the popup for install and uninstall are being placed along side the item :+1:

imagen

However, using the action to show the dialog shows the following traceback:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~\anaconda3\envs\napari-dev\lib\site-packages\app_model\backends\qt\_qaction.py:55, in QCommandAction._on_triggered(self=QMenuItemAction(MenuItem(when=Expr.parse('True')...tle=None, toggled=None), alt=None), app='napari'), checked=False)
     51 def _on_triggered(self, checked: bool) -> None:
     52     # execute_command returns a Future, for the sake of eventually being
     53     # asynchronous without breaking the API.  For now, we call result()
     54     # to raise any exceptions.
---> 55     self._app.commands.execute_command(self._command_id).result()
        self._command_id = 'napari.window.plugins.plugin_install_dialog'
        self = QMenuItemAction(MenuItem(when=Expr.parse('True'), group='1_plugins', order=1.0, command=CommandRule(id='napari.window.plugins.plugin_install_dialog', title='Install/Uninstall Plugins...', category=None, tooltip=None, status_tip=None, icon=None, icon_visible_in_menu=True, enablement=None, short_title=None, toggled=None), alt=None), app='napari')
        self._app = Application('napari')

File ~\anaconda3\envs\napari-dev\lib\site-packages\app_model\registries\_commands_reg.py:245, in CommandsRegistry.execute_command(self=<CommandsRegistry at 0x1a952ccb910 (148 commands)>, id='napari.window.plugins.plugin_install_dialog', execute_asynchronously=False, *args=(), **kwargs={})
    241 except Exception as e:
    242     if self._raise_synchronous_exceptions:
    243         # note, the caller of this function can also achieve this by
    244         # calling `future.result()` on the returned future object.
--> 245         raise e
    246     future.set_exception(e)
    248 return future

File ~\anaconda3\envs\napari-dev\lib\site-packages\app_model\registries\_commands_reg.py:240, in CommandsRegistry.execute_command(self=<CommandsRegistry at 0x1a952ccb910 (148 commands)>, id='napari.window.plugins.plugin_install_dialog', execute_asynchronously=False, *args=(), **kwargs={})
    238 future: Future = Future()
    239 try:
--> 240     future.set_result(cmd(*args, **kwargs))
        future = <Future at 0x1a9626881f0 state=pending>
        cmd = <function _show_plugin_install_dialog at 0x000001A95DB9A170>
        args = ()
        kwargs = {}
    241 except Exception as e:
    242     if self._raise_synchronous_exceptions:
    243         # note, the caller of this function can also achieve this by
    244         # calling `future.result()` on the returned future object.

File ~\anaconda3\envs\napari-dev\lib\site-packages\in_n_out\_store.py:934, in Store.inject_processors.<locals>._deco.<locals>._exec(*args=(), **kwargs={})
    932 @wraps(func)
    933 def _exec(*args: P.args, **kwargs: P.kwargs) -> R:
--> 934     result = func(*args, **kwargs)
        func = <function _show_plugin_install_dialog at 0x000001A95DB9BD00>
        args = ()
        kwargs = {}
    935     if result is not None:
    936         self.process(
    937             result,
    938             type_hint=type_hint,
   (...)
    941             _funcname=getattr(func, "__qualname__", str(func)),
    942         )

File ~\anaconda3\envs\napari-dev\lib\site-packages\in_n_out\_store.py:804, in Store.inject.<locals>._inner.<locals>._exec(*args=(), **kwargs={})
    797 logger.debug(
    798     "  Calling %s with %r (injected %r)",
    799     _fname,
    800     bound.arguments,
    801     _injected_names,
    802 )
    803 try:
--> 804     result = func(**bound.arguments)
        bound = <BoundArguments (window=<napari._qt.qt_main_window.Window object at 0x000001A952D1E800>)>
        func = <function _show_plugin_install_dialog at 0x000001A95AD94280>
        bound.arguments = {'window': <napari._qt.qt_main_window.Window object at 0x000001A952D1E800>}
    805 except TypeError as e:
    806     if "missing" not in e.args[0]:

File E:\Acer\Documentos\Quansight\Napari\napari\napari\_qt\_qapp_model\qactions\_plugins.py:35, in _show_plugin_install_dialog(window=<napari._qt.qt_main_window.Window object>)
     30 # TODO: Once menu contributions supported, `napari_plugin_manager` should be
     31 # amended to be a napari plugin and simply add this menu item itself.
     32 # This callback is only used when this package is available, thus we do not check
     33 from napari_plugin_manager.qt_plugin_dialog import QtPluginDialog
---> 35 QtPluginDialog(window._qt_window).exec_()
        QtPluginDialog = <class 'napari_plugin_manager.qt_plugin_dialog.QtPluginDialog'>
        window._qt_window = <napari._qt.qt_main_window._QtMainWindow object at 0x000001A954209C60>
        window = <napari._qt.qt_main_window.Window object at 0x000001A952D1E800>

File E:\Acer\Documentos\Quansight\Napari\napari otros\gonzalo\napari-plugin-manager\napari_plugin_manager\qt_plugin_dialog.py:1326, in QtPluginDialog.exec_(self=<napari_plugin_manager.qt_plugin_dialog.QtPluginDialog object>)
   1323 plugin_dialog.setModal(True)
   1324 plugin_dialog.show()
-> 1326 if self._first_open:
        self = <napari_plugin_manager.qt_plugin_dialog.QtPluginDialog object at 0x000001A962694280>
   1327     stylesheet = get_current_stylesheet([STYLES_PATH])
   1328     self.setStyleSheet(stylesheet)

AttributeError: 'QtPluginDialog' object has no attribute '_first_open'
INFO: Plugin Manager: process completed

Maybe there is a need to initialize the _first_open attribute early?

dalthviz commented 2 months ago

Another thing I noticed now is that since is possible to close the plugin dialog with in progress tasks, you can end up showing the pop up after installation when the dialog is closed, so you can see something like:

plugin_install_uninstall_popup_dialog_closed

Checking, this behavior is also present with latest main, but maybe could be worthy to take care of that here too? Something like oviating the pop up logic in that case and instead just show with the napari notification the info about the need to restart napari for UI changes to take effect along side the process completed message? 🤔

goanpeca commented 2 months ago

Checking, this behavior is also present with latest main, but maybe could be worthy to take care of that here too? Something like oviating the pop up logic in that case and instead just show with the napari notification the info about the need to restart napari for UI changes to take effect along side the process completed message? 🤔

Great suggestion @dalthviz I had not thought about that but yes! Will push a fix


Also fixing the bug you found!

goanpeca commented 2 months ago

I think the errors are now fixed @dalthviz , next round :)

napari

dalthviz commented 2 months ago

Gave this another check and seems like things are working as expected 🎉

goanpeca commented 2 months ago

Merging! Thanks for the reviews