TypeError: one() takes 1 positional argument but 2 were given - matplotlib

PyCharm return "TypeError: one() takes 1 positional argument but 2 were given"
I've searched for the whole night but still can't figure it out T T
I think the bug is from mpl_connect(), because when I use the connect() from pyqtBoundSignal it works
"""test.py"""
class forTest(QWidget):
signalTest = pyqtSignal()
def __init__(self):
super(forTest, self).__init__()
canvas = FigureCanvas(figure(facecolor="blue"))
# I got the following from other answer, but still not working
self.cid = canvas.mpl_connect('button_press_event', self.one)
layout = QHBoxLayout()
self.setLayout(layout)
layout.addWidget(canvas)
def one(self):
self.signalTest.emit()
print("emit()")
"""receice.py"""
class RTest(object):
def handle_signal(self):
print("get successfully")
"""main.py"""
if __name__ == "__main__":
app = QApplication(sys.argv)
tt = forTest()
rr = RTest()
tt.signalTest.connect(rr.handle_signal)
tt.show()
sys.exit(app.exec_())

From the mpl_connect() documentation:
func : callable
The callback function to be executed, which must have the signature:
def func(event: Event) -> Any
So, one() must have a further argument:
def one(self, event):
self.signalTest.emit()
print("emit()")
The reason for which the direct signal connection works is that PyQt is able to discard positional arguments when they exceed the connected signal (or function) argument count.

Related

pytest-qt waitSignal for long running computation running in a thread pool

I have successfully implemented a Python Qt app based off this very nice tutorial.
I am now writing tests using pytest-qt to specifically test a button that triggers a long running computation that eventually emits a signal when finished. I would like to use waitSignal as documented here.
def test_long_computation(qtbot):
app = Application()
# Watch for the app.worker.finished signal, then start the worker.
with qtbot.waitSignal(app.worker.finished, timeout=10000) as blocker:
blocker.connect(app.worker.failed) # Can add other signals to blocker
app.worker.start()
# Test will block at this point until either the "finished" or the
# "failed" signal is emitted. If 10 seconds passed without a signal,
# TimeoutError will be raised.
assert_application_results(app)
When the button is clicked, this function is executed:
def on_button_click_function(self):
"""
start thread pool to run function
"""
# Pass the function to execute
worker = Worker(self.execute_check_urls)
worker.signals.result.connect(self.print_output) # type: ignore
worker.signals.finished.connect(self.thread_complete) # type: ignore
worker.signals.progress.connect(self.progress_fn) # type: ignore
# Execute
log_info("Starting thread pool worker ...")
self.threadpool.start(worker).
And when the thread completes, a signal is emitted
def thread_complete(self):
main_window = self.find_main_window()
if main_window:
main_window.button_click_signal.emit(
self.results
)
log_info(
f"Emitted signal for button click function: {self.results}"
)
Below is the init function of the main class:
class MyClass:
def __init__(
self,
*args,
**kwargs
):
super(MyClass, self).__init__(*args, **kwargs)
self.threadpool = QThreadPool()
print(
"Multithreading with max %d threads"
% self.threadpool.maxThreadCount()
).
And the worker class which is QRunnable:
def __init__(
self,
fn,
*args,
**kwargs
):
super(Worker, self).__init__()
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
self.kwargs['progress_callback'] = self.signals.progress
#Slot()
def run(self):
try:
result = self.fn(*self.args, **self.kwargs)
except (Exception):
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit(
(exctype, value, traceback.format_exc())
)
else:
self.signals.result.emit(result)
finally:
self.signals.finished.emit().
I would appreciate some guidance on how to access the worker object from the threadpool. I also tested qtbot.mouseClick() which triggers the function but never emits the signal.

Numpy use dispatcher for argument displacement

This question is specific to NEP 18, which proposes a dispatch mechanism for using an arbitrary functions together with classes that implement the __array_function__ interface (such as np.ndarray).
def _einsum_dispatcher(subscripts, *operands):
return (*operands,), dict(subscripts=subscripts)
#np.core.overrides.array_function_dispatch(_einsum_dispatcher, verify=False)
def my_einsum(*operands, **subscripts):
raise RuntimeError("This should currently never happen")
class ArrayLike:
def __array_function__(self, func, types, args, kwargs):
return f"""
func = {func},
types = {types},
args = {args},
kwargs = {kwargs}
"""
Running a test for my_einsum we get
a = ArrayLike()
print(my_einsum('...', a))
Output:
RuntimeError: This should currently never happen
The function never gets intercepted by __array_function__ method for ArrayLike. Although, this can be solved by changing the dispatcher a bit:
def _einsum_dispatcher(subscripts, *operands):
return (*operands,)
Now when testing my_einsum the exact same way again:
a = ArrayLike()
print(my_einsum('...', a))
Output:
func = <function my_einsum at 0x7efded61bd30>,
types = (<class '__main__.ArrayLike'>,),
args = ('...', <__main__.ArrayLike object at 0x7efdef83efa0>),
kwargs = {}
The function is correct, but how do I move the subscripts argument into kwargs ? Can the array_function_dispatch only be used to dispatch argument types?

