Robert Basic's blog

Archive for the 'Programming' category

Install PyQt5 in Python 3 virtual environment

by Robert Basic on February 04, 2015.

It’s been a while since I last made something with PyQt, so I decided to check out what’s it like nowadays. I’m curious to see what’s new in Qt5 and how does it differ from Qt4. Qt5 also can run under python 3 so I figured to give it a try.

Fedora 21 comes with both python 2.7 and python 3.4, but the default version is 2.7, which means if PyQt5 is installed through the package manager, it will be installed against 2.7. As I’m not currently in the mood of bricking my laptop by changing the default python version, I decided to install PyQt5 in a python virtual environment. Btw, Fedora 22 should have python 3 by default.

In the code samples below, assume the working directory is always ~/pyqt.

Create a virtual environment

First off, let’s create a virtualenv with python 3.4:

virtualenv --python=python3.4 env

Activate the virtualenv and check the python version to verify:

source env/bin/activate
python --version

And that should print something like Python 3.4.1. Leave the virtualenv active, as that’s where PyQt5 is going to be installed.

PyQt5 dependencies

Cool, now with that set up, let’s get PyQt5 dependencies sorted out:

sudo yum install gcc gcc-c++ python3-devel qt5-base qt5-base-devel

As the documentation says, SIP must be installed before PyQt5. Lets grab the sources, configure and make and install them.

tar xzf sip-4.16.5.tar.gz
cd sip-4.16.5
sudo make install
cd ..
rm -r sip-4.16.5*

Not sure why I had to do sudo make install. Verify sip is installed correctly by starting a python shell and typing in the following:

import sip

That should show the sip version 4.16.5.

Installing PyQt5

All the dependencies should be met now, so let’s install PyQt5.

tar xzf PyQt-gpl-5.4.tar.gz
cd PyQt-gpl-5.4
python --qmake /usr/bin/qmake-qt5
make install
cd ..
rm -r PyQt-gpl-54*

This will install PyQt5 with the basic modules such as QtCore, QtWidgets and QtSql. Check the output of the python step to see what modules will be installed. If you need additional modules in your PyQt5 setup, you’ll have to install additional Qt packages on your system. For example, to get the QtWebKit module, install the qt5-qtwebkit package through your package manager first.

Writing a basic PyQt5 app we can verify that it all works. Save the following as

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = QMainWindow()

Running it with python should start the application that’s just one small window.

Happy hacking!

Tags: pyqt5, python, virtualenv.
Categories: Development, Programming, Software.

Mocking hard dependencies with Mockery

by Robert Basic on December 23, 2014.

One problem with unit testing legacy applications is that the code has new statements all over the place, instantiating new objects in a way that doesn’t really makes it easier to test the code.

Of course, the easy answer to this is “Just refactor your application!”, but that’s almost always easier said than done.

If refactoring is an option, do it. If not, one option is to use Mockery to mock the hard dependencies.

One prerequisite to make this work is that the code we are trying to test uses autoloading.

Let’s take the following code for an example:

namespace App;
class Service
    function callExternalService($param)
        $externalService = new Service\External();
        return $externalService->getSomething();

The way we can test this without doing any changes to the code itself is by creating instance mocks by using the overload prefix.

namespace AppTest;
use Mockery as m;
class ServiceTest extends \PHPUnit_Framework_TestCase {
    public function testCallingExternalService()
        $param = 'Testing';

        $externalMock = m::mock('overload:App\Service\External');

        $service = new \App\Service();

        $result = $service->callExternalService($param);

        $this->assertSame('Tested!', $result);

If we run this test now, it should pass. Mockery does it’s job and our App\Service will use the mocked external service instead of the real one.

The problem whit this is when we want to, for example, test the App\Service\External itself, or if we use that class somewhere else in our tests.

When Mockery overloads a class, because of how PHP works with files, that overloaded class file must not be included otherwise Mockery will throw a “class already exists” exception. This is where autoloading kicks in and makes our job a lot easier.

To make this possible, we’ll tell PHPUnit to run the tests that have overloaded classes in separate processes and to not preserve global state. That way we’ll avoid having the overloaded class included more than once. Of course this has it’s downsides as these tests will run slower.

Our test example from above now becomes:

namespace AppTest;
use Mockery as m;
 * @runTestsInSeparateProcesses
 * @preserveGlobalState disabled
class ServiceTest extends \PHPUnit_Framework_TestCase {
    public function testCallingExternalService()
        $param = 'Testing';

        $externalMock = m::mock('overload:App\Service\External');

        $service = new \App\Service();

        $result = $service->callExternalService($param);

        $this->assertSame('Tested!', $result);

And that should be pretty much it. If nothing else, it should make parts of old code easier to test.

For anyone interested, I put the example code up on Github.

Tags: mockery, php, testing, unit tests.
Categories: Development, Programming.

Xdebug and private /tmp on Fedora

by Robert Basic on December 16, 2014.

This one was a bit weird and needed some figuring out. Xdebug profiler output files were not being generated in the /tmp directory.

I wanted to do some profiling with xdebug. I set all the necessary configuration settings in my php.ini, restarted apache, confirmed xdebug is present and configured correctly with php -i | grep xdebug, appended ?XDEBUG_PROFILE=1 aaaand! Nothing. Nothing in /tmp, the default profiler output directory. Double checked paths, permissions, nope, nothing. No profiler files were generated.

find /tmp -name "cachegrind*"

listed the files in


What the?

Apparently systemd services in Fedora can have this setting called PrivateTmp and services with this setting set to true are started with a private /tmp directory. Something something security.

Well then. I created a /var/log/xdebug directory, changed the owner to apache and set the xdebug.profiler_output_dir to that new directory and all is well again.

Hey, I learned something new today.

Tags: fedora, php, systemd, xdebug.
Categories: Development, Programming, Software.

Ack in vim

by Robert Basic on December 09, 2014.

I started using vim 3, 4 years ago. The way I use it is that I started out with no plugins and with a handful of lines in .vimrc. It is far too easy to cram all kind of stuff into it and then get lost in the myriads of key combinations. To prevent that, I decided to slowly add in bits and pieces I find lacking in my day to day usage of vim. Also allows me to first learn the editor and later the plugins.

Today was an exceptional day as I added not one, but two plugins to vim! And that is a big change for me as the total number of plugins I now use is 4.

The first one I added is ack.vim. It’s a nice little plugin to run ack from within vim and show the results in a split window. It’s rather easy to use, one just basically types :Ack search_string and that’s it. The one thing I immediately disliked is that it sort of gets lost in the subdirectories of a project.

A quick google search found a solution for that little problem as well: vim-rooter. It doesn’t do much, just changes the current working directory of vim to the project root when you open a file.

And that’s basically it. Nice and fast searching with ack from vim.

Tags: ack, plugins, rooter, vim.
Categories: Development, Programming, Software.

Saturday night hack - coords

by Robert Basic on March 24, 2013.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

When I was just starting out learning programming, everything was so simple. I did not care about design patterns and best practices and unit tests and how will users use that piece of code. Hell, I did not even know those things exist. I was having fun, I was learning, I was free to do whatever I wanted to do, I was playing, I was like a child. Not that there is something wrong caring about those things now, but then I was able to put out a piece of code that was fixing a core of one problem I had and that was it. Once I was done with that, I would move on to the next problem. For a long time now I was missing that feeling of not caring, just fix the damn problem and move on. Just to slap together some crappy piece of code, use it once or twice and then forget about it.

And that was exactly what I did last night. I sat down and in some five or six hours I put together coords. It is an ugly as hell little pygtk application, void of any good practices, no tests, just a few comments here and there and that’s it. And I had fun writing it! I completely lost track of time while hacking, got into the zone and today, after some six hours of sleep I woke up feeling like I was on a vacation for a week.

The application itself doesn’t do much, it helps determine coordinates on your desktop. Start the application, click “track”, drag the mouse from the top-left corner you’re interested in to the bottom-left one and that’s it. The entire functionality is shown in this ten second long gif that runs somewhere here on the page. The best part is that it actually solves a problem I had, it helps me determine coordinates on my desktop and then I can use those coordinates for byzanz-record. I loved every second I spent hacking on this.

Best part is that even this little application had a quite an interesting challenge to solve, namely, to determine the position of the mouse anywhere on the screen. It’s no big deal to determine the position of the mouse inside your application, but once you want to break out of it, well, it gets bit tricky.

With pygtk one can only subscribe to events that happen inside the application itself. To go lower than that one needs to use a different library, something like xlib (python-xlib from python). After much poking around I found a way to do it from pygtk itself. It is possible to get hold of the root window instance, which is created by the X server itself (you can’t create a root window from an application, or make an application be a root window, afaik). Once you have the root window, grab the pointer, and then filter events you are interested in on the root window before they get sent from the X server to gtk. Or at least that is how I understood this whole process. While having control over the pointer, get the mouse coordinates from the time left button is pressed till the time it is released. Don’t forget to ungrab/release the pointer once your done. And that’s all there is to it, more or less.

The interesting parts are:

def start_tracking(self, widget, data=None):
    self.root_window = gtk.gdk.get_default_root_window()
    gtk.gdk.pointer_grab(self.root_window, False, mask)
    self.root_window.add_filter(self.track_region, self.region)
def track_region(self, event, region):
    x, y, flags = event.window.get_pointer()
    if 'GDK_BUTTON1_MASK' in flags.value_names \
            and region.track_started == False:
        region.start_x = x
        region.start_y = y
        region.track_started = True
        region.track_ended = False
    if 'GDK_BUTTON1_MASK' not in flags.value_names \
            and region.track_started == True:
        region.end_x = x
        region.end_y = y
        region.track_ended = True
        region.track_started = False
        # ungrab the pointer so we get control back
    return gtk.gdk.FILTER_CONTINUE

Isn’t it ugly? Very. But it works and it solves the problem I had. Btw you can check out the code on github to have a bit more context for all this.

Happy hackin’!

Tags: byzanz, hack, pygtk, python.
Categories: Development, Programming, Software.