SEP 3 — Including packages into the SDyPy namespace#

Authors:

Domen Gorjup <domen.gorjup@fs.uni-lj.si>, Janko Slavič <janko.slavic@fs.uni-lj.si>

Status:

Draft

Type:

Process

Created:

2021-03-25

Abstract#

SDyPy uses Python’s namespace package mechanism to include packages with a high level of integration into its namespace while allowing for an independently development processes. The use of namespace packages in SDyPy is described in this document.

Motivation#

As SDyPy aims to integrate multiple open-source Python packages in the structural dynamics field to provide a coherent workflow, it may be beneficial to include some packages into the SDyPy namespace. However, it is reasonable that some of these packages keep a high level of independence in their development and distribution (e.g. their repositories with a wealth of existing resources, issues and commit histories…). To achieve this, Python’s namespace package mechanism is used.

Detailed description#

The four levels of integration, described in SEP1, define two types of packages that are included in the SDyPy namespace, but are developed in independent repositories:

  • 2nd level packages are namespace packages with a high level of integration with SDyPy, that are developed by a separate organization.

  • 1st level packages are hosted by the SDyPy organization, but can be developed in a repository, separate from the `core SDyPy package`_.

To integrate these two types of packages into the SDyPy namespace, Python’s namespace package mechanism is used. A native support for namespace packages has been introduced with Python 3.3 and is defined by PEP 420. When a package has reached a high level of integration with SDyPy, it can be included into the SDyPy namespace by adhering to Python’s namespace package file structure

example_project/
   setup.py
   SDyPy/
      example_project/
         __init__.py

As stated in Python’s namespace package documentation, it is important that the namespace directory (SDyPy/) omits an __init__.py file. It is also necessary to alter an existing package’s setup script to adhere to the changed file structure.

When a package, developed by a separate organization is defined to be part of the SDyPy namespace, as shown in the above example, it becomes a Level 2 SDyPy package. If it’s ownership is also transferred to the SDyPy organization it becomes a Level 1 SDyPy package.

SDyPy packages should follow the The Zen of Python, presented in PEP 20.

The umbrella package and the lazy facade#

The core sdypy distribution provides the only sdypy/__init__.py in the namespace and acts as a lightweight lazy facade. It exposes each first-level sub-package (EMA, io, FRF, excitation, model, view) as an attribute via PEP 562 module __getattr__ - importing the sub-package only on first access - and provides __version__ from the installed distribution metadata. It keeps the package a namespace-compatible portion (via pkgutil.extend_path) so the sibling portions still contribute.

All other packages contributing to the sdypy namespace MUST be native PEP 420 portions and MUST NOT ship a top-level sdypy/__init__.py. This keeps the umbrella’s __init__.py the single owner of the namespace root, so sub-package discovery and lazy attribute resolution are deterministic regardless of sys.path order, and it reconciles the README’s documented sd.EMA usage with the native-namespace requirement described above.

Discussion#

This section may just be a bullet list including links to any discussions regarding the SEP:

  • This includes links to mailing list threads or relevant GitHub issues.

References and Footnotes#