Creando una extensión
- ¿Qué es una extensión de OpenSesame?
- Archivos relevantes
- Información de extensión
- Escribiendo el código de extensión
- Escuchar eventos
- Creando un paquete y subiéndolo a pypi
- Ejemplos
- Resumen de eventos
- cambio_experimento
- cambio_elemento
- cerrar
- eliminar_elemento
- latido_corazon
- ide_saltar_a_linea
- ide_nuevo_archivo
- ide_guardar_archivo_actual
- deteccion_anotaciones_imagen
- excepcion_jupyter_ocurrida
- finalizacion_ejecucion_jupyter
- resultado_texto_ejecucion_jupyter
- inicio_ejecucion_jupyter
- interrupcion_jupyter
- reiniciar_jupyter
- jupyter_run_code
- jupyter_run_system_command
- jupyter_show_prompt
- jupyter_write
- new_item
- new_linked_copy
- notify
- open_experiment
- open_item
- pause_experiment
- prepare_change_experiment
- prepare_delete_item
- prepare_open_item
- prepare_purge_unused_items
- prepare_regenerate
- prepare_rename_item
- purge_unused_items
- pyqode_clear_breakpoints
- pyqode_resume_auto_backend_restart
- pyqode_select_indentation_mode
- pyqode_suspend_auto_backend_restart
- regenerate
- register_editor
- rename_item
- resume_experiment
- run_experiment_canceled
- save_experiment
- startup
- unregister_editor
¿Qué es una extensión de OpenSesame?
Las extensiones agregan funcionalidad arbitraria a la interfaz de usuario de OpenSesame. Por ejemplo, una extensión puede agregar una nueva entrada a la barra de herramientas principal o al menú. (Para agregar funcionalidad que se pueda utilizar en experimentos, necesita un plugin.)
Archivos relevantes
Una o más extensiones se agrupan en un paquete de extensión, que siempre es un subpaquete de opensesame_extensions
(que a su vez es un llamado paquete de espacio de nombres implícito, pero ese es un detalle técnico que no es muy importante). Supongamos que su paquete de extensión se llama example
y que contiene una única extensión (puede haber más) llamada example_extension
. Esto correspondería a la siguiente estructura de archivos y carpetas:
opensesame_extensions/
example/
__init__.py # puede estar vacío pero debe existir
example_extension/
__init__.py # contiene información de extensión
example_extension.py # contiene clase de extensión
Información de extensión
La información de la extensión se define en el __init__.py
del módulo de extensión, por lo que en nuestro ejemplo este es opensesesame_extensions/example/example_extension/__init__.py
.
"""Una cadena de documentación con una descripción de la extensión"""
# Un nombre de icono estándar
# - <https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html>
icon = 'applications-accessories'
# La etiqueta y el tooltip se usan para crear la acción predeterminada, que es
# insertar en el menú y / o barra de herramientas (o ninguno)
label = "Extensión de ejemplo"
tooltip = "Ejemplo de información sobre herramientas"
menu = {
"index": -1,
"separator_before": True,
"separator_after": True,
"submenu": "Ejemplo"
}
toolbar = {
"index": -1,
"separator_before": True,
"separator_after": True
}
# La configuración se almacena de forma persistente en el objeto cfg
settings = {
"example_setting": "valor de ejemplo"
}
Una extensión puede aparecer en el menú o en la barra de herramientas principal de OpenSesame. Esto requiere que defina varios campos en __init__.py
como se muestra arriba:
- La
label
es el texto que aparecerá en el menú. - El
icon
es un nombre de icono compatible con freedesktop que especifica el icono que aparecerá en el menú y / o barra de herramientas. - El
index
indica la posición de la extensión en el menú / barra de herramientas, y funciona como un índice delist
. Es decir, los valores negativos son relativos a la última entrada, donde -1 coloca su extensión al final.
Para que su extensión responda a la activación del menú / barra de herramientas, implemente el método activate()
como se muestra a continuación en el código de extensión.
Escribiendo el código de extensión
El código principal de extensión se coloca en [extension_name].py
. Este archivo generalmente contiene solo una clase llamada [ExtensionName].py
, es decir, una clase con el equivalente CamelCase del nombre del plugin, que hereda libqtopensesame.extensions.BaseExtension
. Entonces, una clase de extensión básica (no funcional) se ve así:
from libopensesame.py3compat import *
from libopensesame.oslogging import oslogger
from libqtopensesame.extensions import BaseExtension
class ExampleExtension(BaseExtension):
"""Una extensión de ejemplo que enumera varios eventos comunes. El nombre de la clase
debe ser la versión CamelCase del folder_name y file_name. Entonces, en
este caso, tanto la carpeta de extensión (que es un paquete de Python) como el
archivo .py (que es un módulo de Python) se llaman example_extension, mientras que
la clase se llama ExampleExtension.
"""
def activate(self):
oslogger.debug('se activó la extensión example_extension')
def event_save_experiment(self, path):
oslogger.debug(f'Se disparó el evento: save_experiment(path={path})')
# Vea el código fuente de example_extension para obtener más oyentes de eventos
Escuchar eventos
OpenSesame dispara eventos cuando ocurre algo importante. Por ejemplo, el evento save_experiment
se dispara cuando se guarda un experimento. Para que su extensión escuche un evento, simplemente implemente un método con el nombre event_[nombre del evento]
como se muestra arriba.
Tenga en cuenta que algunos eventos toman argumentos de palabras clave, como path
en el caso de save_experiment
. La firma de palabras clave de su función debe coincidir con la firma de palabras clave esperada. Consulte la descripción general de eventos a continuación para obtener una lista completa de eventos y palabras clave esperadas.
Creando un paquete y subiéndolo a pypi
Crear un paquete de extensión y cargarlo en pypi
funciona de la misma manera que lo hace para los complementos:
- https://osdoc.cogsci.nl/4.0/es/dev/plugin
- https://github.com/open-cogsci/opensesame-extension-example
Ejemplos
Para un ejemplo funcional, consulte:
Otros ejemplos se pueden encontrar en la carpeta opensesame_extensions
del código fuente de OpenSesame:
Resumen de eventos
Esta descripción general enumera todos los eventos que se disparan en algún lugar del código, y que su extensión puede escuchar implementando las funciones event_[nombredelevento]()
correspondientes.
cambio_experimento
Disparado en: general_properties.py
extension_manager.fire(u'cambio_experimento')
cambio_elemento
Disparado en: sequence.py
extension_manager.fire(u'cambio_elemento', nombre=self.name)
Disparado en: qtitem.py
extension_manager.fire(u'cambio_elemento', nombre=self.name)
Disparado en: loop.py
extension_manager.fire(u'cambio_elemento', nombre=self.name)
cerrar
Disparado en: qtopensesame.py
extension_manager.fire(u'cerrar')
eliminar_elemento
Disparado en: qtitem_store.py
extension_manager.fire(u'eliminar_elemento', nombre=nombre)
latido_corazon
Disparado en: multiprocess_runner.py
extension_manager.fire(u'latido_corazon')
ide_saltar_a_linea
Disparado en: SymbolSelector.py
extension_manager.fire('ide_saltar_a_linea', lineno=lineno)
Disparado en: OpenSesameIDE.py
extension_manager.fire('ide_saltar_a_linea', lineno=line_number)
ide_nuevo_archivo
Disparado en: JupyterNotebook.py
extension_manager.fire(u'ide_nuevo_archivo', fuente=code, ext=ext)
ide_guardar_archivo_actual
Disparado en: OpenSesameIDE.py
extension_manager.fire('ide_guardar_archivo_actual')
deteccion_anotaciones_imagen
Disparado en: JupyterNotebook.py
extension_manager.fire(u'deteccion_anotaciones_imagen', code=code)
excepcion_jupyter_ocurrida
Disparado en: transparent_jupyter_widget.py
extension_manager.fire('excepcion_jupyter_ocurrida')
finalizacion_ejecucion_jupyter
Disparado en: transparent_jupyter_widget.py
extension_manager.fire('finalizacion_ejecucion_jupyter')
resultado_texto_ejecucion_jupyter
Disparado en: transparent_jupyter_widget.py
extension_manager.fire('resultado_texto_ejecucion_jupyter', texto=texto)
inicio_ejecucion_jupyter
Disparado en: transparent_jupyter_widget.py
extension_manager.fire('inicio_ejecucion_jupyter')
interrupcion_jupyter
Disparado en: OpenSesameIDE.py
extension_manager.fire(u'interrupcion_jupyter')
reiniciar_jupyter
Disparado en: console_bridge.py
extension_manager.fire(u'jupyter_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire(u'jupyter_restart')
jupyter_run_code
Disparado en: menubar.py
extension_manager.fire('jupyter_run_code',
code=command)
jupyter_run_system_command
Disparado en: JupyterNotebook.py
extension_manager.fire('jupyter_run_system_command', cmd=cmd)
jupyter_show_prompt
Disparado en: console_bridge.py
extension_manager.fire(u'jupyter_show_prompt')
jupyter_write
Disparado en: console_bridge.py
extension_manager.fire(u'jupyter_write', msg=s)
new_item
Disparado en: tree_overview.py
extension_manager.fire(u'new_item', name=item.name,
_type=item.item_type)
new_linked_copy
Disparado en: tree_overview.py
extension_manager.fire('new_linked_copy', name=item_name)
notify
Disparado en: sequence.py
extension_manager.fire(u'notify',
message=_(u'Sequence contains non-existing item: %s')
Disparado en: qtitem.py
extension_manager.fire(u'notify',
message=_(u'"%s" is set to a variable or '
u'unknown value and can only be edited through '
u'the script.')
Disparado en: qtitem.py
extension_manager.fire(u'notify',
message=_(u'"%s" is defined using '
'variables and can only be edited through the '
'script.')
Disparado en: qtitem.py
extension_manager.fire(u'notify',
message=_(u'"%s" is defined using '
u'variables or has an invalid value, and can only be '
u'edited through the script.')
Disparado en: logger.py
extension_manager.fire(u'notify',
message=_(u'You have multiple unlinked loggers. This can lead to messy log files.')
Disparado en: sketchpad_widget.py
extension_manager.fire(u'notify', message=notification,
category=u'info')
open_experiment
Disparado en: qtopensesame.py
extension_manager.fire(u'open_experiment', path=path)
open_item
Disparado en: qtitem.py
extension_manager.fire(u'open_item', name=self.name)
pause_experiment
Disparado en: base_runner.py
extension_manager.fire(u'pause_experiment')
prepare_change_experiment
Disparado en: general_properties.py
extension_manager.fire(u'prepare_change_experiment')
prepare_delete_item
Disparado en: qtitem_store.py
extension_manager.fire(u'prepare_delete_item', name=name)
prepare_open_item
Disparado en: qtitem.py
extension_manager.fire(u'prepare_open_item', name=self.name)
prepare_purge_unused_items
Disparado en: unused_widget.py
extension_manager.fire(u'prepare_purge_unused_items')
prepare_regenerate
Disparado en: qtopensesame.py
extension_manager.fire(u'prepare_regenerate')
prepare_rename_item
Disparado en: qtitem_store.py
extension_manager.fire(u'prepare_rename_item', from_name=from_name,
to_name=to_name)
purge_unused_items
Disparado en: unused_widget.py
extension_manager.fire(u'purge_unused_items')
pyqode_clear_breakpoints
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_clear_breakpoints')
pyqode_resume_auto_backend_restart
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_resume_auto_backend_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_resume_auto_backend_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_resume_auto_backend_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_resume_auto_backend_restart')
pyqode_select_indentation_mode
Disparado en: menubar.py
extension_manager.fire('pyqode_select_indentation_mode')
pyqode_suspend_auto_backend_restart
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_suspend_auto_backend_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_suspend_auto_backend_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_suspend_auto_backend_restart')
Disparado en: OpenSesameIDE.py
extension_manager.fire('pyqode_suspend_auto_backend_restart')
regenerate
Disparado en: qtopensesame.py
extension_manager.fire(u'regenerate')
Disparado en: qtopensesame.py
extension_manager.fire(u'regenerate')
register_editor
Disparado en: qtplugin.py
extension_manager.fire(u'register_editor', editor=editor)
rename_item
Disparado en: qtitem_store.py
extension_manager.fire(u'rename_item', from_name=from_name,
to_name=to_name)
resume_experiment
Disparado en: base_runner.py
extension_manager.fire(u'resume_experiment')
run_experiment_canceled
Disparado en: base_runner.py
extension_manager.fire('run_experiment_canceled')
save_experiment
Disparado en: qtopensesame.py
extension_manager.fire(u'save_experiment', path=self.current_path)
startup
Disparado en: qtopensesame.py
extension_manager.fire(u'startup')
unregister_editor
Disparado en: OpenSesameIDE.py
extension_manager.fire('unregister_editor', editor=editor)