#pyqt | Logs for 2018-10-13

Back
[00:08:17] -!- mintograde has quit [Ping timeout: 244 seconds]
[02:01:19] -!- mandeep has quit [Ping timeout: 268 seconds]
[03:18:23] -!- kushal has quit [Ping timeout: 256 seconds]
[03:18:40] -!- kushal has joined #pyqt
[05:15:53] -!- anqxyr has joined #pyqt
[05:34:07] -!- anqxyr has quit [Ping timeout: 246 seconds]
[05:58:45] -!- mintograde has joined #pyqt
[06:32:55] -!- frispete has quit [Quit: Konversation terminated!]
[06:34:34] -!- frispete has joined #pyqt
[06:42:00] -!- Belxjander has quit [Ping timeout: 252 seconds]
[10:25:17] -!- circ-user-kM2Fj has joined #pyqt
[10:30:38] <circ-user-kM2Fj> I'm pretty new to PyQt and trying to debug an issue where my UI freezes-specifically a video feed and some real-time charts. My application is for driving a remote-controlled vehicle. I have an XBox controller for driving and a background thread that polls for button presses. Sometimes the application lags and uses a whole core, and then my XBox controller becomes unresponsive. I'm trying to figure out the issue a
[10:31:05] <circ-user-kM2Fj> How can I make sure that even if my chart updates get slow, the other threads are still responsive?
[10:32:24] <altendky> circ-user-kM2Fj: you only get one CPU worth of time for your python code even with multiple threads.
[10:33:21] <altendky> circ-user-kM2Fj: generally you need multiple processes for more CPU time. In one process you should generally be working async, like qt
[10:33:56] <circ-user-kM2Fj> Right now whenever I have data come in on a signal, it binds to a handler on my main thread and updates the UI. Is there a way I can skip updates if the application is getting behind? I'm thinking maybe I should attach a timestamp to the updates.
[10:34:17] <circ-user-kM2Fj> Sometimes I observe the UI lag and then start to update really quickly, getting through the updates it had missed
[10:34:51] <circ-user-kM2Fj> Okay, so it sounds like I should move some of this to another process
[10:35:08] <circ-user-kM2Fj> I was also just surprised though at the amount of CPU used by the charting
[10:35:48] <altendky> circ-user-kM2Fj: can you avoid threads? What are you doing in them?
[10:37:19] <circ-user-kM2Fj> The threads are for talking to the remote-controlled vehicle / robot and to sensor systems on it
[10:37:42] <altendky> circ-user-kM2Fj: but why are they threads?
[10:38:35] <circ-user-kM2Fj> I think the original idea was to take signals from the UI and send them as commands to the threads, so even if the commands take a while to execute, the UI doesn't get locked
[10:38:54] <circ-user-kM2Fj> I'm inheriting some code here..
[10:39:27] <altendky> circ-user-kM2Fj: but what would take awhile?
[10:40:30] -!- mandeep has joined #pyqt
[10:40:34] <altendky> circ-user-kM2Fj: async is another way to handle things that can 'take awhile'. Qt is significantly async (signals/slots, callbacks, events).
[10:40:35] <circ-user-kM2Fj> Waiting for other systems to respond could take a while. Right now some of these threads will ping a system and wait for it to reply.
[10:41:27] <altendky> circ-user-kM2Fj: how they wait matters. As I've said, async is good. Especially in guis, especially in Python. Especially in both at once.
[10:43:15] <circ-user-kM2Fj> So using the XBox controller as an example. I have a thread that has a run() that is constantly looping and polling for events. When it gets an event, it emits a signal.
[10:43:24] <circ-user-kM2Fj> Is that a good way of handling that?
[10:44:07] <altendky> circ-user-kM2Fj: not even a sleep?
[10:44:09] <circ-user-kM2Fj> The problem I'm noticing is that sometimes the UI freezes and my XBox controller button presses may take 1 second to respond, even though the loop is supposed to run every 1ms
[10:44:19] <circ-user-kM2Fj> I'm using QThread.msleep
[10:44:27] <circ-user-kM2Fj> QThread.msleep(1)
[10:44:41] <altendky> circ-user-kM2Fj: yeah, that's not going to happen with any load in other threads
[10:44:57] <altendky> circ-user-kM2Fj: what is happening when you poll?
[10:45:21] <altendky> circ-user-kM2Fj: at some point we'll have to look at code
[10:46:11] <circ-user-kM2Fj> altendky: The XBox controller thread is super lightweight; it polls and takes an enum value and emits a corresponding signal.
[10:47:00] <altendky> circ-user-kM2Fj: but what does 'poll' mean? Does it block waiting for something to happen? Does it talk over serial? What exactly is going on
[10:47:33] <circ-user-kM2Fj> https://pastebin.com
[10:47:59] <circ-user-kM2Fj> altendky: The sdl2 module is this: https://pysdl2.readthedocs.io
[10:50:17] <altendky> circ-user-kM2Fj: why isn't that just using a qtimer in the main thread to check cyclically?
[10:50:29] <circ-user-kM2Fj> altendky: The docs for the poll event in sdl2: https://wiki.libsdl.org
[10:50:57] <circ-user-kM2Fj> altendky: Is that preferable?
[10:51:24] <circ-user-kM2Fj> altendky: I saw that half the code in this codebase used a qtimer in the main thread and then other code is using a sleep...
[10:51:32] <altendky> circ-user-kM2Fj: yes, not threads is preferable. Then you are in control of sharing the cpu
[10:52:19] <altendky> circ-user-kM2Fj: since threads don't get you extra CPU time, they are much less valuable than they might be in other languages.
[10:52:38] <circ-user-kM2Fj> altendky: Okay, that's helpful
[10:52:52] <circ-user-kM2Fj> altendky: Would you use threads for anything in PyQt?
[10:53:57] <altendky> circ-user-kM2Fj: blocking calls that you can't find an async alternative to. Long running code that you don't control so can't put processEvents in.
[10:54:53] <altendky> circ-user-kM2Fj: I have one thread and generally expect to get rid of it. I also hope to at some point split to a couple processes to get my cyclic networking code more responsive. My GUI is a bit of a hog.
[10:56:13] <circ-user-kM2Fj> altendky: Got it. So this codebase that I'm inheriting has a lot of threads and some of the things they are doing are pretty lightweight. You would advise reducing the number of threads, and as long as they are wired with signals and slots the front-end UI will remain responsive right?
[10:56:55] <circ-user-kM2Fj> altendky: Also, all of the QTimers are configured and running on threads other than the main one
[10:57:05] <circ-user-kM2Fj> altendky: It would be best to run those on the primary thread?
[10:57:52] <altendky> circ-user-kM2Fj: we'd have to look at each. But I'd think a 1ms sleep in a loop is still fairly tight.
[11:00:33] <altendky> circ-user-kM2Fj: and running in the main thread still depends on being not otherwise blocking as well
[11:01:28] <altendky> circ-user-kM2Fj: here are a couple quick reads about async. http://krondo.com
[11:01:42] <altendky> https://glyph.twistedmatrix.com
[11:03:02] <circ-user-kM2Fj> altendky: Thanks!
[11:04:17] <altendky> circ-user-kM2Fj: qt offers processEvents as a kind of generic 'yield' and signals/slots for more specific 'yield'ing. For more control and more 'normal' code in some cases you can use either twisted or asyncio to write async/await (another sort of yield) python code.
[11:04:26] <circ-user-kM2Fj> altendky: If I use a QTimer can I force this polling code to run more often than it does with a sleep? Or do I really have no control because I have so many threads?
[11:05:49] <altendky> circ-user-kM2Fj: you never have any control. But you don't want to waste CPU time checking more than once per ms.
[11:07:13] <circ-user-kM2Fj> altendky: So I might want to use a second process to handle the XBox controller events? Or I should be looking into these other things you're referencing for async?
[11:09:00] <altendky> circ-user-kM2Fj: you may want separate processes for GUI and controls. I'm pretty sure you don't care about sub ms input latency.
[11:09:26] <altendky> circ-user-kM2Fj: human response times are measured in hundreds of ms.
[11:09:32] <circ-user-kM2Fj> altendky: Got it
[11:10:48] <altendky> circ-user-kM2Fj: off the top of my head I'd be shooting for 20-30 ms controller input response in a polling environment.
[11:11:32] <circ-user-kM2Fj> altendky: Would it be better for me to increase that msleep then? Yeah I definitely don't need such a fast response, and I guess I could be killing performance elsewhere if this thread is actually sleeping for so little time.
[11:11:50] <circ-user-kM2Fj> altendky: Twisted looks awesome also; I can probably refactor some other code to use that
[11:12:56] <altendky> circ-user-kM2Fj: sure, upping the sleep time is an easy adjustment. It might help, though I don't expect much.
[11:13:18] <altendky> circ-user-kM2Fj: even if using twisted, I would recommend using async/await syntax.
[11:14:32] <circ-user-kM2Fj> altendky: So all of this code that has been written on other threads and really doesn't need to be synchronous... I could just throw 'aysnc' in front of it?
[11:15:04] <altendky> circ-user-kM2Fj: no, not that easy...
[11:15:29] <circ-user-kM2Fj> altendky: I think the original author of the application thought that by putting everything on threads and using signals and slots, the UI would always remain responsive
[11:20:23] <altendky> circ-user-kM2Fj: in other languages it would help more. Are you familiar with locking to synchronize between threads such as to maintain data integrity when writing in one thread and reading from another?
[11:21:01] <circ-user-kM2Fj> altendky: Yes I am familiar with that
[11:21:30] <altendky> circ-user-kM2Fj: how about the python GIL? Global interpreter lock
[11:22:20] <circ-user-kM2Fj> altendky: Yes a bit... my understanding is that threads will work well for this stuff until we have to acquire the GIL, and I think the only time we don't have the GIL is when waiting for some other system to respond?
[11:22:58] <altendky> circ-user-kM2Fj: the gil must be heald any time any python code is running.
[11:23:42] <circ-user-kM2Fj> altendky: That explains a lot...
[11:23:51] <altendky> circ-user-kM2Fj: since python manages all objects in all threads, it needs to lock to control the integrity at the interpreter level. They found it is more efficient in most cases to have a single lock.
[11:24:48] <circ-user-kM2Fj> altendky: So in Python if I have two threads and they share an object, is the object inherently threadsafe because of the GIL?
[11:25:05] <circ-user-kM2Fj> altendky: There are still threadsafe things in Python, like Queue, and other things that aren't right?
[11:25:10] <altendky> circ-user-kM2Fj: pyqt could release the Gil while running c++ code but I think it usually doesn't. At least not for small stuff
[11:25:36] <altendky> circ-user-kM2Fj: the Gil protects what the interpreter needs, not your data.
[11:25:57] <altendky> circ-user-kM2Fj: so yes, queue is thread safe for your data. Lists are not
[11:26:01] <altendky> Etc
[11:30:46] <altendky> circ-user-kM2Fj: how time gets shared with regards the threads and the Gil has changed, but iirc it used to effectively significantly prioritize long running activities.
[11:35:34] <circ-user-kM2Fj> altendky: So as soon as I have threads I have no control over what runs when. If I write a synchronous program I have to wait for each thing to finish before doing the next. It sounds like what I should be doing is using async/await syntax for all of the things that take a while to run?
[11:35:58] <circ-user-kM2Fj> circ-user-kM2Fj: I'm familiar with doing things aysnc in JavaScript, like when you make a request to the server and you can't handle the response until it arrives
[11:36:45] <circ-user-kM2Fj> circ-user-kM2Fj: The advantage is you can finish setting up things on the page. Basically you want everything to be event-driven. User clicks on this thing, it fires an event, and you wire that event to run some other code, but keep the UI responsive.
[11:40:10] <altendky> circ-user-kM2Fj: yup. Doesn't solve the CPU time issue, but it does drop the threading
[11:40:49] <altendky> circ-user-kM2Fj: I don't particularly expect this to solve your CPU time issue, but... It'll still be good mostly.
[11:41:16] <altendky> circ-user-kM2Fj: do you have an event filter on your charts? Pyqt charts?
[11:41:25] <circ-user-kM2Fj> altendky: Yeah, I want to reduce the CPU usage but that's a lesser concern than being able to handle the XBox controller events
[11:42:32] <altendky> circ-user-kM2Fj: I have some charting as a side feature and it's really slow. But I have an event handler connected. I want to try removing that and also try http://www.pyqtgraph.org
[11:43:04] <circ-user-kM2Fj> altendky: The way the charts work... There is a signal that emits data whenever it is collected from a sensor. That signal is routed to a handler. The handler directly updates the UI's lineseries using PyQt charts.
[11:43:07] <altendky> circ-user-kM2Fj: well, as long as something blocks for a second with the Gil heald... Nothing much you can do.
[11:43:17] <circ-user-kM2Fj> altendky: Yeah I was also looking at pyqtgraph and I have a feeling it would be a lot more efficient
[11:43:30] <altendky> circ-user-kM2Fj: what's the update frequency?
[11:43:52] <altendky> circ-user-kM2Fj: and how do you communicate with the sensors.
[11:43:54] <circ-user-kM2Fj> altendky: It's currently updating 8 charts 10x / second
[11:44:10] <altendky> circ-user-kM2Fj: actually, I should have started with this. When choking, what's the CPU usage?
[11:44:42] <altendky> circ-user-kM2Fj: mm, that's not crazy but you could throttle it back and probably get a benefit
[11:45:05] <circ-user-kM2Fj> altendky: So I haven't pinned down the CPU usage problem because there's so much going on in this program. When I am running it on a 2-core machine, the CPU was hitting 50% when it was choking and I figured that meant I was using a full core, all that Python could use on a single process.
[11:45:39] <altendky> circ-user-kM2Fj: depends on the os and tool as to how they report it, but sure
[11:45:55] <circ-user-kM2Fj> altendky: Windows 10 task manager
[11:46:26] <altendky> I forget which is which...
[11:49:32] <circ-user-kM2Fj> altendky: That's fair. Any suggestions on how to profile a PyQt application and figure out where I'm spending all the CPU when I get it to max out?
[11:50:32] <altendky> circ-user-kM2Fj: I'm tempted to make twisted 'bindings' for some more common rpc, but I did try out this twisted AMP example. https://github.com towards the goal of multiple processes to isolate my gui
[11:50:52] <altendky> circ-user-kM2Fj: I profiled with cProfile and... Let me look
[11:51:34] <altendky> Yappy
[11:51:46] <altendky> I think snakeviz worked with both
[11:52:37] <altendky> circ-user-kM2Fj: there were some cases where it seemed a tad confused about where time should be blamed what with the heart of the program being c++ (the qt event loop)
[11:52:37] <circ-user-kM2Fj> altendky: Nice
[11:53:45] <circ-user-kM2Fj> altendky: I think the next step for me will be using cProfile to figure out where all the CPU time is going
[11:53:51] <circ-user-kM2Fj> altendky: Thanks for all the help!
[11:59:11] <altendky> circ-user-kM2Fj: let me know how it goes. I don't have anything scheduled but realtime plotting is a thing we'd like to add to my program
[12:34:47] -!- mandeep_ has joined #pyqt
[12:34:51] -!- mandeep has quit [Read error: Connection reset by peer]
[13:01:46] -!- circ-user-kM2Fj has quit [Ping timeout: 268 seconds]
[15:30:18] -!- circ-user-kM2Fj has joined #pyqt
[15:30:21] <circ-user-kM2Fj> altendky: Upon profiling my application, the culprit looks to be all the signal emits. We are emitting every data block, and there are over 80 / second just for data we're gathering, and it looks like there are a lot more in total. Are signals the right way to get data up to the GUI?
[15:30:58] <circ-user-kM2Fj> cProfile shows the cost of an 'emit' on a 'PyQt5.QtCore.pyqtBoundSignal' object is 2-3 ms.
[15:51:16] <_val_> altendky: I have not been aby to fix anything
[15:51:34] <_val_> Could you please help me with the last piece of disk thingy? @_@
[15:52:03] <_val_> I promise I will pick up from there ^. I am tweaking with different layouts and stuff but unable to do anything with real python code.
[15:53:27] <altendky> circ-user-kM2Fj: yes, signals are both the async tool and the thread boundary crossing tool. I do wonder if there is something misleading with that profiling though.
[15:53:29] <_val_> altendky: here the latest code I have: https://dpaste.de <--
[15:57:41] <_val_> altendky: Maybe you don't have the other link that does show the vmname, disk size and disk uuid on the command line. Here it is https://dpaste.de
[15:58:19] <altendky> _val_: https://repl.it ok, i updated my example to show both some print() code and an alternative that usefully returns the values
[15:59:30] <altendky> _val_: there are three differences. 1) you create a list (or other collection) first to hold the stuff 2) instead of printing to the screen, you store the data you want into the collection (.append() for a list) 3) you return the collection (the list)
[16:03:20] <_val_> altendky: In your example I don't see the function accepting an argument. In my case I need the argument to be the VM
[16:04:04] <_val_> So here: https://dpaste.de line 24: I have there ...(virtual_machine.disk_attachments): but this virtual_machine var should be the one that has to be passed to the function
[16:04:48] <altendky> _val_: updated https://repl.it
[16:04:50] <_val_> e.g get_vm_disks(vm_name):\n\t for disk_attachment in connection.follow_link(vm_name.disk_attachments): no?
[16:05:47] <altendky> _val_: one issue you have here is that you'll have to decide if you want to keep only names around in your code (outside the api calls) or if you want objects. presently you have just names so you are passing in vm_name. so, you may have to turn that name into an api vm object to get it's disks
[16:07:29] <_val_> altendky: so I added something too. I think I get how this works... but now how to glue that together though
[16:09:01] <altendky> _val_: added to what?
[16:09:07] <circ-user-kM2Fj> altendky: Do you have a sense for the expected cost of calling emit?
[16:09:15] <_val_> altendky: to the link you shared with me
[16:09:19] <_val_> https://repl.it
[16:10:17] <altendky> circ-user-kM2Fj: i wouldn't think it'd be huge. but i'm imagining there maybe being something about the threads and locking etc that gives a 'false' reading there. i'm not sure. but there may also just be an issue with threads and the gil and signals/slots being troublesome
[16:11:15] <altendky> _val_: i prefer list comprehensions https://repl.it but i'm not sure what you are showing with that
[16:12:41] <altendky> circ-user-kM2Fj: are these things where the code being run is blocking? or can we just move them to the main thread and drop the threading considerations
[16:20:43] <circ-user-kM2Fj> altendky: This particular one isn't blocking. I'm going to remove the two lines that creates the thread and then moves this object off to the thread--it won't affect any of the connections--and then I'll profile again.
[16:21:00] <_val_> oh altendky see update , especially the last line
[16:21:04] <_val_> I changed that to a function
[16:21:25] <altendky> _val_: did you edit mine? you'll get a new url
[16:21:54] <_val_> oH
[16:22:06] <_val_> altendky: https://repl.it
[16:22:21] <_val_> No I .append() :)
[16:23:54] <altendky> _val_: isn't that basically the original code? i don't see a list getting created or appended to. and isn't vm_name going to be a string? so it won't have .id or .disk_attachments
[16:25:07] <_val_> altendky: yes. The vm_name should be passed to the function no?
[16:25:39] <altendky> _val_: if you want to get the disks for a particular vm, sure. but it will be a string i would think, at this point.
[16:25:58] <altendky> _val_: so, you'll have to use the api to turn that string into a vm object which you can get the data about
[16:26:09] <altendky> _val_: and also create a list and append to it rather than printing
[16:26:55] <_val_> altendky: yes but first I need to see if I get the correct results though
[16:27:16] <altendky> _val_: maybe write a new function. `vm_from_name()`
[16:27:40] <_val_> altendky: https://repl.it
[16:27:42] <_val_> see update
[16:27:53] <_val_> so ok, lets say we have get_all_disks(): funciton
[16:29:18] <_val_> altendky: ok so I put there all the functions you wrote...
[16:29:59] <_val_> since I am using: disk[vm_name] = get_vm_disks(vm_name)
[16:30:20] <_val_> get_vm_disks(vm_name): should exist correct?
[16:30:52] <altendky> _val_: 'should exist'? like it's appropriate to write it?
[16:31:02] <circ-user-kM2Fj> altendky: Even when I keep everything on the main thread I'm seeing the same cost to an emit
[16:31:39] <altendky> circ-user-kM2Fj: hmm...
[16:31:56] <altendky> circ-user-kM2Fj: you are emitting to what and what are you timing?
[16:32:26] <altendky> circ-user-kM2Fj: when in the same thread emit normally literally calls the connected functions before returning iirc
[16:32:40] <_val_> altendky: yes.
[16:33:09] <altendky> _val_: seems reasonable at this point. i'm not sure what overall architecture we should end up at but tidying the code with these functions might help us see
[16:34:01] <_val_> In [27]: get_all_disks.__dict__
[16:34:01] <_val_> Out[27]: {}
[16:34:14] <altendky> _val_: why are you doing that?
[16:35:09] <_val_> altendky: just to see if there is something in there
[16:35:20] <_val_> I am using ipython to quickly check / test
[16:35:54] <altendky> _val_: i find fiddling with more than, say, 5 lines in the repl to be more confusing that just writing a test suite and running it
[16:36:03] <altendky> *than just
[16:37:30] <_val_> altendky: sorry for that. It is so frustrating to keep gussing stuff and not knowing what's really going on
[16:37:53] <altendky> _val_: sure. i'm just not sure why you are looking at the __dict__ of a function
[16:38:43] <_val_> altendky: checking if it held some disk objects
[16:39:10] <altendky> _val_: no, a function isn't going to 'hold' disk objects. the code that is the body of the function might return some disk objects though.
[16:39:42] <altendky> *when you call it
[16:42:18] <altendky> _val_: let's take one step from your standalone script. instead of having it print a bunch of strings. add those strings to a list and then print the list after they are all collected.
[16:42:41] <altendky> _val_: forget about breaking up into functions, or disk objects, or... just store the strings in a list rather than outputting them with print()
[16:43:56] <_val_> altendky: ok
[16:46:55] <_val_> altendky:
[16:46:55] <_val_> disks.append(disk.id)
[16:46:55] <_val_> ...: return disks
[16:47:10] <_val_> just a sec
[16:47:15] <altendky> _val_: full code, old and new
[16:49:53] <_val_> altendky: https://repl.it
[16:49:54] <_val_> :)
[16:50:00] <_val_> this seems to return the uuid
[16:50:32] <altendky> _val_: do you have a step through debugger setup?
[16:50:38] <altendky> _val_: i forget what editor you are using
[16:51:13] <_val_> No
[16:51:16] <_val_> I am using atom
[16:51:25] <_val_> oh that was in ipython temrinal
[16:51:30] <_val_> terminal*
[16:52:41] <_val_> but no this code is getting the first thing it returns
[16:53:00] <altendky> _val_: set something up. i don't know atom but a quick search turns up https://atom.io
[16:53:01] <_val_> sorry for killing your brain altendky
[16:54:02] <altendky> _val_: it doesn't look like it shows you a nice tree structure of objects, but at least it gets you step-through
[16:54:46] <altendky> _val_: anyways, yes, that's the first issue i saw. it directly returns the first time through the loops
[16:55:08] <altendky> _val_: "just store the strings in a list rather than outputting them with print()"
[16:56:03] <altendky> _val_: anyways, dedent return 3 levels
[16:57:21] <_val_> altendky: I am not using print anymore
[16:57:24] <_val_> it is commented out
[16:57:35] <altendky> _val_: yeah, ignore that quote
[16:57:44] <altendky> _val_: dedent and see what issue you see next
[17:03:44] <_val_> altendky: debugger doesnt seem to complain
[17:04:11] <altendky> _val_: it wouldn't complain. it's a tool to help you see what the code is doing
[17:04:40] <altendky> _val_: such as 'wait, it returns the first time through the loops rather than finishing looping over all the items'
[17:05:00] <altendky> _val_: but, did you dedent return three levels?
[17:06:32] <_val_> altendky: yes
[17:06:38] <_val_> it hangs there.. doesn't do much
[17:06:44] <altendky> _val_: hangs?
[17:06:56] <_val_> yes
[17:07:10] <altendky> _val_: share code and output
[17:07:21] <altendky> _val_: and mostly only use repl.it for code that can actually run there
[17:07:57] <_val_> altendky: copy that!
[17:10:48] -!- circ-user-kM2Fj has quit [Ping timeout: 272 seconds]
[17:13:25] <_val_> altendky: hmm
[17:14:51] <_val_> altendky: and why do I see this: https://dpaste.de
[17:15:09] <altendky> _val_: why are you doing __dict__?
[17:15:38] <_val_> altendky: I have no idea ... wanted to know what functions this object had
[17:15:58] <_val_> altendky: I have no idea why I do things sometimes ^
[17:16:06] <altendky> _val_: but ok. why are you surprised by that? and what code did it come from? it'll help if you just add code like this to your script and run the whole thing. presumably it doesn't take that long and then it is repeatable and shareable
[17:17:12] <_val_> altendky: https://dpaste.de this is the code I am running
[17:17:33] <_val_> and then I am providing this fuction an existing virtual machine name as in ..
[17:17:35] <altendky> _val_: that code won't do anything because you never call get_vm_disks(). full code and full output
[17:17:48] <_val_> get_vm_disks('my-real-vm-name')
[17:17:58] <_val_> altendky: I do call that though
[17:18:14] <_val_> but whatever name I provide ... it will return the same thing
[17:18:22] <altendky> _val_: not in the code you shared. i can either try to piece together the full history of your repl session... or we can skip it and you can run a file and share the full file
[17:18:40] <_val_> altendky: hold a sec
[17:18:55] <altendky> _val_: step through the code and keep an eye on the vm_name variable. look at what happens to it
[17:19:12] <altendky> (step through with the debugger
[17:22:32] <_val_> altendky: I am sharing what I have. Just as in the beginning. Without a function without fancy stuff
[17:22:35] <_val_> https://dpaste.de
[17:23:49] <_val_> this is step one. Now I know you told me not to print anything.. so I did... but it wouldn't change anything in the code in my opinion
[17:24:11] <altendky> _val_: i'm not sure why changing code wouldn't change it
[17:24:47] <_val_> altendky: but what should I return? vm_name.name, disk_size or disk.id?
[17:24:54] <_val_> disks = []
[17:25:04] <_val_> disks.append(disk.id)
[17:25:08] <_val_> return disks
[17:25:13] <altendky> _val_: what information do you want? but let's ignore that for now. let's assume you want the string you were printing. instead of printing it, put that string in a list.
[17:25:15] <_val_> This is what I had
[17:25:26] <altendky> _val_: and let's skip the function and return as well.
[17:25:52] <altendky> _val_: https://dpaste.de take this and put the string it presently prints and instead collect each of those strings into a list
[17:26:16] <altendky> _val_: there should be one new line of code and one line changed
[17:26:45] <_val_> altendky: ok
[17:27:46] <_val_> altendky: https://dpaste.de
[17:28:39] <altendky> _val_: aside from deleting the output, that looks like one line changed. where's the added line?
[17:28:48] <altendky> _val_: also, what happened to the string?
[17:29:04] <altendky> (also, use .format() instead of % usually)
[17:29:18] <_val_> altendky: store_list = [vm_name.name, disk_size, disk.id]
[17:29:21] <_val_> this is the new line
[17:29:31] <_val_> the print line was commented
[17:30:01] <altendky> _val_: that's more of a modification of the print line. you need a brand new line that didn't previously exist at all
[17:30:32] <_val_> altendky: an empty list variable?
[17:30:39] <_val_> above the for loop?
[17:30:44] <altendky> _val_: yes
[17:30:59] <altendky> _val_: if you want to collect things into a list, you have to create a list first
[17:31:48] <_val_> altendky: https://dpaste.de
[17:32:09] <_val_> disks.append(vm_name.name, disk_size, disk.id)
[17:32:11] <_val_> + return disks
[17:33:13] <altendky> _val_: there's no function so you can't return. and where is the new line creating a new list?
[17:33:42] <altendky> and what happened to the string?
[17:34:01] <_val_> altendky: hmm.. what string? @_@
[17:34:51] <_val_> altendky: yeah that is true. return would cause a syntax error then
[17:36:40] <altendky> _val_: https://dpaste.de take this and collect the strings it presently prints into a list. there will be one new line of code creating a list and one changed line of code to collect instead of printing.
[17:41:23] <_val_> altendky: I thought I did
[17:41:36] <_val_> initialize an empty list: disks = []
[17:41:45] <_val_> then... disks.append(disk.id)
[17:41:51] <_val_> then return disks
[17:41:53] <altendky> _val_: that line was already there, wasn't it?
[17:42:14] <_val_> you mean disks = [] ?
[17:42:17] <_val_> yes it was there
[17:42:32] <altendky> _val_: so, it's not a new line :]
[17:42:41] <_val_> then I appended to it using disks.append(disk.id). There is no print( line anymore
[17:42:52] <altendky> _val_: there may be other issues with the original code including irrelevant lines. but i'm trying to focus on one thing
[17:43:39] <_val_> altendky: usually a simple string to list case would be
[17:43:56] <_val_> foo = ['bar','baz',cux']
[17:43:59] <_val_> for f in foo:
[17:44:13] <_val_> foo.append(f)
[17:44:26] <_val_> anyways... this is what I tried to do
[17:44:39] <altendky> _val_: https://www.diffchecker.com
[17:44:52] <altendky> _val_: one line added which creates a list. one line changed to append to the list rather than printing
[17:47:29] <altendky> _val_: do you see how that collects everything we would have printed into a list instead?
[17:48:28] <_val_> altendky: I didn't know you could put placeholders within a list.append()..
[17:48:34] <_val_> as in %d, %s %f etc.
[17:49:00] <altendky> _val_: i'm not. i'm passing a str to append(). it happens to be being created by the % format syntax
[17:49:14] <_val_> I see
[17:49:36] <_val_> altendky: so return the_list correcT?
[17:49:45] <altendky> _val_: there's no function to return from.
[17:49:50] <_val_> altendky: I made one
[17:49:58] <altendky> _val_: let's take it one step at a time here
[17:50:11] <altendky> _val_: let's next print that list out to confirm it contains what we wanted. should be one new line of code
[17:50:32] <_val_> altendky: print(the_list) :)?
[17:50:38] <altendky> _val_: sure
[17:51:07] <altendky> _val_: and share full code
[17:51:16] <altendky> and output
[17:53:31] <_val_> altendky: taking long
[17:54:06] <_val_> I think it is putting all as in ['vmname..., size, vmuuid....', 'vmname.... ,etc..']
[17:54:38] <_val_> yes so it did
[17:54:39] <_val_> sec
[17:55:46] <_val_> altendky: https://dpaste.de
[17:56:05] <_val_> you see vm-prod02 twice because this virtual machine has 2 disks
[17:56:07] <altendky> _val_: that's not full code
[17:57:03] <_val_> altendky: https://dpaste.de
[17:57:17] <_val_> login ditails missed but that is the whole code
[17:58:16] <altendky> _val_: that'll give you a NameError for sdk
[17:58:54] <_val_> lol altendky https://dpaste.de
[17:58:59] <_val_> I added the import lines
[18:00:29] <altendky> _val_: don't 'add'. copy/paste the entire file.
[18:00:41] <altendky> _val_: there are various ways to not include your credentials in the source
[18:00:57] <_val_> Ok
[18:01:55] <_val_> altendky: https://dpaste.de this is the full code as i have now
[18:05:43] <altendky> _val_: put 5-28 inside a function. no parameters. return the list. call the new function and print the result from outside the new function
[18:09:18] <_val_> altendky: https://dpaste.de
[18:09:22] <_val_> how about this?
[18:10:24] <_val_> oops typo
[18:10:32] <_val_> return(the_list) should have been
[18:10:48] <altendky> _val_: just fix it and make a new paste
[18:11:18] <_val_> altendky: ['vm-prod01 : 32 28723709-bd28-4a09-9720-ba36d494a261']
[18:11:25] <_val_> this is what it returns
[18:11:48] <altendky> _val_: full code and full output
[18:14:02] <_val_> altendky: https://dpaste.de
[18:15:19] <altendky> _val_: why is the return indented so far?
[18:15:57] <altendky> _val_: it's going to return at the end of the first iteration of the outer for loop
[18:16:19] <_val_> oh
[18:16:28] <_val_> altendky: so I should move it to left?
[18:16:30] <_val_> @_@
[18:17:34] <altendky> _val_: it should at least be where the print was https://dpaste.de if you want it to have the same contents as were printed there.
[18:18:11] <altendky> _val_: i would probably default to putting it even another layer out. i'm not sure what the point of `if len(vms) > 0:` is
[18:18:45] -!- diK has joined #pyqt
[18:18:48] <altendky> but, we can get back to that
[18:18:59] <_val_> altendky: hmm that produces quite a mess of an output
[18:19:12] <_val_> I moved return 4 spaces back.. and uhm.. it prints all vm's now
[18:19:15] <altendky> _val_: it should produce the same as before it was a function
[18:19:26] <_val_> altendky: yes but it is printing all vms now
[18:19:40] <altendky> _val_: just like it was before you made it a function, yes?
[18:19:42] <_val_> also yeah that line is if vm's were found then proceed
[18:19:47] <_val_> yes
[18:20:07] <altendky> _val_: but, `for vm_name in vms:` will already do nothing if `vms` is empty.
[18:20:14] <altendky> _val_: but leave it for now
[18:20:17] <_val_> altendky: exactly
[18:20:23] <altendky> _val_: so, latest code and full output
[18:22:24] <_val_> altendky: https://dpaste.de
[18:22:54] <altendky> _val_: `return` isn't a function
[18:23:26] <_val_> altendky: so I could leave (..) out
[18:23:32] <altendky> yup
[18:23:32] <_val_> but would that change the situation?
[18:24:16] <altendky> _val_: it would have no functional change, no
[18:24:47] <_val_> altendky: I removed the surrounding (..)
[18:25:31] <altendky> _val_: let's extract a function that can get the disks for a single vm
[18:26:11] <_val_> altendky: haha. Yeah lets do that!
[18:26:13] <_val_> :)
[18:26:30] <altendky> _val_: that'll be lines 19-28 in https://dpaste.de
[18:26:52] <altendky> _val_: the new function will need to create it's own list to collect results into and then to return
[18:27:43] <altendky> _val_: the existing function `get_vm_disks()` will have to call the new function and collect it's results into the existing list. that will use `the_list.extend()` rather than `.append()`
[18:31:33] <_val_> altendky:
[18:31:49] <_val_> I need to create another function? Does this accept an argument?
[18:32:19] <altendky> _val_: yes, the new function will accept an argument
[18:32:41] <_val_> altendky: what should we name this new function?
[18:33:02] <altendky> _val_: how about `get_vm_disks()` and rename the original to `get_all_vm_disks()`
[18:33:07] <_val_> get_disks(vm_disks): ?
[18:33:14] <_val_> sure
[18:33:15] <_val_> sec
[18:34:12] <_val_> altendky: def get_vm_disks(vm_disks):
[18:34:20] <_val_> I renamed the other one
[18:34:33] <altendky> _val_: why would you pass `vm_disks` to `get_vm_disks()`?
[18:34:56] <_val_> altendky: get_all_vm_disks() has no argument
[18:35:03] <altendky> _val_: sure
[18:35:33] <_val_> altendky: but but...
[18:35:34] <_val_> [00:32] altendky> _val_: yes, the new function will accept an argument
[18:35:51] <altendky> _val_: if i ask you to go get me milk... do you give you milk?
[18:36:23] <altendky> _val_: usually not, because that'd mean i already had milk and didn't need to ask you to get it
[18:37:02] <_val_> altendky: oh I would give you milk :-p. I like the analogy! :)
[18:37:12] <_val_> ok so the other function will be just def get_vm_disks():
[18:37:13] <_val_> ?
[18:37:14] <altendky> _val_: i might need to tell you where to get it, or what kind of milk though
[18:37:25] <altendky> _val_: no, as i said, the new function will take a parameter
[18:37:26] <_val_> haha. Goat milk? :P
[18:37:30] <_val_> Ok sorry
[18:37:33] <_val_> hold a sec
[18:37:46] <altendky> _val_: but sure, don't specify a parameter for now. an error message will help you see what you need to pass
[18:38:23] <_val_> altendky: https://dpaste.de
[18:38:32] <_val_> this is what I have now
[18:39:00] <altendky> _val_: lines 19-28 belong in the new function
[18:40:31] <_val_> altendky: https://dpaste.de
[18:41:06] <altendky> _val_: remember how something called `get_vm_disks` wouldn't take a parameter named as the thing it is getting?
[18:41:21] <altendky> _val_: and the point is to _move_ those lines.
[18:43:48] <_val_> altendky: ok just a sec
[18:46:12] <_val_> altendky: ok so I changed that: https://dpaste.de
[18:46:34] <altendky> _val_: still got `def get_milk(milk):`
[18:46:48] <_val_> you mean get_vm_disks(vm_disks): shouldn't have the argument called 'vm_disks'
[18:46:57] <_val_> ok but I am not so creative as you have noticed
[18:47:10] <_val_> altendky:
[18:47:21] <altendky> _val_: x would be a better name than that. but we will see by an error what it is we are needing to pass
[18:47:30] <altendky> _val_: but go ahead and call `get_vm_disks()` from inside `get_all_vm_disks()`
[18:47:32] <_val_> def get_vm_disks(virtual_machine_dsk): ?
[18:47:57] <_val_> ok
[18:48:24] <altendky> _val_: no. you aren't going to pass disks to a function that is meant to get you the disks
[18:49:30] <_val_> altendky: https://dpaste.de
[18:49:37] <_val_> makes sense for now?
[18:49:46] <altendky> _val_: that's an old url
[18:49:59] <_val_> no
[18:50:04] <_val_> this is the latest
[18:50:23] <altendky> _val_: it's the same link you posted 10 minutes ago
[18:50:29] <_val_> oh sorry
[18:50:31] <_val_> my bad
[18:50:49] <_val_> here https://dpaste.de
[18:52:19] <altendky> _val_: you moved some code from `get_all_vm_disks()` to `get_vm_disks()`. presumably you want to call `get_vm_disks()` in a similar location as the code you moved was in
[18:53:05] <_val_> indent problem
[18:53:17] <altendky> not just
[18:55:29] <_val_> altendky: I moved line 19-28 in the new function
[18:55:56] <_val_> sorry I don't get it
[18:56:18] <_val_> You said to call get_vm_disks() from inside `get_all_vm_disks()` so I did
[18:56:19] <_val_> :/
[18:56:29] <altendky> _val_: ok, how do you have it now?
[18:57:44] <_val_> altendky: https://dpaste.de
[18:57:59] <altendky> _val_: you have the name there, but you aren't calling it
[18:59:27] <_val_> altendky: return get_vm_disks('vm-name')?
[19:00:03] <altendky> _val_: you don't have it taking any parameter right now, so you wouldn't be passing anything. we'll figure out what to pass after
[19:00:43] <_val_> yes so I thought.
[19:01:19] <_val_> when I used print(get_all_vm_disks) I got an object back
[19:01:34] <altendky> _val_: yes, the function
[19:01:38] <_val_> yes
[19:01:44] <altendky> _val_: you have to add () to call a function
[19:01:50] <altendky> (or any other callable)
[19:03:51] <_val_> altendky: yeah. So since we are at this stage. What is the next move?
[19:03:53] <_val_> @_@
[19:04:07] <altendky> _val_: do you have code calling the new function?
[19:04:39] <_val_> no
[19:04:50] <_val_> altendky: so create another function?
[19:05:05] <altendky> _val_: no. if you have a function called `x` then you would write `x()` to call it
[19:05:27] <_val_> altendky: sure I undertsand that but which to call?
[19:05:32] <_val_> get_all_vm_disks()
[19:05:33] <_val_> ?
[19:07:13] <_val_> altendky: I am using the debuuger but don't see anything wrong there
[19:08:02] <altendky> _val_: you moved some code from `get_all_vm_disks()` into a new function `get_vm_disks()`. presumably you want to call `get_vm_disks()` from `get_all_vm_disks()` and from the same place as the code used to be
[19:10:56] <_val_> altendky: I am calling get_vm_disks() from get_all_vm_disks()
[19:11:07] <altendky> _val_: ok, share full code
[19:11:34] <_val_> https://dpaste.de
[19:12:02] <altendky> _val_: ok, what happens when you run that? share full output
[19:12:03] <_val_> altendky: I know get_vm_disks() shouldn't be indented there
[19:12:10] <_val_> altendky: nothing outputs
[19:12:39] <altendky> _val_: i don't think that'd have no output
[19:12:42] <_val_> no hold
[19:13:23] <_val_> altendky: https://dpaste.de
[19:13:35] <_val_> but ok this can be explained I guess
[19:14:11] <_val_> vm_name is not defined anywhere
[19:14:27] <_val_> within get_vm_disks() function
[19:14:31] <altendky> _val_: the error doesn't refer to `vm_name`
[19:14:55] <_val_> NameError: name 'vms_service' is not defined
[19:14:56] <_val_> ah
[19:16:01] <_val_> altendky: ok so
[19:16:04] <_val_> just a sec
[19:18:51] <_val_> altendky: https://dpaste.de
[19:19:02] <_val_> I moved vms_service to get_vm_disks()
[19:19:37] <altendky> _val_: ok, so what do you think of that error?
[19:20:02] <_val_> altendky: vm_name is not defined
[19:20:05] <_val_> that is true
[19:20:18] <altendky> _val_: how do you think you should fix it?
[19:21:17] <_val_> altendky: by providing an argument to get_vm_disks(x):
[19:21:18] <_val_> ?
[19:21:45] <_val_> no
[19:21:46] <_val_> sec
[19:21:58] <altendky> _val_: what might be a good name for a parameter you will use for vm_name?
[19:22:55] <altendky> i mean vm_name is a bad name for right now because it isn't the name, it's actually the whole vm. but, whatever, we can deal with that later
[19:23:31] <_val_> altendky: def get_vm_disks(virtual_machine):
[19:23:32] <_val_> ?
[19:23:58] <altendky> _val_: let's just go with vm_name for the moment
[19:24:03] <altendky> that's how it was already coded
[19:24:40] <_val_> yes ok, so we have it
[19:25:40] <altendky> _val_: full code, full output
[19:26:18] <_val_> sec
[19:27:31] <_val_> altendky: https://dpaste.de
[19:27:35] <_val_> no output produced
[19:28:29] <altendky> _val_: alrighty. maybe we want to check the overall result like we did before.
[19:28:52] <_val_> altendky: ah
[19:29:03] <_val_> altendky: sec.
[19:30:52] <_val_> altendky: https://dpaste.de
[19:31:00] <_val_> I added the print there
[19:31:07] <_val_> Line 43
[19:31:28] <altendky> _val_: that's not going to be the overall result. that's about as inside as you can get in this code
[19:32:45] <_val_> altendky: so ok. Will this work now gluing it with pyqt?
[19:33:02] <_val_> once a vm is selected, the disk(s) for that vm is printed?
[19:33:16] <altendky> _val_: you aren't checking the overall result
[19:33:51] <_val_> altendky: what do you mean by overall result?
[19:34:05] <altendky> _val_: you call a function. does it return what you want?
[19:34:26] <altendky> _val_: you don't check this by modifying the function and putting a print inside. you check it by looking at what the function returned
[19:36:20] <_val_> altendky: well sorry but this is too much for me I guess
[19:37:05] <altendky> _val_: print(get_all_vm_disks())
[19:37:10] <altendky> _val_: that's how we were checking before
[19:37:41] <altendky> _val_: if you ask me to get you milk, do you check to see if i got you milk by following me to the store? or do you wait until i come back and make sure i have milk for you.
[19:38:37] <_val_> altendky: latter
[19:38:38] <_val_> :)
[19:40:35] <altendky> _val_: if you checked at the store but i threw the milk in the river on the way home, having checked at the store wouldn't be very relevant
[19:41:09] <_val_> altendky: exactly. That's why I preferred the latter
[19:41:10] <_val_> :)
[19:41:25] <_val_> waiting to make sure there is milk at the end :)
[19:41:39] <altendky> _val_: ok, so what does that get you
[19:42:14] <_val_> see if the function returns true?
[19:42:17] <_val_> no idea
[19:42:34] <_val_> altendky: it is here: f3d0r4:~/PROGRAMMING/PYTHON[1]$ date
[19:42:34] <_val_> Sun Oct 14 01:42:26 CEST 2018
[19:42:54] <_val_> I couldn't think clearly earlier.. let alone now :/
[19:43:00] <altendky> _val_: hey, your call. :]
[19:43:49] <_val_> altendky: I understand print(get_all_vm_disks()) isn't the right way
[19:43:51] <_val_> but what is
[19:45:21] <altendky> _val_: naw, that's fine. see what that outputs
[19:46:27] <_val_> altendky: same thing
[19:46:31] <_val_> shows me same output
[19:46:49] <_val_> I lied
[19:47:06] * _val_ bangs his head against the desk
[19:47:14] <_val_> altendky: output is None
[19:47:24] <altendky> _val_: :] ok. do you know why?
[19:47:40] <_val_> altendky: no?
[19:48:19] <altendky> _val_: functions implicitly return None when they fall off the end without running an explicit return statement
[19:49:22] <_val_> altendky: ok so return the_list is missing?
[19:50:36] -!- diK has quit [Quit: Leaving]
[19:50:53] <_val_> altendky: hold
[19:51:47] <_val_> altendky: https://dpaste.de
[19:51:53] <_val_> does this make sense? ^
[19:52:01] <_val_> I get 1 record now
[19:52:20] <altendky> _val_: sounds like a bug :]
[19:52:50] <_val_> oh?
[19:53:10] <altendky> _val_: well, it isn't what you want, right?
[19:53:19] <_val_> maybe it is
[19:53:26] <altendky> _val_: maybe step through the code and see what runs
[19:53:42] <_val_> if I dynamically using a combobox can change vm_name
[19:53:49] <_val_> than I would get another disk right
[19:54:16] <altendky> _val_: it's not what the code did before you refactored it into two functinos
[19:55:52] <_val_> well it prints all vms and disks and stuff , or just 1
[19:56:20] <altendky> _val_: no, `get_all_vm_disks()` should get disks for all vm's
[19:57:13] <_val_> altendky: so now?
[19:57:34] <altendky> _val_: step through the code (debugger?) and consider if what it does is what you meant for it to do
[19:59:56] <_val_> altendky: return the_list[0] is the same as return the_list
[20:00:05] <_val_> so the first index is returned each time
[20:00:06] <altendky> _val_: not really
[20:00:21] <altendky> _val_: one returns the list, the other returns the first element of the list
[20:00:26] <altendky> _val_: but, that's not the issue
[20:01:12] <_val_> altendky: then I have no idea
[20:01:13] <_val_> :/
[20:01:24] <altendky> _val_: https://repl.it consider `double_b()`
[20:02:29] <_val_> altendky: yeah sure but I don't understand
[20:03:04] <altendky> _val_: what does it do 1) in the loop and 2) after the loop
[20:04:43] <_val_> altendky: before loop it initiates the values, then in the loop it times *2 those values
[20:05:55] <altendky> _val_: before the loop it creates a container, in the loop it adds stuff to the container, after the loop it returns the container
[20:06:36] <_val_> altendky: yes
[20:06:45] <_val_> empty list double = [] is created
[20:07:09] <_val_> then loops through and appends to double
[20:07:19] <_val_> it is clear to me yes
[20:07:32] <altendky> _val_: your functions should be doing something similar
[20:09:35] <_val_> altendky: that is what I have
[20:09:39] <_val_> I don't get it
[20:09:46] <altendky> _val_: i didn't see it share latest
[20:10:32] <_val_> altendky: https://dpaste.de
[20:10:51] <altendky> _val_: you have two functions, are both like that?
[20:11:00] <_val_> altendky: yes
[20:11:49] <altendky> _val_: 1) before the loop it creates a container, 2) in the loop it adds stuff to the container, 3) after the loop it returns the container
[20:12:07] <altendky> _val_: what line is implementing each of 1/2/3 in `get_all_vm_disks()`?
[20:12:23] <altendky> *lines
[20:12:27] <altendky> *lines are
[20:14:48] <_val_> if len(vms) > 0:
[20:14:48] <_val_> v = []
[20:14:48] <_val_> for vm_name in vms:
[20:14:48] <_val_> v.append(get_vm_disks(vm_name))
[20:14:49] <_val_> return v
[20:15:04] <altendky> _val_: much better.
[20:15:13] <altendky> _val_: i would v.extend() to retain the previous functionality though
[20:15:36] <altendky> _val_: x = [1,2,3]; x.append([4,5,6]) -> [1,2,3,[4,5,6]]
[20:15:44] <altendky> _val_: x = [1,2,3]; x.extend([4,5,6]) -> [1,2,3,4,5,6]
[20:16:30] <_val_> oh I see
[20:16:40] <_val_> well no I got this? :)... and nexT?
[20:17:04] <altendky> _val_: is the output of `get_all_vm_disks()` back to where it started?
[20:17:05] <_val_> so append creates an inner list
[20:17:19] <_val_> altendky: it is cluttered but it prints all vm's
[20:17:23] <altendky> _val_: append increases the length of the list by one. it just happens i was putting in a list
[20:17:37] <altendky> _val_: extend increases the list length by the number of items in the passed iterable
[20:18:15] <altendky> _val_: ok. now you wanted to be able to get disks for just one vm. try after the print(get_all_vm_disks()) call to get the disks for just one of them by passing a vm name
[20:19:32] <_val_> hmm
[20:20:05] <_val_> after? new line?
[20:20:10] <_val_> next line?
[20:22:02] <_val_> altendky: ^
[20:22:18] <_val_> print(get_all_vm_disks()) change to #print(get_all_vm_disks()) ?
[20:22:23] <altendky> _val_: another line
[20:22:26] <_val_> so it won't print.
[20:22:44] <_val_> but do I call get_vm_disks('vm-name')?
[20:22:59] <altendky> _val_: sure, see what happens
[20:23:17] <_val_> vm_service = vms_service.vm_service(vm_name.id)
[20:23:17] <_val_> AttributeError: 'str' object has no attribute 'id'
[20:24:11] <altendky> _val_: yep. so you had a variable `vm_name` but it wasn't really the vm name. it was a vm object itself
[20:25:21] <_val_> altendky: yes so I should call it with .name?
[20:25:36] <_val_> I mean if it is an object I should call a method of that object
[20:25:42] <altendky> _val_: no, you should rework the function so it can get a vm object from a name
[20:26:10] <_val_> altendky: well then we'll be here 2 hours later and I won't learn much I guess :/
[20:26:26] <altendky> _val_: it takes a lot of passes to get to a useful place
[20:27:51] <_val_> rework the function. I mean which one. How.
[20:28:28] <altendky> _val_: the one that didn't work how you wanted when you called it. `get_vm_disks()`
[20:28:49] <altendky> but sure, changing what it takes as a parameter will (slightly) affect the code in the other function too
[20:30:09] <_val_> altendky: well Thanks for the long walk through these functions. It is quite late here and I am not sure I can think clearly anymore.
[20:30:22] <altendky> _val_: by all means, you are allowed to sleep. :]
[20:31:24] <_val_> Thanks again and have a great time.
[20:32:37] <altendky> _val_: you too, cheers
[21:02:21] -!- acwatt has joined #pyqt
[21:03:25] -!- beeman has quit [Quit: Connection closed for inactivity]
[21:42:08] -!- kallesbar has quit [Quit: Konversation terminated!]