cwl_utils.sandboxjs
===================

.. py:module:: cwl_utils.sandboxjs

.. autoapi-nested-parse::

   Safe execution of CWL Expressions in a NodeJS sandbox.



Attributes
----------

.. autoapisummary::

   cwl_utils.sandboxjs.default_timeout
   cwl_utils.sandboxjs.seg_symbol
   cwl_utils.sandboxjs.seg_single
   cwl_utils.sandboxjs.seg_double
   cwl_utils.sandboxjs.seg_index
   cwl_utils.sandboxjs.segments
   cwl_utils.sandboxjs.segment_re
   cwl_utils.sandboxjs.param_str
   cwl_utils.sandboxjs.param_re


Classes
-------

.. autoapisummary::

   cwl_utils.sandboxjs.JSEngine
   cwl_utils.sandboxjs.NodeJSEngine
   cwl_utils.sandboxjs.QuickJSEngine


Functions
---------

.. autoapisummary::

   cwl_utils.sandboxjs.code_fragment_to_js
   cwl_utils.sandboxjs.linenum
   cwl_utils.sandboxjs.stdfmt
   cwl_utils.sandboxjs.get_js_engine
   cwl_utils.sandboxjs.set_js_engine
   cwl_utils.sandboxjs.check_js_threshold_version
   cwl_utils.sandboxjs.exec_js_process
   cwl_utils.sandboxjs.new_js_proc


Module Contents
---------------

.. py:data:: default_timeout
   :type:  float
   :value: 20


   Default number of seconds to wait while running a javascript engine.


.. py:data:: seg_symbol
   :value: '\\w+'


.. py:data:: seg_single
   :value: "\\['([^']|\\\\')+'\\]"


.. py:data:: seg_double
   :value: '\\["([^"]|\\\\")+"\\]'


.. py:data:: seg_index
   :value: '\\[[0-9]+\\]'


.. py:data:: segments
   :value: '(\\.\\w+|\\[\'([^\']|\\\\\')+\'\\]|\\["([^"]|\\\\")+"\\]|\\[[0-9]+\\])'


.. py:data:: segment_re

.. py:data:: param_str
   :value: '\\((\\w+)(\\.\\w+|\\[\'([^\']|\\\\\')+\'\\]|\\["([^"]|\\\\")+"\\]|\\[[0-9]+\\])*\\)$'


.. py:data:: param_re

.. py:function:: code_fragment_to_js(jscript, jslib = '')

.. py:function:: linenum(fn)

.. py:function:: stdfmt(data)

.. py:class:: JSEngine

   Bases: :py:obj:`abc.ABC`

   .. autoapi-inheritance-diagram:: cwl_utils.sandboxjs.JSEngine
      :parts: 1


   Helper class that provides a standard way to create an ABC using
   inheritance.


   .. py:method:: eval(scan, jslib = '', timeout = default_timeout, force_docker_pull = False, debug = False, js_console = False, container_engine = 'docker', **kwargs)
      :abstractmethod:



   .. py:method:: regex_eval(parsed_string, remaining_string, current_value, **kwargs)

      Walk a parameter reference without a javascript engine (pure Python).



.. py:class:: NodeJSEngine(have_node_slim = False, minimum_node_version_str = '0.10.26', process_finished_str = 'r1cepzbhUTxtykz5XTC4\n')

   Bases: :py:obj:`JSEngine`

   .. autoapi-inheritance-diagram:: cwl_utils.sandboxjs.NodeJSEngine
      :parts: 1


   Helper class that provides a standard way to create an ABC using
   inheritance.


   .. py:attribute:: localdata


   .. py:attribute:: have_node_slim
      :type:  bool
      :value: False



   .. py:attribute:: minimum_node_version_str
      :type:  str
      :value: '0.10.26'



   .. py:attribute:: process_finished_str
      :type:  str
      :value: Multiline-String

      .. raw:: html

         <details><summary>Show Value</summary>

      .. code-block:: python

         """r1cepzbhUTxtykz5XTC4
         """

      .. raw:: html

         </details>




   .. py:attribute:: processes_to_kill
      :type:  Deque[subprocess.Popen[str]]


   .. py:method:: __del__()


   .. py:method:: check_js_threshold_version(working_alias)

      Check if the nodeJS engine version on the system with the allowed minimum version.

      https://github.com/nodejs/node/blob/master/CHANGELOG.md#nodejs-changelog



   .. py:method:: exec_js_process(js_text, timeout = default_timeout, js_console = False, context = None, force_docker_pull = False, container_engine = 'docker')

      Run a javascript text.

      :param timeout: Max number of seconds to wait.
      :returns: A tuple of the return code, stdout, and stderr of the javascript
                engine invocation.



   .. py:method:: new_js_proc(js_text, force_docker_pull = False, container_engine = 'docker')

      Return a subprocess ready to submit javascript to.



   .. py:method:: eval(scan, jslib = '', timeout = default_timeout, force_docker_pull = False, debug = False, js_console = False, container_engine = 'docker', **kwargs)


.. py:class:: QuickJSEngine(qjs_path = 'qjs')

   Bases: :py:obj:`JSEngine`

   .. autoapi-inheritance-diagram:: cwl_utils.sandboxjs.QuickJSEngine
      :parts: 1


   Evaluate CWL javascript fragments with the ``qjs`` interpreter.

   QuickJS starts in about a millisecond, so unlike :py:class:`NodeJSEngine`
   no persistent process or wire protocol is needed: each evaluation runs in
   one short-lived ``qjs`` subprocess.  The container fallback keyword
   arguments accepted by the NodeJS engine (``force_docker_pull``,
   ``container_engine``) are accepted and ignored; ``js_console`` is not
   supported.


   .. py:attribute:: qjs_path
      :value: 'qjs'



   .. py:method:: check_js_threshold_version(working_alias = None)

      Check that the qjs interpreter supports the features this engine needs.

      QuickJS distributions do not share a version scheme (the original
      QuickJS uses dates while quickjs-ng uses semantic versions), so
      rather than parsing version strings this probes the interpreter
      with a small script exercising the features the engine relies on:
      eval() completion values, globalThis, Object.assign, JSON, and
      print. A missing or broken interpreter fails the probe.



   .. py:method:: eval(scan, jslib = '', timeout = default_timeout, force_docker_pull = False, debug = False, js_console = False, container_engine = 'docker', **kwargs)


   .. py:method:: exec_js_process(js_text, timeout = default_timeout, js_console = False, context = None, force_docker_pull = False, container_engine = 'docker')

      Run a javascript text in a fresh qjs subprocess.

      The ``context`` script, when given, is evaluated first and the
      properties of its completion value become global variables for
      ``js_text``, mirroring how cwlNodeEngineWithContext.js applies
      ``vm.runInNewContext(js_text, context)``.

      :param timeout: Max number of seconds to wait.
      :returns: A tuple of the return code, stdout, and stderr of the
                javascript engine invocation.  A timeout is reported as
                return code -1.



.. py:function:: get_js_engine()

   Return the process-wide JS engine, creating it on first use.

   The engine is chosen by the ``CWL_JS_ENGINE`` environment variable
   (``node`` or ``quickjs``); when it is unset, QuickJS is preferred if a
   usable ``qjs`` executable is found on the PATH, NodeJS otherwise.
   Engines installed with :py:func:`set_js_engine` take precedence.


.. py:function:: set_js_engine(js_engine)

.. py:function:: check_js_threshold_version(*args, **kwargs)

.. py:function:: exec_js_process(*args, **kwargs)

   Run a javascript text.

   :param timeout: Max number of seconds to wait.
   :returns: A tuple of the return code, stdout, and stderr of the javascript
             engine invocation.


.. py:function:: new_js_proc(*args, **kwargs)

