.. _Usage: Usage ******************************************************************************* This section gives an overview of the general usage of the priint:comet Python API .. _usage.ImportDirectives: Import directives =============================================================================== Usually, Python modules are imported by providing the module or package name: .. code-block:: python :caption: Importing in Python #Native libaries import io import csv #Comet import comet These can be either native built-ins (e.g. io, csv, …), built-ins provided by our implementation (comet) or custom modules which are data pool specific. Imports work like CScript *#include* statements. The CScript interpreter uses a custom callback for processing an #include directive. We are therefore able to implement custom syntax extensions using tokens to fetch an include from a specific data source. These data sources include the current XML-Offline folder, the current Pubserver or SOAP connection or the current SQL connection: .. code-block:: C :caption: Including in CScript #include "internal/text.h" #include "[xml]/actions/10000.crpt" #include "[soap]/actions/10000.crpt" #include "[sql]/select stmt from actions where id = 10000" For Python we want to use the language’s default import system where possible – expanding on that would mean changing the language definition, which we avoid. The default import system however is limited to very specific inputs: - Limited to alphanumeric characters - No *[xml]*, *[sql]*, *[Pubserver]* custom directives to fetch data from the current data connection - No relative or absolute paths The user can work around paths with executing a more verbose import: .. code-block:: python :caption: Importing from explicit file path in Python import importlib.util spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py") foo = importlib.util.module_from_spec(spec) spec.loader.exec_module(foo) foo.MyClass() This however does not solve the problem with our data pool related tokens. Since Python exposes the importer module itself and can execute it at runtime, we can provide custom functionality for importing modules from special paths: :py:meth:`comet.pyImport` This function is a simple wrapper to the import module which accepts, parses and provides necessary preparation for importing modules from said data pools. The result of the function is the imported module: .. code-block:: python :caption: Importing a Python library from an datapool specific path myModule = comet.pyImport('[xml]/modules/myModule.py') myModule.helloWorld() The following datapool specific imports are supported: .. table:: Datapool imports :class: comet alternating-rows :width: 100% :widths: 15 40 30 25 +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | Syntax | Description | Comments | Example | +====================================+===========================================================================+===========================================================================+=======================================================================+ | **XML files** | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | | \[xml\]/pID sID | Import via the XML file panelstatements.xml. | Include will only be executed where there is a valid XML data link. | *comet.pyImport('.xml\_/123, 4')* | | | /pID sID | | | with Panel statement 123 | | | .xml\_/pID sID | First, the panel statement will be loaded with the ID *pID*. | | *"includes.xml" select stmt node includes.include where id = ?* | | | | | | | | | \[xml]\/pID sName | The found command will then be executed. | | Result of the Includes is *stmt* from *includes.xml* with the ID 4. | | | /pID sName | The first result column of this command must be a string. | | | | | xml\_/pID sName | | | | | | In the where-condition of the command must contain exactly one '?', | | | | | this '?' will be replaced by *sID* or *sName*. | | | | | | | | | | The name may be enclosed with quotation marks but this is not necessary. | | | | | The string that is found is the result of the Includes. | | | +------------------------------------+---------------------------------------------------------------------------+ +-----------------------------------------------------------------------+ | | \[xml\]/path | Import the coded script file from the XML data folder. | | *comet.pyImport('.xml\_/actions/1000.crpt')* | | | /path | The path is specified relative the XML data folder. | | | | | .xml\_/path | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | **Database** | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | | [sql]/statement | Import from a database. | Include will only be executed where there is a valid database connection. | *comet.pyImport('.sql\_/select stmt from includes where id = 12')* | | | /statement | | The first result row of the statement must be a string or CLOB. | | | | .sql_/statement | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | **SOAP** | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | | \[soap\]/id | Import from a SOAP connection. | Include will only be executed where there is a valid SOAP connection. | *comet.pyImport('.soap\_/mystuff.cpp)'* | | | /id | | | | | | .soap\_/id | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | **Pubserver** | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | \[pubserver\]/LibraryIdentifier.h | Import of a *script library* | Include is only available when connected to a PubServer | *comet.pyImport('\[pubserver\]/ProjectLib.h)'* | | | | | | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ | \[pubserver\]/plugin/PluginName.c | Import of Python-Code for calling Java methods of a PubServer | Include is only available when connected to a PubServer | *comet.pyImport('\[pubserver\]/plugins.c)'* | | | Plugin directly from the Python. | | | | | | Take care to use the extension .c here. | | | | *PluginName* is the registration name of the Java Plugin. | | | | | | | | +------------------------------------+---------------------------------------------------------------------------+ +-----------------------------------------------------------------------+ | \[pubserver\]/plugins.c | Import of cScript-Code for calling Java methods of all | | *comet.pyImport('\[pubserver\]/stdlib.c)'* | | | available PubServer Plugins. | | | | | | | | | | Please note: plugins.c is just a meta include, which contains | | | | | include directives for all available Java plug-ins. | | | | | | | | +------------------------------------+---------------------------------------------------------------------------+---------------------------------------------------------------------------+-----------------------------------------------------------------------+ .. _usage.funcvars: Function variables =============================================================================== Function variables follow the same syntax as in other script languages and statements. Unlike in CScript, the function variable syntax is a Python comment and the definition is thefore not removed during script execution, resulting in line numbers still being consistent when error messages come up. There are two possible ways to access function variables in your Python scripts. Suppose you have the following function variable definition: .. code-block:: python #pragma var "gTextColor//Text Color" "kBlack//Black" "kRed//Red" "kOrange//Orange" **Access as member of the comet module:** Any function variable is added as a direct member to the :py:mod:`comet` module itself by name. .. code-block:: python import comet colorValue = comet.gTextColor **Access using the global function variable list of the comet module:** Additionally, the :py:mod:`comet` module keeps a dictionary of function variables and their values. **Keys and values are always of type** :py:class:`str` .. code-block:: python import comet colorValue = comet.gFuncVars['gTextColor'] Note that function variable names may clash with built-in constants, modules or functions. In this case your script will fail to run. It is generally a good idea to prefix you function variable names with a unique, non-clashing identifier. .. _usage.placeholderSync: Placeholder synchronization =============================================================================== The module allows setting a '**new value**' and an '**old value**', which are only evaluated during synchronization calls. Whether or not the script is run in a synchronization call be determined using :py:func:`comet.getContext()` which then returns :py:data:`comet.kContextPlaceHolderSync` if that is the case. The **new value** of a placeholder is the **data source** value which is determined for the automatic synchronization state of a placeholder (sync action ID = -1) and the value which is displayed in the 'ToDo' panel. Note that no changes may be made to the document when the script is executed as a synchronization call. In particular, no text may be changed through functions like :py:meth:`.CFrame.replace` and the like , since here the load scripts can be called again automatically - which can lead to endless loops. The **old value** is the **document** value which is displayed in the document value display of the 'ToDo' panel. Normally this value is determined by comet automatically by extracting the value directly from the document. In certain rare cases it may be necessary to provide a different value here. Both new and old values can be set by calling :py:func:`comet.setOutput` with the keys *'gNewValue'* or *'gOldValue'*, respectively. See here for more information: :py:ref:`ENV-kContextPlaceHolderSync` .. _usage.RepeatingElements: Repeating Elements =============================================================================== When building repeating elements there is a number of output variables which need to be filled during the build action of the placeholder. .. list-table:: :header-rows: 1 :class: comet alternating-rows constants * - Variable Name - Data type - Description * - gElements - :py:class:`list` [:py:class:`.CElement`] - List of products to build * - gFormat - :py:class:`str` - Format string The same build action can be used for synchronization purposes for repeating elements. In this case the variables in the lower table can be filled to customize the synchronization behavior. .. list-table:: :header-rows: 1 :class: comet alternating-rows constants :widths: 20 20 60 * - Variable Name - Data type - Description * - gPrivateSync - :py:class:`bool` - Set the value to True, to enable your customized sync. Otherwise the default behavior is executed. * - gState - :py:class:`int` - The result state of the repeating element. Default is 1 (Okay) * - gSyncChanged - :py:class:`bool` - When manually setting the sync state, set this variable to True * - gOldValue - :py:class:`str` - The string is shown in the ToDo panel as the **Document** text. * - gNewValue - :py:class:`str` - The string is shown in the ToDo panel as the **Data pool** text. .. _usage.CallingOtherScripts: Calling other scripts =============================================================================== It is possible to call other script types from Python. For this purpose there are two script functions available: :py:func:`comet.runJavaScript` and :py:func:`comet.runCScript` The possibility on calling these depends on the host software: .. container:: priint-block |indd| **JavaScript**, **CScript** .. container:: priint-block |comet-pdf| |illu| **CScript** CScript ------------------------------------------------------------------------------- CScript calls can be made using the function :py:func:`comet.runCScript`. This function provides automatic environment variable conversion - environment variables from comet which are available in the executing Python script are also available in the CScript. Which variables are available and get converted depend on the execution context and are listed in the section :ref:`EnvironmentVariables`. :priint-important:`Only input variables are automatically converted.` .. container:: priint-block **Function variables** are a special case since they provide the variable key and value as global variables, aswell as both **gFuncVarNames** and **gFuncVarValues** of type *StringList*. Additionally, it is possible to provide custom variables - using the *items* parameter - so you can easily access your Python data in CScript. The following table shows which types are supported and which result type to expect. .. list-table:: Python ➞ CScript :header-rows: 1 :class: comet alternating-rows * - Source data type - Target data type - Availability * - :py:class:`int` - int - |indd| |comet-pdf| |illu| * - :py:class:`float` - float - |indd| |comet-pdf| |illu| * - :py:class:`str` - `String <../cscript/String.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CBook` - `ItemRef <../cscript/ItemRef.html>`__ - |indd| * - :py:class:`.CDocument` - `ItemRef <../cscript/ItemRef.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CElement` - `Element <../cscript/Element.html>`__ - |indd| |comet-pdf| * - :py:class:`.CFrame` - `ItemRef <../cscript/ItemRef.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CIDType` - `IDType <../cscript/IDType.html>`__ - |indd| |comet-pdf| * - :py:class:`.CPageItem` - `ItemRef <../cscript/ItemRef.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CParameter` - `Parameter <../cscript/Parameter.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CPlanning` - `Planning <../cscript/Planning.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CProduct` - `Product <../cscript/Product.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CPublication` - `Publication <../cscript/Publication.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CPublicationType` - `PublicationType <../cscript/PublicationType.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CRect` - `Rect <../cscript/Rect.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CTable` - `ItemRef <../cscript/ItemRef.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`.CWorkflowStatus` - `WorkflowStatus <../cscript/WorkflowStatus.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`int`] - `List <../cscript/List.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`float`] - `FloatList <../cscript/FloatList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`str`] - `StringList <../cscript/StringList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`bool`] - `List <../cscript/List.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CFrame`] - `ItemList <../cscript/ItemList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CPageItem`] - `ItemList <../cscript/ItemList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CTable`] - `ItemList <../cscript/ItemList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CElement`] - `ElementList <../cscript/ElementList.html>`__ - |indd| |comet-pdf| * - :py:class:`list` [:py:class:`.CIDType`] - `IDTypeList <../cscript/IDTypeList.html>`__ - |indd| |comet-pdf| * - :py:class:`list` [:py:class:`.CParameter`] - `ParameterList <../cscript/ParameterList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CPlanning`] - `PlanningList <../cscript/PlanningList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CProduct`] - `ProductList <../cscript/ProductList.html>`__ - |indd| |comet-pdf| * - :py:class:`list` [:py:class:`.CPublication`] - `PublicationList <../cscript/PublicationList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CPublicationType`] - `PublicationTypeList <../cscript/PublicationTypeList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CRect`] - `RectList <../cscript/RectList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`list` [:py:class:`.CWorkflowStatus`] - `WorkflowStatusList <../cscript/WorkflowStatusList.html>`__ - |indd| |comet-pdf| |illu| * - :py:class:`dict` [:py:class:`str`, :py:class:`str`] - `KeyValues <../cscript/KeyValues.html>`__ - |indd| |comet-pdf| |illu| :priint-important:`All other variable types are ignored and not automatically converted.` JavaScript ------------------------------------------------------------------------------- When calling **JavaScript** from Python you may want to provide additional, non-primitive environment variables to your script. :py:func:`comet.runJavaScript` has an additional parameter called *items* which can be used to provide a list of certain Python objects which are then additionally available in the executed script. For each object which belongs to a document, two environment variables are created: gItemRef\ **N** and gDocRef\ **N** where **N** is the nth object in the list, starting at **1**. e.g. when a list of three :py:class:`.CFrame` objects is provided to the items parameter you get six global variables of type *ItemRef* in your CScript: **gItemRef1, gItemRef2, gItemRef3, gDocRef1, gDocRef2, gDocRef3** When the provided object in *items* has no document, the creation of the gDocRef\ **N** parameter is omitted, but the **N** suffix is still increased so that when e.g. **gItemRef1** has no **gDocRef** equivalent, **gDocRef2** is the next candidate for the next document variable name. Vice versa, when a provided object in *items* is a document itself, only the next **gDocRef** variable is created, and the **gItemRef** variable is omitted. The following table shows all allowed types for entries in the *items* list: .. list-table:: Python ➞ JavaScript :header-rows: 1 :class: comet alternating-rows * - Source data type - Target data type - Creates gItemRefN - Creates gDocRefN * - :py:class:`.CFrame` - PageItem - |check| - |check| * - :py:class:`.CDocument` - Document - |x| - |check| * - :py:class:`.CTable` - Table - |check| - |check| .. include:: EnvironmentVariables.inc