px
pypx

apipkg

v3.0.2

apipkg: namespace control and lazy-import mechanism

8 KB Python 3.7+ py3-none-anyMIT License Likely Unmaintained
Diff
$ uv add apipkg

Welcome to apipkg !

With apipkg you can control the exported namespace of a Python package and greatly reduce the number of imports for your users. It is a small pure Python module_ that works on CPython 3.7+, Jython and PyPy. It cooperates well with Python's help() system, custom importers (PEP302) and common command-line completion tools.

Usage is very simple: you can require 'apipkg' as a dependency or you can copy paste the ~200 lines of code into your project.

Tutorial example

Here is a simple mypkg package that specifies one namespace and exports two objects imported from different modules:

# mypkg/__init__.py
import apipkg
apipkg.initpkg(__name__, {
    'path': {
        'Class1': "_mypkg.somemodule:Class1",
        'clsattr': "_mypkg.othermodule:Class2.attr",
    }
}

The package is initialized with a dictionary as namespace.

You need to create a _mypkg package with a somemodule.py and othermodule.py containing the respective classes. The _mypkg is not special - it's a completely regular Python package.

Namespace dictionaries contain name: value mappings where the value may be another namespace dictionary or a string specifying an import location. On accessing an namespace attribute an import will be performed:

>>> import mypkg
>>> mypkg.path
<ApiModule 'mypkg.path'>
>>> mypkg.path.Class1   # '_mypkg.somemodule' gets imported now
<class _mypkg.somemodule.Class1 at 0xb7d428fc>
>>> mypkg.path.clsattr  # '_mypkg.othermodule' gets imported now
4 # the value of _mypkg.othermodule.Class2.attr

The mypkg.path namespace and its two entries are loaded when they are accessed. This means:

  • lazy loading - only what is actually needed is ever loaded
  • only the root "mypkg" ever needs to be imported to get

access to the complete functionality

  • the underlying modules are also accessible, for example:
from mypkg.sub import Class1

Including apipkg in your package

If you don't want to add an apipkg dependency to your package you can copy the apipkg.py_ file somewhere to your own package, for example _mypkg/apipkg.py in the above example. You then import the initpkg function from that new place and are good to go.

Feedback?

If you have questions you are welcome to

  • join the #pytest channel on irc.libera.chat_

(using an IRC client, via webchat_, or via Matrix_).

  • create an issue on the bugtracker_

Details

Version
3.0.2
License
MIT License
Python
>=3.7
Maintainer
holger krekel

Maintainers

  • holger krekel