Skip to content

disconnect only slots that got connected#2923

Merged
j9ac9k merged 4 commits intopyqtgraph:masterfrom
pijyoi:fix-disconnect-unconnected
Feb 14, 2024
Merged

disconnect only slots that got connected#2923
j9ac9k merged 4 commits intopyqtgraph:masterfrom
pijyoi:fix-disconnect-unconnected

Conversation

@pijyoi
Copy link
Copy Markdown
Contributor

@pijyoi pijyoi commented Feb 1, 2024

PySide 6.7 will stop raising an exception when attempting to disconnect a slot that wasn't connected in the first place.
It will instead print out a warning.
See:
https://code.qt.io/cgit/pyside/pyside-setup.git/commit/?id=d7aa15abe25bd71ea19180743ce9b41e0b788520

This PR fixes:

  1. the many warnings printed due to GraphicsItem.
  2. https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/graphicsItems/ViewBox/ViewBox.py#L1780-L1795
    • this warning gets emitted on program exit

Remaining code that still cause warnings:

  1. https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/parametertree/interactive.py#L115-L118
    • this warning gets emitted in the test suite

PySide 6.7 will stop raising an exception when attempting to
disconnect a slot that wasn't connected in the first place.

It will instead print out a warning.
@pijyoi
Copy link
Copy Markdown
Contributor Author

pijyoi commented Feb 3, 2024

I don't understand the condition in the following code:
self.destroyed.connect(lambda: ViewBox.forgetView(sid, name) if (ViewBox is not None and 'sid' in locals() and 'name' in locals()) else None)
from https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/graphicsItems/ViewBox/ViewBox.py#L284-L288
and explicitly added in e5f383f

Based on my testing script below, the expression 'sid' in locals() and 'name' in locals() is always True, since they are referenced in the expression ViewBox.forgetView(sid, name)

def func_indirect(x):
    return x

def func1(x):
    # "'x' in locals" is True 
    return lambda : func_indirect(x) if 'x' in locals() else None

def func2(x):
    y = 2 * x
    # "'y' in locals" is False
    return lambda : func_indirect(x) if 'y' in locals() else None

print(func1(1)())   # 1
print(func2(2)())   # None

@samtygier
Copy link
Copy Markdown
Contributor

I got interested in what was happening with locals() in the lambda. I agree, looks like it must always be true. I wondered if there had been a change in python since that was written, but see the same output for your test in python 2.7 and 3.2.

@pijyoi
Copy link
Copy Markdown
Contributor Author

pijyoi commented Feb 10, 2024

While trying to fix interactive.py to not trigger warnings on PySide 6.7, I am not sure if I have stumbled onto a bug. The 3rd commit in this PR does a check for connections before attempting to disconnect; and this does manage to prevent some of the warnings.

However, despite this check, there are still 2 failures to disconnect of sigValueChanged.
These failures are actually present in all bindings.
i.e. previously, these real failures were just being ignored

UPDATE: So there isn't any bug. The issue with my failed attempt is that knowing that a signal has slot(s) connected is not a sufficient condition for ascertaining whether a particular slot is connected.
For this case, sigValueChanged is already connected elsewhere which makes the receivers() count always positive.

@pijyoi pijyoi force-pushed the fix-disconnect-unconnected branch from 12982a2 to b04085e Compare February 11, 2024 02:37
@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Feb 14, 2024

Thanks @pijyoi Always nice when we can address an issue before the upstream library makes a change. Appreciate your effort to look ahead and mitigate issues per-emptively.

@j9ac9k j9ac9k merged commit abecfb9 into pyqtgraph:master Feb 14, 2024
@pijyoi pijyoi deleted the fix-disconnect-unconnected branch February 14, 2024 11:39
@campagnola
Copy link
Copy Markdown
Member

campagnola commented Mar 13, 2024

I don't understand the condition in the following code: self.destroyed.connect(lambda: ViewBox.forgetView(sid, name) if (ViewBox is not None and 'sid' in locals() and 'name' in locals()) else None) from https://github.com/pyqtgraph/pyqtgraph/blob/master/pyqtgraph/graphicsItems/ViewBox/ViewBox.py#L284-L288 and explicitly added in e5f383f

Based on my testing script below, the expression 'sid' in locals() and 'name' in locals() is always True, since they are referenced in the expression ViewBox.forgetView(sid, name)

Sorry for the late reply @pijyoi ! The reason for this code is that the callback can be invoked during python teardown (in which case some of these locals may already have been deleted). I think this just avoids error messages that would appear on exit, but it's also possible that it prevented segmentation faults at exit, which were common at the time this was written.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants