¿Configuración de Python, instalar un módulo como un módulo secundario de otro módulo?

Me gustaría crear un paquete que se instale en un submódulo de otro paquete de Python como una extensión.

Básicamente el módulo original está configurado así:

origmodule/ __init__.py stuff.py ext/ __init__.py # This module is empty 

Y luego tener mi módulo de extensión instalado en el módulo origmodule.ext vacío. Al leer las instrucciones de los distutils no estaba claro si esto es posible o si es compatible. El objective final es que mi módulo de extensión una vez instalado se importe de esta manera:

import origmodule.ext.my_extension

No puede hacer eso con setuptools, no se admite la instalación dentro de otro paquete.

En su lugar, desea utilizar puntos de entrada en su lugar. Su origmodule debe buscar cualquier cosa registrada como punto de entrada para una clave específica, y su módulo de extension debe registrarse para esa clave.

Su extensión registra un punto de extensión:

 entry_points={ 'some.opaque.string.unique.to.origmodule': ['my_extension = my.extension.package:some.entry.point', ] } 

que su origmodule puede descubrir preguntando a pkg_resources :

 import pkg_resources for entrypoint in pkg_resources.iter_entry_points(group='some.opaque.string.unique.to.origmodule'): extension = entrypoint.load() 

Eche un vistazo al proyecto Babel como ejemplo. Babel puede extraer texto traducible de archivos; sabe cómo hacer esto para el código fuente de Python, pero también admite extensiones que pueden extraer dicho texto de otros formatos.

Dichos métodos de extracción se pueden registrar como puntos de extensión. Babel documenta esto en la sección Métodos de extracción de escritura . El código de extracción del mensaje luego carga esos puntos de entrada al extraer texto:

 GROUP_NAME = 'babel.extractors' # ... for entry_point in working_set.iter_entry_points(GROUP_NAME, method): func = entry_point.load(require=True) break 

El lenguaje de plantillas Mako proporciona tal complemento; registra el punto de entrada , que apunta a la implementación real :

 [babel.extractors] mako = mako.ext.babelplugin:extract 
 def extract(fileobj, keywords, comment_tags, options): # ...