Repository: psychopy/psychopy

Issue:
psychopy components can't open [Bug]: 
### PsychoPy Version

2024.1.0

### What OS are your PsychoPy running on?

Windows 11

### Bug Description

`Traceback (most recent call last):
  File "D:\PsychoPy\lib\site-packages\psychopy\app\builder\builder.py", line 3319, in onPluginBtn
    dlg = psychopy.app.plugin_manager.dialog.EnvironmentManagerDlg(self)
  File "D:\PsychoPy\lib\site-packages\psychopy\app\plugin_manager\dialog.py", line 43, in __init__
    self.pluginMgr = PluginManagerPanel(self.notebook, dlg=self)
  File "D:\PsychoPy\lib\site-packages\psychopy\app\plugin_manager\plugins.py", line 258, in __init__
    self.pluginList = PluginBrowserList(self.splitter, stream=dlg.output)
  File "D:\PsychoPy\lib\site-packages\psychopy\app\plugin_manager\plugins.py", line 488, in __init__
    self.populate()
  File "D:\PsychoPy\lib\site-packages\psychopy\app\plugin_manager\plugins.py", line 496, in populate
    items = getAllPluginDetails()
  File "D:\PsychoPy\lib\site-packages\psychopy\app\plugin_manager\plugins.py", line 1270, in getAllPluginDetails
    localPluginDatabase = json.loads(localPluginDatabase)
  File "D:\PsychoPy\lib\json\__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "D:\PsychoPy\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "D:\PsychoPy\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
`

### Expected Behaviour

I want to download the tobii eyetracker plugin and test it, but can't open the component page
![image](https://github.com/psychopy/psychopy/assets/109449633/12ab80a3-7fed-48fe-b533-18603933d9af)


### Steps to Reproduce

1. installed the StandalonePsychoPy-2024.1.0-win64.exe 
2. open psychopy and click the "Get more" in the components
3. can't open and report bug
...


### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/psychopy/app/plugin_manager/plugins.py b/psychopy/app/plugin_manager/plugins.py
--- a/psychopy/app/plugin_manager/plugins.py
+++ b/psychopy/app/plugin_manager/plugins.py
@@ -169,7 +169,7 @@ def icon(self):
                     if ext in pil.registered_extensions():
                         content = requests.get(self._requestedIcon).content
                         writeOut = os.path.join(appPluginCacheDir, fname)
-                        with open(writeOut, 'wb') as f:
+                        with open(writeOut, 'wb', encoding='utf-8') as f:
                             f.write(content)
                         self._icon = utils.ImageData(os.path.join(
                             appPluginCacheDir, fname))
@@ -1253,7 +1253,7 @@ def readLocalPluginDatabase(srcFile):
             return None
         # attempt to parse JSON
         try:
-            with srcFile.open("r") as f:
+            with srcFile.open("r", encoding="utf-8") as f:
                 return json.load(f)
         except json.decoder.JSONDecodeError:
             # if JSON parse fails, return nothing
@@ -1283,7 +1283,7 @@ def deletePluginDlgCache():
         if str(pluginDatabase) != str(localPluginDatabase):
             deletePluginDlgCache()
             # write new contents to file
-            with pluginDatabaseFile.open("w") as f:
+            with pluginDatabaseFile.open("w", encoding='utf-8') as f:
                 json.dump(pluginDatabase, f, indent=True)
 
     elif localPluginDatabase is not None:


Test patch: