Psychopy: Support for pyglet 1.4

Created on 7 Jul 2019  路  14Comments  路  Source: psychopy/psychopy

When installing psychopy's dependencies, pip now retrieves the latest version of pyglet (at least for me), pyglet 1.4. But some psychopy code is only compatible with pyglet<=1.3.

Opening a window with visual.Window() and the pyglet backend raises an error with traceback leading to pyglet.window.get_platform(). This problem is noted in #2399, with a downgrade to pyglet 1.3 as the suggested fix.

In pyglet 1.4, pyglet.window.get_platform().get_default_display() seems to have been refactored to pyglet.canvas.get_display() (see pyglet issue here).

I am not familiar enough with the psychopy project to know which fix is preferable:

  • hold back pyglet to <=1.3 in psychopy's dependencies
  • switch to supporting only the latest pyglet
  • offer compatibility for both pyglets with a version check

If the preference is for full compatibility, then the necessary fix is probably in pygletbackend.py, which would need to become something like:

if pyglet.version > '1.3':
    defDisp = pyglet.canvas.get_display()
else:
    defDisp = pyglet.window.get_platform().get_default_display()
involves opengl library

Most helpful comment

@hoechenberger and I have discussed a bit before. My feeling in general is that we should aim to be compatible with all versions of libs as far as possible so that users generally can use the latest version or whatever they have installed for other purposes. If we fix the version then tests will only run on that version of the lib (as intsalled by Travis etc) and we won't know whether a newer version (that a user has installed) is now broken.
There are times when we do have to (usually temporarily) fix a certain lib to a certain version but it's relatively rare that we need to and then I think we should do it just for that lib for as long as needed.

All 14 comments

I tested the change I suggested above, and it fixes the immediate problem, so that opening a window with the pyglet backend and pyglet 1.4 runs without error.

But the refactoring in pyglet 1.4 clearly goes deeper. Creating a TextStim for the window leads to a similar-looking problem in text.py, where pyglet.font.Text() no longer matches the new module structure in pyglet 1.4.

So I guess there are many such changes and providing compatibility for pyglet 1.4 would be a bigger task.

Thanks for detailing a couple of the issues. Yes, I imagine there are a number of changes we need to make to enable this switch and, for now, fixing the pyglet version is probably needed. I'll try and look later this week at what else would be required

I notice from setup.cfg that a lot of the dependency versions are unspecified, not just pyglet's, right?

Is there a particular reason you do it this way? It seems like it could just keep on producing bugs like this one. Why not just limit all the dependencies to the currently tested versions and wait for proven compatibility until moving them up?

@hoechenberger and I have discussed a bit before. My feeling in general is that we should aim to be compatible with all versions of libs as far as possible so that users generally can use the latest version or whatever they have installed for other purposes. If we fix the version then tests will only run on that version of the lib (as intsalled by Travis etc) and we won't know whether a newer version (that a user has installed) is now broken.
There are times when we do have to (usually temporarily) fix a certain lib to a certain version but it's relatively rare that we need to and then I think we should do it just for that lib for as long as needed.

ie. the real solution is to have tests detecting when a lib is non-compatible and then fix for that lib as fast as possible to be dual-compatible

I see. Thanks for the explanation!

Mostly fixed in #2575, thanks to @luketudge for the suggestions. If anything goes wrong, people can revert to Pyglet 1.3 which should still work.

Thanks @mdcutone. I haven't looked at the failed tests, but for basic drawing and displaying text your fix #2575 is also working on my system with either pyglet 1.3 or 1.4.

However, as you noted, the text seems to scale slightly differently across versions (larger in 1.4), and for me it also aligns differently, with 1.4 putting the text towards the left of the window by default, and 1.3 putting it in the center as expected.

pyglet.text.Label() has an additional init parameter align (see here), which I thought might be at fault, but fixes likealign='center' or align=self.alignHoriz have no effect that I can discern.

As far as I can glean from the pyglet documentation, your fix does broadly the right thing. So at the moment my working hypothesis is that the fault lies rather with pyglet. When I get some time I will try to confirm by doing some basic text drawing with pyglet 1.4 directly and see whether I can find bugs there.

Some of those failed tests are surely to do with the scaling being different. I'll need to look into that.

There is one in TextStim._setTextNoShaders that hasn't been changed from the deprecated call and that therefore errors. At some point it probably is time to remove support for cards that don't have shader support. That was added in OpenGL2.0 (2004) but I don't know when the oldest cards supporting GL1.4 were still being produced. When we drop support for non-shader it will cut out quite a lot of duplicate code :-)

Text rendering is something we should handle ourselves to prevent 3rd party APIs from breaking support. It's really easy to do actually, https://learnopengl.com/In-Practice/Text-Rendering

We can use https://pypi.org/project/freetype-py/ as the interface. Also here's a GL example https://github.com/rougier/freetype-py/blob/master/examples/opengl.py

Yes. It's halfway done. ;-)
https://github.com/peircej/psychopy/tree/textbox2
It just keeps being overtaken by bigger priorities. One slight issue with that rendering technique is the question of choosing when to upload each glyph but it isn't too bad unless the font needs to be large.

The above is also faster than pyglet in nearly all cases, including on-the-fly updates, and we can change color for each character etc. The one thing I haven't finished, which I want to do is support text editing properly. The issue with that is that we need to track, while laying out text, row/column numbers so that when someone goes 'up' with the keyboard it goes to the correct position in the (linear) string. But otherwise most of the above is working and superior to pyglet. Oh it will also allow us to add proper right/left/center justification rules which pyglet couldn't handle last I checked.

I could write some text related functions for gltools to make this easier. There's some cases where I need text rendering functionality around PsychoPy without invoking a whole stimulus class.

Closed via #2693

Was this page helpful?
0 / 5 - 0 ratings