Python multiprocessing how to update a complex object in a manager list without using .join() method

I started programming in Python about 2 months ago and I've been struggling with this problem in the last 2 weeks.
I know there are many similar threads to this one but I can't really find a solution which suits my case.
I need to have the main process which is the one which interacts with Telegram and another process, buffer, which understands the complex object received from the main and updates it.
I'd like to do this in a simpler and smoother way.
At the moment objects are not being updated due to the use of multi-processing without the join() method.
I tried then to use multi-threading instead but it gives me compatibility problems with Pyrogram a framework which i am using to interact with Telegram.
I wrote again the "complexity" of my project in order to reproduce the same error I am getting and in order to get and give the best help possible from and for everyone.
a.py
class A():
def __init__(self, length = -1, height = -1):
self.length = length
self.height = height
b.py
from a import A
class B(A):
def __init__(self, length = -1, height = -1, width = -1):
super().__init__(length = -1, height = -1)
self.length = length
self.height = height
self.width = width
def setHeight(self, value):
self.height = value
c.py
class C():
def __init__(self, a, x = 0, y = 0):
self.a = a
self.x = x
self.y = y
def func1(self):
if self.x < 7:
self.x = 7
d.py
from c import C
class D(C):
def __init__(self, a, x = 0, y = 0, z = 0):
super().__init__(a, x = 0, y = 0)
self.a = a
self.x = x
self.y = y
self.z = z
def func2(self):
self.func1()
main.py
from b import B
from d import D
from multiprocessing import Process, Manager
from buffer import buffer
if __name__ == "__main__":
manager = Manager()
lizt = manager.list()
buffer = Process(target = buffer, args = (lizt, )) #passing the list as a parameter
buffer.start()
#can't invoke buffer.join() here because I need the below code to keep running while the buffer process takes a few minutes to end an instance passed in the list
#hence I can't wait the join() function to update the objects inside the buffer but i need objects updated in order to pop them out from the list
import datetime as dt
t = dt.datetime.now()
#library of kind of multithreading (pool of 4 processes), uses asyncio lib
#this while was put to reproduce the same error I am getting
while True:
if t + dt.timedelta(seconds = 10) < dt.datetime.now():
lizt.append(D(B(5, 5, 5)))
t = dt.datetime.now()
"""
#This is the code which looks like the one in my project
#main.py
from pyrogram import Client #library of kind of multithreading (pool of 4 processes), uses asyncio lib
from b import B
from d import D
from multiprocessing import Process, Manager
from buffer import buffer
if __name__ == "__main__":
api_id = 1234567
api_hash = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
app = Client("my_account", api_id, api_hash)
manager = Manager()
lizt = manager.list()
buffer = Process(target = buffer, args = (lizt, )) #passing the list as a parameter
buffer.start()
#can't invoke buffer.join() here because I need the below code to run at the same time as the buffer process
#hence I can't wait the join() function to update the objects inside the buffer
#app.on_message()
def my_handler(client, message):
lizt.append(complex_object_conatining_message)
"""
buffer.py
def buffer(buffer):
print("buffer was defined")
while True:
if len(buffer) > 0:
print(buffer[0].x) #prints 0
buffer[0].func2() #this changes the class attribute locally in the class instance but not in here
print(buffer[0].x) #prints 0, but I'd like it to be 7
print(buffer[0].a.height) #prints 5
buffer[0].a.setHeight(10) #and this has the same behaviour
print(buffer[0].a.height) #prints 5 but I'd like it to be 10
buffer.pop(0)
This is the whole code about the problem I am having.
Literally every suggestion is welcome, hopefully constructive, thank you in advance!
At last I had to change the way to solve this problem, which was using asyncio like the framework was doing as well.
This solution offers everything I was looking for:
-complex objects update
-avoiding the problems of multiprocessing (in particular with join())
It is also:
-lightweight: before I had 2 python processes 1) about 40K 2) about 75K
This actual process is about 30K (and it's also faster and cleaner)
Here's the solution, I hope it will be useful for someone else like it was for me:
The part of the classes is skipped because this solution updates complex objects absolutely fine
main.py
from pyrogram import Client
import asyncio
import time
def cancel_tasks():
#get all task in current loop
tasks = asyncio.Task.all_tasks()
for t in tasks:
t.cancel()
try:
buffer = []
firstWorker(buffer) #this one is the old buffer.py file and function
#the missing loop and loop method are explained in the next piece of code
except KeyboardInterrupt:
print("")
finally:
print("Closing Loop")
cancel_tasks()
firstWorker.py
import asyncio
def firstWorker(buffer):
print("First Worker Executed")
api_id = 1234567
api_hash = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
app = Client("my_account", api_id, api_hash)
#app.on_message()
async def my_handler(client, message):
print("Message Arrived")
buffer.append(complex_object_conatining_message)
await asyncio.sleep(1)
app.run(secondWorker(buffer)) #here is the trick: I changed the
#method run() of the Client class
#inside the Pyrogram framework
#since it was a loop itself.
#In this way I added another task
#to the existing loop in orther to
#let run both of them together.
my secondWorker.py
import asyncio
async def secondWorker(buffer):
while True:
if len(buffer) > 0:
print(buffer.pop(0))
await asyncio.sleep(1)
The resources to understand the asyncio used in this code can be found here:
Asyncio simple tutorial
Python Asyncio Official Documentation
This tutorial about how to fix classical Asyncio errors

pygame - python getting variables with the visiter pattern

I'm trying to use the visiter pattern to get self.coin value from the first class and return it to the method in the second class but its not working, its always returning none... can anyone help?
class coin_collector(Observer):
def __init__(self):
super(Observer, self).__init__()
self.coin_count = 0
self.run = True
self.coin = 0
def acceptVisitor(self, visitor):
visitor.visit(self)
def update(self, observable, other):
me = coin_collector()
me.coin_Count(other, True)
def coin_Count(self, value, TF):
run = TF
if run:
self.coin = value
print self.coin
return self.coin
def __str__(self):
return self.__class__.__name__
#this is part of a different class in a different file
def visit(self, location):
location.coin_Count(0, False)
def update(self):
visitee = coin_collector()
self.c_Count = self.visit(visitee) # for some reason this always returns none
print self.c_Count, "working" # this always prints none...
Ok, so let's start with Coin Collector. His coin attribute is set to 0.
You also have a second class with an update and visit function.
The update function creates a new coin_collector at every call. Then it assigns the return value of visit function to self.c_Count. Let's now see the visit function.
It takes in a brand new coin collector and returns None It would assign its value parameter to the coin field if you would pass True as TF.
After coming back from coin_count function, you do not do anything in the visit function so the return value is lost. That is why, when you try to assign the result of self.visit, you get a None.

Python: Anything wrong with dynamically assigning instance methods as instance attributes

I came up with the following code to decorate instance methods using a decorator that requires the instance itself as an argument:
from functools import wraps
def logging_decorator(tricky_instance):
def wrapper(fn):
#wraps(fn)
def wrapped(*a, **kw):
if tricky_instance.log:
print("Calling %s.." % fn.__name__)
return fn(*a, **kw)
return wrapped
return wrapper
class Tricky(object):
def __init__(self, log):
self.log = log
self.say_hi = logging_decorator(self)(self.say_hi)
def say_hi(self):
print("Hello, world!")
i1 = Tricky(log=True)
i2 = Tricky(log=False)
i1.say_hi()
i2.say_hi()
This seems to work great, but I fear that I may have overlooked some unintended side effects of this trick. Am I about to shoot myself in the foot, or is this safe?
Note that I don't actually want to use this for logging, it's just the shortest meaningful example I could come up with.
It's not really clear to me why you would ever want to do this. If you want to assign a new method type dynamically use types:
import types
class Tricky(object):
def __init__(self):
def method(self):
print('Hello')
self.method = types.MethodType(method, self)
If you want to do something with the instance, do it in the __init__ method. If you just want access to the method's instance inside the decorator, you can use the im_self attribute:
def decorator(tricky_instance):
def wrapper(meth):
print(meth.im_self == tricky_instance)
return meth
return wrapper
Personally, I think this is veering into Maybe-I-Shouldn't-Use-Decorators land.
I think I was trying to be needlessly smart. There seems to be an embarrassingly simpler solution:
from functools import wraps
def logging_decorator(fn):
#wraps(fn)
def wrapped(self, *a, **kw):
if self.log:
print("Calling %s.." % fn.__name__)
return fn(self, *a, **kw)
return wrapped
class Tricky(object):
def __init__(self, log):
self.log = log
#logging_decorator
def say_hi(self):
print("Hello, world!")
i1 = Tricky(log=True)
i2 = Tricky(log=False)
i1.say_hi()
i2.say_hi()