# Python tooling for FlightGear development

This package contains Python modules and scripts used for development of the
[FlightGear](https://www.flightgear.org/) flight simulator. It is built from
an official FlightGear repository called FGMeta, uploaded by FlightGear
developers but does not contain the flight simulator itself. If you are
interested in the latter, please visit its
[home page](https://www.flightgear.org/).

This package is mostly of interest to FlightGear developers. The
internationalization scripts it ships can be useful for aircraft and
add-on developers that want to add translations to their work.

There is nothing special about the packaging. The following instructions
are for people familiar with FlightGear but not necessarily with `pip` and
Python `venv`s.

Note: `python3-flightgear` is the directory containing this package in the
[FGMeta](https://gitlab.com/flightgear/fgmeta) repository.

## Telling your Python interpreter how to access the modules

For users of FGMeta: in order to run most of the Python scripts in FGMeta,
your Python 3 installation must have the
`/path/to/fgmeta/python3-flightgear/src` directory in its `sys.path`. If
you use `pip`, the easiest way to ensure this is to install the
`flightgear` Python package (see below). This will also create the scripts
shipped with the package, contrary to a simple modification of
`PYTHONPATH` (which is one of the ways to alter `sys.path`).

### Recommended method for development

The following instructions should be carried out under a normal user
account (not root). They assume you already have a clone of the
[FGMeta](https://gitlab.com/flightgear/fgmeta) repository in
`/path/to/fgmeta`.

1. Create a Python [venv](https://docs.python.org/3/library/venv.html) in
   some directory `dir` of your choice (outside FGMeta):

        python3 -m venv dir

2. Install the `flightgear` package inside the venv. We use option `-e`
   here to tell `pip` to install the project in editable mode, so that
   when files in `/path/to/fgmeta/python3-flightgear` are updated, the
   result is immediately usable from your venv without having to install
   the package again:

        dir/bin/pip install -e /path/to/fgmeta/python3-flightgear

   Now you have the Python modules nicely installed under `dir` and the
   associated scripts in `dir/bin`. If you're interested in `some-script`
   from this package, you can invoke it as `dir/bin/some-script` or create
   a symbolic link to it from a directory that is in your `PATH`. (You
   might want to add `dir/bin` to your `PATH` for simplicity, however
   please note before doing so that it has `python`, `python3` and `pip`
   executables. Your call.)

   Note: the `flightgear` Python package installed with the above command
   can be uninstalled from the venv using:

        dir/bin/pip uninstall flightgear

3. If the underlying Python installation is updated (as in, from Python
   X.Y to Python X.Y+1) or if the venv directory is moved elsewhere (which
   includes one of its parents being moved or renamed), you'll have to
   recreate the venv: simply delete the `dir` directory and redo the
   preceding steps.

### Alternate way

Another, more manual possibility, is to modify the `PYTHONPATH`
environment variable, either directly or by creating a `.pth` file. This
has a few drawbacks as compared to the “recommended way”:

- it won't warn you if your Python version is unsuitable for running the
  code in `fgmeta/python3-flightgear`;

- it won't warn you if you don't have required dependencies (the
  “recommended way” would automatically install them using `pip`);

- it won't create the scripts declared in the `pyproject.toml` file
  (however, they can currently be invoked as Python modules).

So, how does it work? For instance, you can use something like the
following in your shell setup:

    export PYTHONPATH="/path/to/fgmeta/python3-flightgear/src"

This example uses Bourne-style shell syntax; adjust for your particular
shell. Several directories may be added this way using a colon separator
on Unix or macOS (`:`), and a semicolon on Windows (`;`).

An alternative to setting `PYTHONPATH` is to add `.pth` files in special
directories of your Python installation(s). For instance, you could create
a file, say, `FlightGear-meta.pth`, containing a single line (with no
space at the beginning):

    /path/to/fgmeta/python3-flightgear/src

If you want the modules present in
`/path/to/fgmeta/python3-flightgear/src` to be accessible to a particular
Python interpreter (say, a Python 3.8), simply put the `.pth` file in
`/path/to/python-install-dir/lib/python3.8/site-packages/`. This can even
be a virtual environment if you want—that is basically how `pip` installs
packages in editable mode inside a venv. For the system Python
interpreters on Debian, you can put the `.pth` file in, e.g,
`/usr/local/lib/python3.8/dist-packages/`. Note that you may add more
lines to a `.pth` file in case you want to add other paths to the Python
interpreter's `sys.path`.

## The scripts

Once you've done the above setup, the Python modules from
`fgmeta/python3-flightgear/src` should be available to the chosen Python
interpreter. What about scripts that rely on these modules?

Most scripts are declared in `python3-flightgear/pyproject.toml` and
automatically created by the `pip install` command from the “Recommended
method for development” (remember: use `dir/bin/pip install` if you want
the installation to happen under the `dir` venv). There may be a few
exceptions, like currently `catalog/update-catalog.py` which exists as a
standalone script in FGMeta. As long as the modules from
`fgmeta/python3-flightgear/src` are installed for Python (i.e., accessible
via its `sys.path`), which the above methods ensure, such scripts will
work too.

The only remaining problem is therefore the following: if you used the
“alternate way”, you don't have the scripts that `pip install` would have
created for you in the “recommended way”. However, these scripts are
currently available as Python modules. For instance, the file
`python3-flightgear/src/flightgear/meta/scripts/i18n/fg_extract_translatable_strings.py`
can be imported as a Python module. Example: the command

    python3 -m flightgear.meta.scripts.i18n.fg_extract_translatable_strings --help

is equivalent to

    fg-extract-translatable-strings --help

This might be useful for one-off uses of the scripts like in Continuous
Integration, where one doesn't necessarily want to run `pip`: one could
set `PYTHONPATH` and run the desired module(s) as above (the obvious
alternative being to create a temporary venv and use the “recommended
way”).

## Running the unit tests

Once the modules in `python3-flightgear/src` are visible to Python
(regardless of the method used), the unit tests of this package can be run
with:

    cd python3-flightgear
    python3 -m unittest

(the second command is equivalent to `python3 -m unittest discover`; more
details in `tests/README.md`).

## Building the package

In case you want to build the package, you can do:

    cd python3-flightgear
    python3 -m build

This requires the Python `build` tool as explained in the
[Python Packaging User Guide](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#packaging-your-project).
