1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
.. _usingplugins:
Using Plugins to Extend PsychoPy
================================
Plugins are packages which can be loaded to extend core |PsychoPy|, allowing
third-party developers to add optional features and customizations.
PsychoPy's plugin system functions as a dynamic import mechanism where modules
define some objects (classes, functions, variables) and specify which namespaces
to export them to. This process is handled automatically by the plugin loader
and is more convenient than attempting to do the same using ``import``
statements.
Why use plugins?
----------------
Plugins are the easiest way to extend and modify PsychoPy's default behaviour,
without making permanent changes to the installed program files or contributing
the changes to the |PsychoPy| project. You can use plugins created by others, or
make them yourself for whatever purpose. For instance, plugins can be used to
add new stimulus classes to `psychopy.visual`, or modify the behaviour of
existing classes and modules. This can be leveraged to add new features or to
fix bugs between release cycles. Since plugins are standard Python packages,
changes can be easily applied across multiple systems and shared with the
|PsychoPy| community.
Consider using plugins to distribute code which cannot be contributed to the
main |PsychoPy| project for reasons that may include:
* **Niche use**, not many people use the feature and will add bloat to
|PsychoPy| which increases workload when testing and packaging.
* Uses a **GPL incompatible license or contains proprietary** code. This allows
users to distribute code with any licence they chose and permits compliance
to non-disclosure agreements for companies. Using a plugin allows you to
maintain complete ownership over your code.
* **Requires special or uncommon configurations** to use (software or hardware).
This includes features which are limited to specific operating systems, or
requires hardware which the |PsychoPy| dev team does not have regular access to.
* **Under heavy development** where PsychoPy's release cycle is inadequate to
keep up with changes and bug fixes. Furthermore, the code may not be mature
enough for inclusion with core |PsychoPy|. Plugins provide an excellent way of
field testing features before attempting to contribute it to the main project.
* **Contains changes that can possibly break PsychoPy** which can accidentally
affect existing experiments. If something breaks, users can simply disable the
plugin.
* **Cannot be maintained long-term** by the |PsychoPy| developers.
Where can I find plugins?
-------------------------
Plugins are essentially Python packages and can be distributed, installed, and
used like any other Python library. |PsychoPy| plugin packages can be uploaded to
The Python Package Index (PyPI) and installed using `pip`. You can also
distribute and download plugins as ZIP archives which can be installed or
accessed from a local repository.
Are plugins safe?
-----------------
Like any Python package, plugins are capable of injecting and executing
arbitrary code which can seriously harm your system, data, security and privacy.
Therefore, the following precautions can be taken by users when using plugins:
* Only use plugins that come from reliable and reputable sources. Only obtain
packages from sources explicitly sanctioned by the author and not third-party
websites.
* Use anti-virus software to scan files in plugins which cannot be opened and
read (i.e. compiled binaries) or request the author provide the source code.
* Request a checksum from the plugin author to verify the integrity of the
package you've obtained to detect possible tampering. Plugin authors who make
their packages publicly available should be ready to provide checksum data
associated with their packages to users who request it.
* Audit the source code of plugins yourself (or by a trusted third-party) before
installing a plugin. Ensure that the routines contained in the package appear
to do only what the author describes.
* If concerned about privacy, ensure that the plugin does not contain code that
performs unsolicited file operations, modifications to system settings, or
data transmission over a network (ie. internet). If unsure, request details
from the author of the plugin or have the source code audited.
If you have or find any potential security or privacy issues regarding a plugin
which arise from features that **have not been disclosed by the author**, you
can contact the author regarding the issues and request clarification. **Be
respectful** as the author may not be aware of the issue, believed that what
they were doing was innocuous (eg. collecting anonymous usage data to better the
software), or cannot divulge details about some aspect of their software (due to
a non-disclosure agreement or proprietary third-party interface). If the author
is unable to address your concerns in a timely or satisfactory manner,
discontinue use of the plugin and remove it from your system.
How do I install plugins?
-------------------------
Plugins can be installed either by using ``pip`` or by running the `setup.py`
file in the package. For instance, a plugin with project name `psychopy-plugin`
the author uploaded to the The Python Package Index (PyPI) repository can be
downloaded and installed by calling::
python -m pip install psychopy-plugin
You can also install packages contained in zip/egg files using the same command
but substituting `psychopy-plugin` for the file name::
python -m pip install psychopy-plugin-1.0.win-amd64.zip
How do I use a plugin?
----------------------
A plugin can be loaded by calling the ``psychopy.plugins.loadPlugin()``
function. The name of the plugin to load is provided as a string, which should
reflect the project name of the package. Note that a plugin can override the
effects of other plugins loaded before it. Once a plugin is loaded, it cannot be
unloaded until the Python session is restarted.
Calling ``loadPlugin()`` should preferably happen *after* importing `psychopy`
and all other ``import`` statements for |PsychoPy| modules. An example of loading
a plugin called `psychopy-plugin` looks like this::
import psychopy
import psychopy.plugins as plugins
plugins.loadPlugin('psychopy-plugin')
Some plugins may accept arguments for setup prior to attaching objects to
|PsychoPy|. You can pass positional and keyword arguments to ``loadPlugin()`` if
you wish. Here is an example where we pass arguments to the plugin when loading
it::
plugins.loadPlugin('psychopy-plugin', 9600, debug=True)
You can also have specific plugins loaded automatically when |PsychoPy| starts
by specifying their names in Preferences. This can be done in programmatically
by calling::
from psychopy.preferences import prefs
prefs.general['startUpPlugins'].append('plugin-name')
prefs.saveUserPrefs()
Or by adding the name to "File" > "Preferences" > "General" > "startUpPlugins"
in Builder or Coder. After restarting a |PsychoPy| session, the specified plugins
will be loaded automatically, and the user does not need to call
``loadPlugin()`` to enable them.
.. note::
Plugins which contain Builder components need to be loaded on startup for
the components to appear in Builder.
How do I find installed plugins?
--------------------------------
The ``psychopy.plugins.listPlugins()`` function can be used to find all packages
installed on the system which advertise themselves as |PsychoPy| plugins. The
function returns a list of strings indicating the project names of the plugin
packages. You can then pass each of these strings to ``loadPlugins()`` to load
them into the current session.
As an example, you can check if a plugin named `psychopy-plugin` is installed
using the following code::
import psychopy
import psychopy.plugins as plugins
isInstalled = 'psychopy-plugin' in plugins.listPlugins()
# load it if installed
if isInstalled:
plugins.loadPlugin('psychopy-plugin')
How do I make a plugin?
-----------------------
Have a cool idea you want to share with the world (or at least |PsychoPy| users)?
See :ref:`pluginDevGuide` in the developer documentation section for information
about creating your own plugins.
|