# pyFormex scripting

While the pyFormex GUI provides some means for creating and transforming geometry, its main purpose and major strength is the powerful scripting language. It offers you unlimited possibilities to do whatever you want and to automize the creation of geometry up to an unmatched level.

Currently pyFormex provides two mechanisms to execute user applications: as a script, or as an app. The main menu bar of the GUI offers two menus reflecting this. While there are good reasons (of both historical and technical nature) for having these two mechanisms, the fist time user will probably not be interested in studying the precise details of the differences between the two models. It suffices to know that the script model is well suited for small, quick applications, e.g. often used to test out some ideas. As your application grows larger and larger, you will gain more from the app model. Both require that the source file(s) be correctly formatted Python scripts. By obeing some simple code structuring rules, it is even possible to write source files that can be executed under either of the two models. The pyFormex template script as well as the many examples coming with pyFormex show how to do it.

## Scripts

A pyFormex script is a simple Python source script in a file (with ‘.py’ extension), which can be located anywhere on the filesystem. The script is executed inside pyFormex with an `exec` statement. pyFormex provides a collection of global variables to these scripts: the globals of module `gui.draw` if the script is executed with the GUI, or those from the module `script` if pyformex was started with `--nogui`. Also, the global variable `__name__` is set to either ‘draw’ or ‘script’, accordingly. The automatic inclusion of globals has the advantage that the first time user has a lot of functionality without having to know what he needs to import.

Every time the script is executed (e.g. using the start or rerun button), the full source code is read, interpreted, and executed. This means that changes made to the source file will become directly available. But it also means that the source file has to be present. You can not run a script from a compiled (`.pyc`) file.

## Apps

A pyFormex app is a Python module. It is usually also provided a Python source file (`.py`), but it can also be a compiled (`.pyc`) file. The app module is loaded with the `import` statement. To allow this, the file should be placed in a directory containing an ‘__init__.py’ file (marking it as a Python package directory) and the directory should be on the pyFormex search path for modules (which can be configured from the GUI App menu).

Usually an app module contains a function named ‘run’. When the application is started for the first time (in a session), the module is loaded and the ‘run’ function is executed. Each following execution will just apply the ‘run’ function again.

When loading module from source code, it gets compiled to byte code which is saved as a `.pyc` file for faster loading next time. The module is kept in memory until explicitely removed or reloaded (another `import` does not have any effect). During the loading of a module, executable code placed in the outer scope of the module is executed. Since this will only happen on first execution of the app, the outer level should be seen as initialization code for your application.

The ‘run’ function defines what the application needs to perform. It can be executed over and over by pushing the ‘PLAY’ button. Making changes to the app source code will not have any effect, because the module loaded in memory is not changed. If you need the module to be reloaded and the initialization code to be rerun use the ‘RERUN’ button: this will reload the module and execute ‘run’.

While a script is executed in the environment of the ‘gui.draw’ (or ‘script’) module, an app has its own environment. Any definitions needed should therefore be imported by the module.

## Common script/app template

The template below is a common structure that allows this source to be used both as a script or as an app, and with almost identical behavior.

>      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
>     #
>     ##
>     ##  Copyright (C) 2011 John Doe (j.doe@somewhere.org)
>     ##  Distributed under the GNU General Public License version 3 or later.
>     ##
>     ##  This program is free software: you can redistribute it and/or modify
>     ##  it under the terms of the GNU General Public License as published by
>     ##  the Free Software Foundation, either version 3 of the License, or
>     ##  (at your option) any later version.
>     ##
>     ##  This program is distributed in the hope that it will be useful,
>     ##  but WITHOUT ANY WARRANTY; without even the implied warranty of
>     ##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>     ##  GNU General Public License for more details.
>     ##
>     ##  You should have received a copy of the GNU General Public License
>     ##  along with this program.  If not, see http://www.gnu.org/licenses/.
>     ##

>     """pyFormex Script/App Template

>     This is a template file to show the general layout of a pyFormex
>     script or app.

>     A pyFormex script is just any simple Python source code file with
>     extension '.py' and is fully read and execution at once.

>     A pyFormex app can be a '.py' of '.pyc' file, and should define a function
>     'run()' to be executed by pyFormex. Also, the app should import anything that
>     it needs.

>     This template is a common structure that allows the file to be used both as
>     a script or as an app, with almost identical behavior.

>     For more details, see the user guide under the `Scripting` section.

>     The script starts by preference with a docstring (like this),
>     composed of a short first line, then a blank line and
>     one or more lines explaining the intention of the script.

>     If you distribute your script/app, you should set the copyright holder
>     at the start of the file and make sure that you (the copyright holder) has
>     the intention/right to distribute the software under the specified
>     copyright license (GPL3 or later).
>     """
>     # This helps in getting same code working with both Python2 and Python3
>     from __future__ import absolute_import, division, print_function

>     # The pyFormex modeling language is defined by everything in
>     # the gui.draw module (if you use the GUI). For execution without
>     # the GUI, you should import from pyformex.script instead.
>     from pyformex.gui.draw import *

>     # Definitions
>     def run():
>         """Main function.

>         This is automatically executed on each run of an app.
>         """
>         print("This is the pyFormex template script/app")

>     # Code in the outer scope:
>     # - for an app, this is only executed on loading (module initialization).
>     # - for a script, this is executed on each run.

>     print("This is the initialization code of the pyFormex template script/app")

>     # The following is to make script and app behavior alike
>     # When executing a script in GUI mode, the global variable __name__ is set
>     # to 'draw', thus the run method defined above will be executed.

>     if __name__ == '__draw__':
>         print("Running as a script")
>         run()

>     # End

The script/app source starts by preference with a docstring, consisting of a short first line, then a blank line and one or more lines explaining the intention and working of the script/app.