#pyqt | Logs for 2020-06-09
Back
[01:43:18] -!- bomex has joined #pyqt
[01:43:28] <bomex> hello
[01:50:41] <bomex> please review my code: https://pastebin.com
[01:50:50] -!- yustin has joined #pyqt
[01:51:48] <bomex> have I missed any PyQt's conventions?
[02:12:29] -!- Belxjander has quit [Quit: AmigaOSv4.1.6+//PowerPC native]
[02:13:04] -!- Belxjander has joined #pyqt
[02:14:28] -!- bomex has quit [Remote host closed the connection]
[02:40:06] -!- mjacob has joined #pyqt
[02:49:27] <mjacob> i'm running into an issue where pyqt5 calls the python memory allocator without holding the GIL: https://bugs.archlinux.org
[02:49:56] <mjacob> PyQt5 version is 5.15.0
[02:50:23] <mjacob> do_emit (stack frame #24) releases the GIL
[03:22:35] -!- jmarsac has joined #pyqt
[03:29:13] -!- yustin has quit [Remote host closed the connection]
[03:31:17] -!- yustin has joined #pyqt
[04:05:49] -!- frispete has quit [Ping timeout: 265 seconds]
[04:10:21] -!- frispete has joined #pyqt
[04:45:27] -!- Belxjander has quit [Quit: AmigaOSv4.1.6+//PowerPC native]
[04:46:01] -!- Belxjander has joined #pyqt
[04:51:20] <The-Compiler> mjacob: you probably should report this to the mailinglist
[04:51:34] <The-Compiler> (ideally, with a standalone reproducer)
[04:52:12] <mjacob> The-Compiler: yeah, i'm currently trying to produce one
[04:53:25] <mjacob> The-Compiler: i think i found the reason why it crashes, though. qpycore_qobject_qt_metacall() lost SIP_BLOCK_THREADS / SIP_UNBLOCK_THREADS from 5.14.2 to 5.15.0
[04:53:54] <mjacob> in between where these were before, it crashes
[04:54:13] <mjacob> i still need a reproducer...
[04:58:22] <The-Compiler> mjacob: maybe that observation and the stacktrace is enough :)
[05:02:46] <mjacob> is there a source repository for pyqt?
[05:06:15] -!- Belxjander has quit [Quit: AmigaOSv4.1.6+//PowerPC native]
[05:06:53] -!- Belxjander has joined #pyqt
[05:07:22] -!- frispete has quit [Remote host closed the connection]
[05:08:05] -!- frispete has joined #pyqt
[05:10:41] -!- jmarsac_ has joined #pyqt
[05:14:25] -!- jmarsac has quit [Ping timeout: 272 seconds]
[05:16:01] -!- ntome has joined #pyqt
[05:16:09] <ntome> what is https://pypi.org exactly?
[05:16:31] <ntome> the description is way too light, i don't understand what it does
[05:46:48] <The-Compiler> mjacob: nope, no repo
[05:47:43] <The-Compiler> ntome: it's used to build PyQt - I think I (roughly) understand what it does, but I can't really say more than what the description says
[05:48:58] <ntome> ok so it's not for building .ui files from within a setup.py/cfg?
[05:49:53] <The-Compiler> ntome: nope, it's the glue between SIP (C++ bindings generator) and Qt (with qmake and its build system), so you need it to build PyQt from source, or to build custom C++ extensions for PyQt projects
[05:56:37] -!- frispete has quit [Ping timeout: 264 seconds]
[05:59:50] -!- frispete has joined #pyqt
[06:41:05] -!- ali1234 has joined #pyqt
[06:41:39] <ali1234> why doesn't this work? https://bpa.st
[06:41:55] <ali1234> i expect it to print "value changed" whenever i assign to a.val
[06:42:01] <ali1234> however, it does not
[06:43:25] <ali1234> it also does not produce any error messages
[06:44:49] <ali1234> the property itself works. i can assign to it and read it back correctly, and when passing the object to QML the property is available and works correctly
[06:47:13] <Avaris> ali1234: you need an event loop (QApplication)
[06:47:29] <ali1234> i have one in the full code. it still doesnt work
[06:53:10] <ali1234> if i emit the signal manually then it works
[06:54:23] <Avaris> hmm, i thought you didn't need to emit it
[06:54:46] <ali1234> me too
[06:55:13] <ali1234> hmm
[06:56:27] <ali1234> i think what happens is that the notify=sender bit on the decorator just means "if you want to know when the property changes, connect to this signal"
[06:56:46] <ali1234> it doesn't actually cause the signal to be emitted when the setter is called
[06:57:18] <ali1234> emitting the signal manually causes my QML model and view to update automatically without having to manually connect anything like i am in the example above
[06:58:22] <Avaris> seems like if you define setter, you need to emit that. without setter, qt emits for you
[07:00:29] <ali1234> if i dont define the setter it says the property is not writable
[07:02:31] <Avaris> yeah on python side you need that
[07:17:10] -!- bomex has joined #pyqt
[07:17:27] <bomex> hello
[07:18:32] <bomex> my app using QThread crashed my app at a random time for no reason
[07:19:03] <bomex> is it possible to mix Python's threading API with PyQt5?
[07:22:08] <bomex> correction: my app using QThread, QObject, .moveToThread, and signal&slot mechanism, is crashing at random time and for no apparent reason
[07:22:14] <bomex> is it possible to mix Python's threading API with PyQt5?
[07:22:22] <bomex> I hate QThread !
[07:22:59] <Avaris> i doubt switching to python threading will magically fix your crash
[07:24:13] <bomex> Avaris: please look at my code and see if you can find any apparent mistakes in it: https://pastebin.com
[07:24:47] <bomex> apparent=obvious
[07:26:16] <The-Compiler> bomex: you'd better debug those crashes and see what's causing them rather than replacing QThread which might be pointless
[07:26:29] <Avaris> you seem to start thread stuff before starting the thread
[07:26:43] <Avaris> use thread.started signal to initiate stuff
[07:26:48] <The-Compiler> bomex: start with using Python's faulthandler module, and if it's in the Qt mainloop, run everything under gdb (and perhaps build those libraries with debugging symbols)
[07:29:37] <bomex> Avaris: is my custom signal 'started' somehow overriding QThread's 'started' signal? (if QThread even has such a signal)
[07:30:02] <Avaris> https://doc.qt.io
[07:30:51] <Avaris> but no... you start thread process in lines 53 and 54, but thread starts afterwards
[07:31:09] <bomex> I am emitting my own 'started' signal, probably a mistake
[07:31:29] <Avaris> lines 53 and 54 should be `self.background_process.started.connect(self.engine.start_stockfish)`
[07:34:23] -!- jmarsac_ has quit [Ping timeout: 272 seconds]
[07:37:08] <bomex> so like this: https://pastebin.com
[07:37:50] <Avaris> yes
[07:38:02] <bomex> the 'started' signal from QObject was removed, and emitting the 'started' signal was also removed (this is done automatically by QThread)
[07:38:09] <bomex> is that correct?
[07:38:22] <bomex> the automatically part
[07:38:52] <Avaris> thread.start() will emit thread.started signal... i am unsure what automatically means there
[07:40:04] <bomex> yeah, the signal 'started' is emitted by the start() function of the QThread instance
[07:40:34] <bomex> got it
[07:41:36] <bomex> but how can I now properly destroy/kill/shut-down the thread when the application quits?
[07:42:21] <Avaris> i use closeEvent of main window for that
[07:43:16] <bomex> I see
[07:44:20] <bomex> so there are no other steps to be taken care of when quitting the application?
[07:46:07] <bomex> just normal closeEvent.accept() if the user clicks the Yes button and closeEvent.ignore() otherwise?
[07:46:17] <bomex> nothing fancier?
[07:46:55] <Avaris> i'd suggest quit/terminating threads as well. usually, you run into `crash-on-exit` kind of stuff otherwise
[07:48:24] <bomex> so like: self.background_process.finished.connect(self.engine.deleteLater) ???
[07:49:01] <Avaris> calling .quit() on thread
[07:49:34] <bomex> ah!
[07:50:53] <bomex> is that all?
[07:51:20] <bomex> what about terminating the long-running process in the QObject?
[07:53:06] <bomex> will QThread's quit() function handle all the necessary steps to ensure a proper quitting of the app with a return code of 0?
[07:55:42] <bomex> I tried your approach and when I quitted the app, I got this: [Finished in 15.6s with exit code -6]
[07:56:18] <Avaris> no, you need to handle that if required
[07:59:12] <bomex> so like quit the engine process first and then quit the thread and after that accept the close event
[07:59:13] <bomex> ???
[08:00:32] <Avaris> probably
[08:02:17] <bomex> is it also possible I pause my long running thread and then resume it?
[08:03:57] <bomex> is there anything as QThread.wait() and QThread.resume() ??
[08:03:58] -!- jmarsac_ has joined #pyqt
[08:05:48] <Avaris> no. you can't pause threads at arbitrary time. you can implement your process running in the thread to have "pause/resume" states
[08:06:29] <bomex> I see
[08:06:54] <bomex> and how would I achieve that?
[08:06:58] <bomex> any pointers?
[08:07:45] <Avaris> first, *why* do you want that?
[08:10:39] <bomex> because when I scroll up with my mouse wheel, I shuffle between the chess moves in the move stack... during that shuffling, I want the engine to be paused... but if a new move is made by the user, I want the engine to resume thinking about its next move
[08:11:26] <bomex> look at my code again
[08:11:45] <Avaris> ... huh? does the engine continiously spit out moves if you don't do anything?
[08:12:27] <bomex> well, the engine spits out moves if it is its turn
[08:12:56] <bomex> currently, I have hardcoded the engine to always play with the black pieces
[08:13:02] <Avaris> so, when you shuffle and it's not its turn it ... pauses?
[08:13:17] <bomex> yes
[08:13:35] <bomex> because an 'if' statement blocks it from makinf a move
[08:13:44] <bomex> *making
[08:13:46] <Avaris> then what's the problem? you already have pause/resume in the engine
[08:13:58] <bomex> not really
[08:14:53] <bomex> I want it to not play if I shuffle to a move where there's black player's turn
[08:16:10] <bomex> if the engine player is black, whenever there's Black's turn, the engine spits out a move
[08:17:11] <bomex> so if I shuffle moves back and stop to where's Black's turn, the engine just spits out a move... and I don't want that
[08:17:12] <Avaris> based on that code, move generation happens with `invoked` signal and you control when it's emitted
[08:17:31] <bomex> yes
[08:17:44] <Avaris> so... don't invoke when you don't want engine to make a move
[08:18:06] <bomex> but how can I suppress this signal when I shuffle moves back?
[08:18:33] <bomex> the problem is that the signal is invoked in the display_chessboard function
[08:18:39] <Avaris> suppress? it's not an automated signal. you emit it. if you don't want to emit it then don't emit it
[08:19:21] <bomex> the function display_chessboard must be called or there's nothing redrawn on my chessboard
[08:19:58] <Avaris> you can change code, right?
[08:20:27] <bomex> if I invoke the signal in the mousePressEvent, then I must click on the chessboard so that the engine makes a move
[08:21:04] <bomex> maybe signal.disconnect()
[08:21:05] <bomex> ??
[08:21:19] <bomex> and then after a human move, reconnect the signal?
[08:21:54] <bomex> where would you emit this 'invoked' signal?
[08:22:09] <Avaris> define a flag or something. `if computer_turn and please_make_a_move: calculate_move()` i don't know... i'm not writing this code. it's for you to decide how to implement that
[08:22:52] <bomex> I see
[08:23:10] <bomex> you're right
[08:23:16] <bomex> lemme get hackin'
[09:05:00] <ali1234> looks like it is impossible to make an automatic property
[09:06:13] <altendky> ali1234: what is an automatic property?
[09:06:37] <ali1234> a class which creates a property on a QObject, and automatically creates the change signals
[09:06:59] <ali1234> so you can just say foo = MyProperty(str, 'default value')
[09:07:10] <ali1234> and fooChanged is created automatically
[09:07:39] <altendky> ali1234: i've definitely got some stuff at least in that direction, though it's messy and i haven't looked at it for a few years (despite it being used in my daily code). just a sec
[09:08:49] <altendky> not really it, but sometimes (usually?) you don't want to inherit from qobject just to have a signal... https://github.com
[09:09:22] <altendky> maybe actually related to what you want. https://github.com
[09:09:56] <ali1234> i dont understand that :)
[09:10:01] <ali1234> this is what i want: https://bpa.st
[09:10:27] <ali1234> you could perhaps describe it as "attrs for Qt Properties"
[09:10:37] <altendky> ali1234: in my case i wanted to write attrs-based classes that could be used as the definition of a qt model. so, they needed to have properties instead of attributes so that changes could be sent to the model.
[09:10:45] <ali1234> lines 8 to 19 are pointless boilerplate
[09:10:51] <altendky> maybe mine is 'attrs _as_ qt properties'
[09:11:08] <ali1234> right that is exactly what i want too
[09:11:12] <altendky> some examples https://github.com
[09:11:51] <ali1234> i dont understand what this example shows... class P?
[09:12:04] <ali1234> it defines getters and setters which is what i am trying to avoid doing
[09:12:05] <altendky> ali1234: i'll say that i want to revisit and rework this, but as mentioned it's the class/model heart of code i've been working on for a few years so i guess it says _something_ that i haven't spent a lot of time on it since i wrote it. even if it doesn't say that it's great
[09:12:19] <altendky> ali1234: you are allowed to override. it only overrides for c, not a or b
[09:12:49] <ali1234> but i don't want to override
[09:13:04] <altendky> ali1234: so don't use that feature... just like that example P doesn't use it for a or b
[09:13:33] <ali1234> i tried to implement it in two different ways, and neither worked: https://bpa.st
[09:13:36] <altendky> ali1234: but anyways, if nothing else it shows it is possible in some way and you can look at the implementation and figure out if you want to do it that way or use the 'how' and do it a bit differently.
[09:13:54] <ali1234> i dont understand why the second one doesn't work
[09:14:08] <ali1234> i do understand why the first one doesn't work
[09:14:43] <ali1234> i mean, the first one kind of does work, but it relies on the signal being created outside, in the class definition, so fails to fulfil the requirements
[09:15:21] <altendky> ali1234: if you ignore the overriding of the getter/setter for `.c`, what about `P` looks like not what you want?
[09:15:24] <ali1234> i suspect that the first one doesn't work because __set_name__ never gets run on the signal object
[09:15:59] <ali1234> i don't understand P
[09:16:27] <ali1234> if you just had lines 13 to 18, would that work?
[09:16:29] <altendky> ali1234: it's a class. it has `.a`, `.b.`, and `.c`. they become pyqtProperties...
[09:16:50] <altendky> ali1234: you need the super().__init__() but otherwise it should
[09:17:11] <ali1234> hmm
[09:17:18] <ali1234> then it is what i want
[09:17:24] <altendky> as i said, overriding is optional. just as using the socket module from python is optional and despite not wanting to use it we still use python
[09:18:28] <altendky> so one point is that you can't add a signal to a class. it must be there when the class is created. the metaclass used by QObject requires that.
[09:18:44] <ali1234> i see
[09:18:50] <altendky> yay metaclasses
[09:19:12] <ali1234> that would pretty much defeat anything i could come up with
[09:19:33] <altendky> but you'll note on the Signal class i made that let's you have signals on not-QObject's that you can create other holders for the signals
[09:19:44] <altendky> then give access to them from the man object
[09:19:51] <ali1234> i dont need that
[09:20:06] -!- Belxjander has quit [Quit: AmigaOSv4.1.6+//PowerPC native]
[09:20:07] <altendky> it's nice to avoid inheritance and a metaclass though.
[09:20:15] <ali1234> i just want to make properties without have to write 10 lines of boilerplate for each one
[09:20:34] <altendky> also, i thought i used three-arg type() to create a new class to add the properties... but i'm not seeing that at the moment
[09:20:41] -!- Belxjander has joined #pyqt
[09:20:42] -!- cottoneyejim has joined #pyqt
[09:21:14] <altendky> maybe i can review this later myself to help explain it.
[09:21:29] <altendky> but look through the tests to see how it can be used
[09:21:59] <ali1234> how would i even install this?
[09:22:13] -!- gour has joined #pyqt
[09:22:32] <altendky> ali1234: it's on pypi as epyqlib
[09:23:30] <altendky> ali1234: note that i'm not super recommending you use this directly, but i think it contains pieces that could be part of your answer. or, use it directly... all the models in github.com/altendky/pm are built around this.
[09:23:45] -!- BPL has joined #pyqt
[09:28:21] <altendky> i would like to get a tidy lib that isn't just the mess behind the applications i've written, but this isn't it. that's still a maybe someday wish.
[09:47:23] <bomex> altendky
[09:48:06] <bomex> in my code, should I pass a parent to QThread?
[09:49:06] <bomex> like self.background_process = QThread(parent=self) ??
[09:49:24] <bomex> or not self, maybe some other parent?
[09:54:22] -!- cottoneyejim has quit [Ping timeout: 260 seconds]
[10:02:26] <altendky> bomex: I'm no python/qt memory Management expert but I generally wouldn't I think for this
[10:03:26] <bomex> "wouldn't I think for this"?
[10:04:11] <altendky> bomex: I'm no python/qt memory Management expert but I generally wouldn't, I think, for this
[10:05:30] <bomex> I see
[10:07:08] <bomex> so if the parent of the QThread instance has a parent of the class in which it is instanciated, that would not be good, right? the long-running process would then block my PyQt main event loop
[10:07:47] <altendky> bomex: parenting doesn't have anything to do with blocking the event loop
[10:23:30] <bomex> altendky: what do you usually pass as a parent argument to QThread?
[10:25:18] <altendky> bomex: I don't QThread but if you are storing it as an attribute of self then either self or None or just don't specify it
[10:26:27] <bomex> thanks
[10:26:31] -!- bomex has quit [Remote host closed the connection]
[10:33:13] -!- cottoneyejim has joined #pyqt
[11:48:24] -!- jmarsac has joined #pyqt
[11:50:53] -!- jmarsac_ has quit [Ping timeout: 272 seconds]
[12:06:39] <Avaris> ali1234: if you're feeling adventurous, you could potentially do this with metaclasses (or maybe class decorators)
[12:20:02] <altendky> yeah, i was so pissed off at the existing metaclass (you would have to inherit it etc) that i just decided to stay the heck away.
[13:21:33] -!- GrandPa-G has joined #pyqt
[13:22:44] <GrandPa-G> if I have a widget that holds a label and 2 radio buttons. if I create a new widget from this one, how do I reference the widgets radio and label in my script?
[13:23:27] <altendky> GrandPa-G: depends if you have them as attributes or available via methods
[13:23:45] <altendky> Regardless you can .findChildren but that shouldn't be needed.
[13:25:04] <GrandPa-G> at this point I just created the orginal widget in QTDesigner.
[13:26:04] <Avaris> i usually try to make subwidgets standalone by defining methods and signals as interface
[13:26:07] <altendky> GrandPa-G: when you call the setupUi or whatever it will assign the widgets as attributes
[13:26:32] <Avaris> it is more work but feels cleaner
[13:27:28] <GrandPa-G> I think I am going to rethink my solution to make it cleaner and just do what I want another way. Still good to know how. thanks.
[13:27:33] <altendky> yeah, good point, i have done that too
[13:28:29] <altendky> i do call setupUi so that i get a self.ui to hold the widgets rather than mashing them into my hand coded class itself.
[13:28:56] <altendky> then i don't need to worry about method's and widget's names colliding
[13:29:12] -!- Belxjander has quit [Quit: AmigaOSv4.1.6+//PowerPC native]
[13:29:52] -!- Belxjander has joined #pyqt
[13:33:17] <altendky> ali1234: so i'm looking back at that pyqtify stuff and i think it took a sidestep around 'the issue'. to get the signals you have to `epyqlib.utils.qt.pyqtify_signals(p)` to get the object holding them. you should be able to get closer to what you want using three-arg type() or attr.make_class() to create a new class based on the original but with `pyqtProperty`s where the attributes would otherwise be. if i'm reading
[13:33:17] <altendky> my code right...
[13:34:21] <altendky> or maybe with another layer of inheritance
[13:35:01] <altendky> all of this being part of why i dislike metaclasses. they let you do some things... but they make it a pain for anyone else to do some things too.
[13:40:52] -!- cottoneyejim has quit [Ping timeout: 256 seconds]
[14:46:19] -!- jmarsac has quit [Ping timeout: 272 seconds]
[15:00:03] -!- jmarsac has joined #pyqt
[15:00:59] -!- jmarsac_ has joined #pyqt
[15:03:45] <altendky> `Cannot load library /__w/pyqt5-tools/pyqt5-tools/.tox/py38/lib/python3.8/site-packages/pyqt5_tools/Qt/plugins/platforms/libqxcb.so: (libxcb-icccm.so.4: cannot open shared object file: No such file or directory)` i swear i saw a discussion about this recently for 5.15... but i can't find it. ended up with a list of several libraries that you need to install yourself as of qt 5.15 as i recall
[15:05:19] -!- jmarsac has quit [Ping timeout: 272 seconds]
[15:35:37] <Avaris> altendky: this? https://www.riverbankcomputing.com
[15:37:38] <altendky> Avaris: yep no hits for `site:https://www.riverbankcomputing.com/pipermail/pyqt/ icccm` :[
[15:37:40] <altendky> thanks
[16:14:49] <ali1234> altendky: what if i make a metaclass that inserts itself before the Qt metaclass?
[16:16:27] <ali1234> i saw that note in a doc somewhere about how properties aren't automatically mapped to attributes because of name shadowing
[16:16:51] <ali1234> i don't buy this and think PyQt would be infinitely more useful if this was just all done automatically
[16:18:13] <ali1234> inherit QObject and any attributes you make are just automatically properties
[16:21:10] <ali1234> is there anything on the Qt side that prevents you from adding signals to objects dynamically?
[16:22:08] <ali1234> can i build this more easily if i go lower level?
[16:23:53] <ali1234> since my QObject is a pure data class, maybe i can just dynamically generate the class itself
[16:24:58] <altendky> ali1234: in qt proper signals etc are handled by moc so... not sure if there are work arounds
[16:25:05] <Avaris> signals aren't free and i certainly would not want a signal associated with every attribute i created
[16:25:22] <altendky> ali1234: you can't 'insert another etaclass' but you can (maybe) 'inherit from the existing metaclass and extend it'
[16:26:25] <altendky> and given that 'attributes' don't exist until after the object is created... not sure what pyqt would do about this automatically. you have been talking about pyqtProperty, right?
[16:26:36] <ali1234> yeah
[16:26:54] <ali1234> but like, pyqtProperty isn't magic, it must call lower level functions
[16:27:01] <ali1234> so presumably i can call them myself
[16:27:24] <altendky> ali1234: the metaclass processes that right after class definition.
[16:27:38] <ali1234> actually, what if i declare my type in QML and then register it?
[16:27:49] <ali1234> i might not even need to instantiate it from python
[16:27:58] <ali1234> i can just pull it out of the QML context
[16:29:27] <ali1234> that kind of makes more sense, since this type is only for holding the model that drives the QML anyway
[16:29:46] <ali1234> well, its the backing data for the model items
[16:30:23] <ali1234> maybe i dont even need a model and should just inject data directly into the QML entities
[16:31:28] <ali1234> i dont actually need any of the model stuff like transitions
[16:34:32] <ali1234> i could then use positioners and repeaters
[16:36:38] <ali1234> i wouldn't need any signals at all because i'd be directly changing the data inside the QML, and i could wrap that all up in functions on the python side
[16:42:42] -!- SpinTronix has joined #pyqt
[17:22:41] -!- gour has quit [Quit: WeeChat 2.8]
[17:24:58] -!- SpinTronix has quit [Quit: Konversation terminated!]
[17:41:53] -!- cottoneyejim has joined #pyqt
[18:46:24] -!- jmarsac_ has quit [Read error: Connection reset by peer]
[18:49:05] -!- BPL has quit [Quit: Leaving]
[20:02:49] -!- cottoneyejim has quit [Ping timeout: 265 seconds]
[20:30:30] -!- yustin has quit [Ping timeout: 256 seconds]
[23:12:31] -!- GrandPa-G has quit [Ping timeout: 260 seconds]