Nested Modules
==============

If your package uses nested namespaces, then the python interface
should use corresponding nested modules.  To facilitate this, after
following the instructions in .. _`Adding Modules`, follow these
steps:

#. Within the ``src/PyTrilinos`` directory, make a directory with your
   package name.  Repeat for any nested namespaces that also have
   nested namespaces.

#. In ``src/PyTrilinos/CMakeLists.txt``, you will find logic such as::

      # The NOX module employs namespaces, so include the NOX directory
      IF(PyTrilinos_ENABLE_NOX)
        ADD_SUBDIRECTORY(NOX)
      ENDIF(PyTrilinos_ENABLE_NOX)

   Add similar logic for your package.

#. In each nested directory, create a new ``CMakeLists.txt`` file.
   We recommend that you copy an existing file, such as::

      src/PyTrilinos/Teuchos/CMakeLists.txt

   For the following lines, change the ``Teuchos`` package name to your
   fully qualified package or sub-package name::

      ADD_CUSTOM_TARGET(...)
      ADD_CUSTOM_COMMAND(...)
      COMMENT ...

   At the bottom of this file, for modules that also have
   sub-packages, add logic similar to this, as seen in file
   ``src/PyTrilinos/NOX/CMakeLists.txt`` for each sub-module::

      # The NOX module employs namespaces, so include the sub-packages
      IF(NOX_ENABLE_ABSTRACT_IMPLEMENTATION_EPETRA)
        ADD_SUBDIRECTORY(Epetra)
      ENDIF(NOX_ENABLE_ABSTRACT_IMPLEMENTATION_EPETRA)

#. For each namespace you wish to wrap, create a SWIG interface file
   in ``src``.  This includes an interface file that corresponds to
   each directory you created in ``src/PyTrilinos`` as well as an
   interface file for each namespace that does not have a nested
   namespace.  For ``NOX``, this process resulted in the following
   SWIG interface files::

      NOX.Abstract.i
      NOX.Epetra.i
      NOX.Epetra.Interface.i
      NOX.PETSc.i
      NOX.PETSc.Interface.i
      NOX.Solver.i
      NOX.StatusTest.i

   Use the existing SWIG interface files as a guide to generating your
   new ones.  The ``%module`` directive in the SWIG interface files
   for those packages with one or more sub-packages is a little
   special.  For these files, do the following:

   * Do not ``%define`` a docstring or use the ``docstring`` option in
     the ``%module`` directive.  The docstring for these modules will
     be defined in the ``__init__.py.in`` file, described below.

   * The module name that appears at the very end of the ``%module``
     directive will always be ``Base``.

   * Use ``%define`` to define a macro that includes::

      from . import _Base

     and specify this macro as the ``moduleimport`` option in the
     ``%module`` directive.  This is more robust than the ``import``
     statement generated automatically by SWIG.  Often, other import
     statements are added here as well.

#. In the top-level ``CMakeLists.txt`` file, you should have already added an
   if-block for your package that look like this::

      IF(PyTrilinos_ENABLE_Teuchos)
        APPEND_SET(${PACKAGE_NAME}_PACKAGES Teuchos)
        APPEND_SET(${PACKAGE_NAME}_MODULES  Teuchos)
      ENDIF(PyTrilinos_ENABLE_Teuchos)

   Since your package has nested namespaces, your
   ``${PACKAGE_NAME}_MODULES`` set will require multiple values.
   There will be one for each SWIG interface file listed above, minus
   the ``.i`` extension.

#. In ``src/CMakeLists.txt``, find the loop prefaced with the
   comment::

      # Loop over the PyTrilinos-enabled Trilinos modules and define the
      # swig-generated PyTrilinos extension modules

   Within this loop, find the section that begins::

      # Choosing the Trilinos libraries to link against, the python module
      # to byte-compile and the installation rules requires a little bit
      # of logic.

   Use the existing if-blocks below this comment to provide a template
   to add logic to support your sub-modules.

#. To work properly as python packages, each directory you created in
   ``src/PyTrilinos`` will require an ``__init__.py.in`` file.  This
   file will be copied to the same location in the build directory
   with the name ``__init__.py``.  Use an existing ``__init__.py.in``
   by copying it to your directory.  The purposes of an
   ``__init__.py`` file are as follows:

   * Provide a module docstring

   * Import the local ``Base`` module.  See the note above about SWIG
     interface files for modules that have sub-modules.

   * Transfer everything in the ``Base`` module to the local namespace
     with the python command::

        globals().update(Base.__dict__)

   * Preserve certain special variables such as ``__name__`` by saving
     them before the ``update`` and reassigning them after the
     ``update``.  The full list of variables can be found in each
     existing ``__init__.py.in`` file.  Those protected by a ``try:``
     statement are present in python 3, but not python 2.  The python
     3 variables are required to be saved so that ``import`` will work
     correctly in python 3.

   * Create and populate the ``__all__`` variable, containing the
     names of all the sub-packages of the current package.

   * Import all of the sub-packages of the current package.
