Repository: psychopy/psychopy

Issue:
Possible bug - Builder crashes when typing a dollar sign into a text component
**OS:** Ubuntu 20.04
**PsychoPy version:** 2021.2.2
**Standard Standalone**

**What happens:**
When I type a dollar sign ($) at the beginning of a text component, Builder gives an error and crashes.
If I type the $ at a different position in the box, nothing happens (please, see the gif below):

![Builder_crash_with_dollar_sign](https://user-images.githubusercontent.com/23731464/128643192-cf7e7fef-080e-42d4-8391-eb728c6e0efa.gif)

**Error message:**
> Traceback (most recent call last):
File “/home/flavio/.local/lib/python3.8/site-packages/psychopy/app/builder/dialogs/paramCtrls.py”, line 29, in validate
validate(self, self.valType)
File “/home/flavio/.local/lib/python3.8/site-packages/psychopy/app/builder/dialogs/paramCtrls.py”, line 442, in validate
val = str(obj.GetValue())
RecursionError: maximum recursion depth exceeded while calling a Python object

It happens in a new file - I just have to start Builder and insert a text component.
The same was not happening with the previous version of Psychopy (same OS and machine).

I’m available to run diagnostics.

Cheers!
Flavio





Discussion:
Thank you for reporting this. We'll be looking into it.
I haven't been able to replicate this on macOS, although I'm not sure what aspect would make it a platform-specific bug 🤔 
I'll make a fresh install of Ubuntu and Psychopy to check if I can still see it. I'll report it here as soon as I can.
With a fresh install (and after installing all the updates) I still get the error, but now PsychoPy does not crash (please, see the gif below).

![Psychopy_error_text](https://user-images.githubusercontent.com/23731464/129118077-69213b33-e054-4ee1-915e-2d772fbdb553.gif)

**Error message**

> Traceback (most recent call last):
  File "/home/flavio/.local/lib/python3.8/site-packages/psychopy/app/builder/dialogs/paramCtrls.py", line 29, in validate
    validate(self, self.valType)
  File "/home/flavio/.local/lib/python3.8/site-packages/psychopy/app/builder/dialogs/paramCtrls.py", line 442, in validate
    val = str(obj.GetValue())
RecursionError: maximum recursion depth exceeded while calling a Python object

PS: Sadly, in this installation I don't get my buttons on the right panel anymore...

![No_buttons](https://user-images.githubusercontent.com/23731464/129118468-9a03a4e4-79f9-406b-9744-e4ad72103c36.gif)



The way I install PsychoPy changes the behavior of the error:

- No icons, but also no crash: above installation following [this instructions](https://discourse.psychopy.org/t/unable-to-properly-install-psychopy-on-ubuntu-20-04/12760/8)
- Icons showing nicely, but PsychoPy crashes: the method I describe below

> **Install outdated psychopy from Ubuntu's repository**
> sudo apt install psychopy
> 
> **Install pip3**
> sudo apt install python3-pip
> 
> **Download the lastest wxPython-4 from**
> https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-20.04/
> 
> **Install the downloaded wxPython-4 file**
> pip3 install <path_to_wxPython4_downloaded_file>
> _In my case: pip3 install /home/flavio/Downloads/wxPython-4.1.1-cp38-cp38-linux_x86_64.whl_
> 
> **Install Psychtoolbox bindings**
> sudo apt install libusb-1.0-0-dev portaudio19-dev libasound2-dev
> 
> **Update psychopy using pip3**
> pip3 install -U psychopy
> 
> **Upgrade cryptography - only incompatibility I spotted during the installation**
> pip3 install --upgrade cryptography

This time, I started PsychoPy from the terminal so I could (hopefully) get more information on the error. 
**This is the message I got:**

> RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd pygame 1.9.6
> Hello from the pygame community. https://www.pygame.org/contribute.html
> RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd
> PTB-INFO: Using modified PortAudio V19.6.0-devel, revision unknown
> 03:10:50 PM: Debug: "Shift+Tab" is not supported as a keyboard accelerator with GTK

> (psychopy:15982): Gtk-WARNING **: 15:11:26.114: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
> You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
> You can apply tags and insert marks without invalidating your iterators,
> but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
> will invalidate all outstanding iterators
> Segmentation fault (core dumped)

I hope this helps :)

Please, let me know if I can help testing anything.
@peircej I think we need a tool to check whether package versions installed to the system/current interpreter differ from those we ship with standalone. Since we require specific package versions to get things like movies/audio working, other apps within the environment can break or be broken by installing PsychoPy. At the very least we should enumerate over the packages installed to the environment PsychoPy is running on and display warnings if things differ from what's we bundle with standalone. At least that will give a clue to the user that the weird stuff going on is due to API incompatibility and they should adjust their setup accordingly (e.g., use a virtual python environment).
Getting exactly the same behaviour on Centos 7.  I do use separate virtual Python environments for each version of PsychoPy.
This issue does not happen with previous versions of PsychoPy (eg, 2021.1.4) on the same machine, so not sure if it's a simple dependency issue...

As a temporary workaround, I made the following edit to [python-package-directory]/psychopy/app/builder/dialogs/paramCtrls.py.org:
```
@@ -51,7 +51,8 @@
             valType = "str"
         if valType == "code" or hasattr(self, "dollarLbl"):
             # Set font
-            self.SetFont(self.GetTopLevelParent().app._codeFont.Bold())
+            #self.SetFont(self.GetTopLevelParent().app._codeFont.Bold())
+            self.SetFont(self.GetTopLevelParent().app._mainFont)
         else:
             self.SetFont(self.GetTopLevelParent().app._mainFont)

```
PsychoPy no longer crashes and buttons still working on right panel.
Thank you very much for reporting this, @arnon-weinberg!
The workaround you proposed also fixes the problem in my install of PsychoPy 2021.2.3 (no more errors or crashes) :1st_place_medal: 
@arnon-weinberg Thanks for tracking down the issue and fixing it. Perhaps you could submit a PR with the patch to get credit for your contribution and help others out. 😃 
I can, but it didn't seem like a fix so much as a temporary workaround.  It looks like the intended functionality was to set a different font for code than text in the UI; which this patch effectively disables.  A real fix would get that functionality working under Linux, which I am not sure how to do.
I am glad it helps others for now.
Okay I'll sort it out.

Resolving patch:
diff --git a/psychopy/app/builder/dialogs/paramCtrls.py b/psychopy/app/builder/dialogs/paramCtrls.py
--- a/psychopy/app/builder/dialogs/paramCtrls.py
+++ b/psychopy/app/builder/dialogs/paramCtrls.py
@@ -23,23 +23,22 @@
 from ..localizedStrings import _localizedDialogs as _localized
 
 
-class _ValidatorMixin():
+class _ValidatorMixin:
     def validate(self, evt=None):
-        """Redirect validate calls to global validate method, assigning appropriate valType"""
+        """Redirect validate calls to global validate method, assigning
+        appropriate `valType`.
+        """
         validate(self, self.valType)
 
     def showValid(self, valid):
         """Style input box according to valid"""
         if not hasattr(self, "SetForegroundColour"):
             return
+
         if valid:
-            self.SetForegroundColour(wx.Colour(
-                0, 0, 0
-            ))
+            self.SetForegroundColour(wx.Colour(0, 0, 0))
         else:
-            self.SetForegroundColour(wx.Colour(
-                1, 0, 0
-            ))
+            self.SetForegroundColour(wx.Colour(1, 0, 0))
 
     def updateCodeFont(self, valType):
         """Style input box according to code wanted"""
@@ -49,11 +48,20 @@ def updateCodeFont(self, valType):
         if self.GetName() == "name":
             # Name is never code
             valType = "str"
+
+        fontNormal = self.GetTopLevelParent().app._mainFont
         if valType == "code" or hasattr(self, "dollarLbl"):
             # Set font
-            self.SetFont(self.GetTopLevelParent().app._codeFont.Bold())
+            fontCode = self.GetTopLevelParent().app._codeFont
+            fontCodeBold = fontCode.Bold()
+            if fontCodeBold.IsOk():
+                self.SetFont(fontCodeBold)
+            else:
+                # use normal font if the bold version is invalid on the system
+                self.SetFont(fontCode)
         else:
-            self.SetFont(self.GetTopLevelParent().app._mainFont)
+            self.SetFont(fontNormal)
+
 
 class _FileMixin:
     @property


Test patch: