Imports

Importing Quills can be tricky. It is a compiled module, it is not necessarily installed in a location that macOS
searches by default, and it supports a variety of architectures and Python versions.

Overview

As described in Architecture, MacTerm has two major goals that complicate imports: it wants to
avoid requiring an installer with administrator privileges, and it wants to support several versions of macOS and Python.

So, in the MacTerm front-end, the runtime linker and Python interpreter are manually instructed on how to find components, and
each component has a different location depending on the version of the OS.

Example of Importing Quills

In the MacTerm application bundle, you will find two scripts that demonstrate how importing is achieved in a highly portable
way:

MacTerm.app/Contents/MacOS/MacTerm is the main entry point that sets up C++ and Python library paths, and
this is what allows imports to work. Once the environment is set up, a Python interpreter is invoked for the actual
program, RunApplication.py.

MacTerm.app/Contents/MacOS/RunApplication.py is a Python script that imports quills modules (near the top).
For the purposes of this tutorial, you can ignore everything else that is done in RunApplication.py.

The Architecture page contains full details on the directory structure of components.

Prerequisites for Importing

If you write your own scripts that rely on Quills, you must perform the same steps to locate libraries as those in the
example scripts above (assuming you still want to support all macOS versions; see below).

Quills is partly compiled, as noted in Architecture, so you must make sure both the compiled and
Python parts are found. There are two key locations:

Library path. Before the Python interpreter starts, the system’s dynamic linker must already know how to find the C++ part
of the Quills library. This code is packaged as a framework, and is platform-specific.

Module path. The Python interpreter must know how to find the Python interface to quills. By Python convention,
this requires a directory that contains both a pure Python interface quills.py and a _quills.so binding. These files
are small, but a set must usually exist for every Python version.

To set the library path, define the DYLD_LIBRARY_PATH environment variable (or an equivalent) before starting
your Python interpreter (i.e. use the parent shell). Run man dyld for more information on
linker search paths.

Sometimes, installing a framework in a path that macOS searches by default, such as /Library/Frameworks,
allows you to avoid setting a library path at all. However, MacTerm has not yet been tested with this configuration, and attempting
to install the Quills framework system-wide is discouraged.

The module path can be set in a few ways:

Set the PYTHONPATH environment variable before the Python interpreter that imports Quills begins (i.e.
use the parent shell).

Or, change the sys.path in your Python script to include the appropriate directory, before you import.

Or, use install privilege to put the appropriate copy of quills.py and _quills.so in a location that Python
searches by default. Where this is depends on how Python was built, but it is often a place like /usr/local/lib/pythonX.Y,
where X.Y is the base Python version. Since this only saves you from typing one extra line in your Python scripts and adds
complexity for your users, it is not recommended!

As noted in Architecture, the version of macOS that is in use may dictate both the path to the
compiled component and the path to the script bindings (Python module). If your personal script does not care about older versions of
macOS, you can take a simpler approach and only deal with the paths that matter for your computer.

Writing Quills-Dependent Python Scripts

Assuming you have used the steps above to set up an appropriate environment to find frameworks, the following approach is
recommended for actually importing modules in your Python code: