¿Cómo escribir correctamente las referencias cruzadas a la documentación externa con intersphinx?

Estoy tratando de agregar referencias cruzadas a la API externa en mi documentación, pero me enfrento a tres comportamientos diferentes.

Estoy usando sphinx (1.3.1) con Python (2.7.3) y mi asignación intersphinx está configurada como:

{ 'python': ('https://docs.python.org/2.7', None), 'numpy': ('http://docs.scipy.org/doc/numpy/', None), 'cv2' : ('http://docs.opencv.org/2.4/', None), 'h5py' : ('http://docs.h5py.org/en/latest/', None) } 

No tengo problemas para escribir una referencia cruzada a la API numpy con :class:`numpy.ndarray` o :func:`numpy.array` que me da, como es de esperar, algo como numpy.ndarray .

Sin embargo, con h5py, la única manera de generar un enlace es omitir el nombre del módulo. Por ejemplo :class:`Group` (o :class:`h5py:Group` ) me da Group pero :class:`h5py.Group` no genera un enlace.

Finalmente, no puedo encontrar una manera de escribir una referencia cruzada de trabajo a la API de OpenCV, ninguna de estas parece funcionar:

 :func:`cv2.convertScaleAbs` :func:`cv2:cv2.convertScaleAbs` :func:`cv2:convertScaleAbs` :func:`convertScaleAbs` 

¿Cómo escribir correctamente las referencias cruzadas a la API externa, o configurar intersphinx, para tener un enlace generado como en el caso numpy?

Intenté de nuevo entender el contenido de un archivo objects.inv y espero que esta vez haya inspeccionado numpy y h5py en lugar de solo el de OpenCV.

Cómo leer un archivo de inventario intersphinx

A pesar de que no pude encontrar nada útil sobre la lectura del contenido de un archivo object.inv , en realidad es muy simple con el módulo intersphinx.

 from sphinx.ext import intersphinx import warnings def fetch_inventory(uri): """Read a Sphinx inventory file into a dictionary.""" class MockConfig(object): intersphinx_timeout = None # type: int tls_verify = False class MockApp(object): srcdir = '' config = MockConfig() def warn(self, msg): warnings.warn(msg) return intersphinx.fetch_inventory(MockApp(), '', uri) uri = 'http://docs.python.org/2.7/objects.inv' # Read inventory into a dictionary inv = fetch_inventory(uri) # Or just print it intersphinx.debug(['', uri]) 

Estructura de archivo (numpy)

Después de inspeccionar uno de numpy, puedes ver que las claves son dominios:

 [u'np-c:function', u'std:label', u'c:member', u'np:classmethod', u'np:data', u'py:class', u'np-c:member', u'c:var', u'np:class', u'np:function', u'py:module', u'np-c:macro', u'np:exception', u'py:method', u'np:method', u'np-c:var', u'py:exception', u'np:staticmethod', u'py:staticmethod', u'c:type', u'np-c:type', u'c:macro', u'c:function', u'np:module', u'py:data', u'np:attribute', u'std:term', u'py:function', u'py:classmethod', u'py:attribute'] 

Puede ver cómo puede escribir su referencia cruzada cuando mira el contenido de un dominio específico. Por ejemplo, py:class :

 {u'numpy.DataSource': (u'NumPy', u'1.9', u'http://docs.scipy.org/doc/numpy/reference/generated/numpy.DataSource.html#numpy.DataSource', u'-'), u'numpy.MachAr': (u'NumPy', u'1.9', u'http://docs.scipy.org/doc/numpy/reference/generated/numpy.MachAr.html#numpy.MachAr', u'-'), u'numpy.broadcast': (u'NumPy', u'1.9', u'http://docs.scipy.org/doc/numpy/reference/generated/numpy.broadcast.html#numpy.broadcast', u'-'), ...} 

Entonces, aquí :class:`numpy.DataSource` funcionará como se espera.

h5py

En el caso de h5py, los dominios son:

 [u'py:attribute', u'std:label', u'py:method', u'py:function', u'py:class'] 

y si miras el dominio py:class :

 {u'AttributeManager': (u'h5py', u'2.5', u'http://docs.h5py.org/en/latest/high/attr.html#AttributeManager', u'-'), u'Dataset': (u'h5py', u'2.5', u'http://docs.h5py.org/en/latest/high/dataset.html#Dataset', u'-'), u'ExternalLink': (u'h5py', u'2.5', u'http://docs.h5py.org/en/latest/high/group.html#ExternalLink', u'-'), ...} 

Es por eso que no pude hacerlo funcionar como referencias numpy. Por lo tanto, una buena manera de formatearlos sería :class:`h5py:Dataset` .

OpenCV

El objeto de inventario de OpenCV parece malformado. Donde esperaría encontrar dominios en realidad hay 902 firmas de funciones:

 [u':', u'AdjusterAdapter::create(const', u'AdjusterAdapter::good()', u'AdjusterAdapter::tooFew(int', u'AdjusterAdapter::tooMany(int', u'Algorithm::create(const', u'Algorithm::getList(vector&', u'Algorithm::name()', u'Algorithm::read(const', u'Algorithm::set(const' ...] 

Y si tomamos el valor del primero:

 {u'Ptr': (u'OpenCV', u'2.4', u'http://docs.opencv.org/2.4/detectorType)', u'ocv:function 1 modules/features2d/doc/common_interfaces_of_feature_detectors.html#$ -')} 

Estoy bastante seguro de que es imposible escribir referencias cruzadas de OpenCV con este archivo …

Conclusión

Pensé que intersphinx generó el objects.inv basado en el contenido del proyecto de documentación de una manera estándar , lo que no parece ser el caso. Como resultado, parece que la forma correcta de escribir referencias cruzadas depende de la API y se debe inspeccionar un objeto de inventario específico para ver qué hay disponible.

Además de la respuesta detallada de @gall, he descubierto que intersphinx también se puede ejecutar como un módulo:

 python -m sphinx.ext.intersphinx 'http://python-eve.org/objects.inv' 

Esto produce información muy bien formateada. Para referencia: https://github.com/sphinx-doc/sphinx/blob/master/sphinx/ext/intersphinx.py#L390

Cómo utilizar OpenCV 2.4 (cv2) intersphinx

Inspirado por la respuesta de @ Gall, quise comparar los contenidos de los archivos de inventario de OpenCV y números. No pude hacer funcionar sphinx.ext.intersphinx.fetch_inventory desde ipython, pero lo siguiente sí funciona:

 curl http://docs.opencv.org/2.4/objects.inv | tail -n +5 | zlib-flate -uncompress > cv2.inv curl https://docs.scipy.org/doc/numpy/objects.inv | tail -n +5 | zlib-flate -uncompress > numpy.inv 

numpy.inv tiene líneas como esta:

 numpy.ndarray py:class 1 reference/generated/numpy.ndarray.html#$ - 

mientras que cv2.inv tiene líneas como esta:

 cv2.imread ocv:pyfunction 1 modules/highgui/doc/reading_and_writing_images_and_video.html#$ - 

Entonces, presumiblemente, enlazarías a los documentos de OpenCV con :ocv:pyfunction:`cv2.imread` lugar de :py:function:`cv2.imread` . A la esfinge no le gusta, sin embargo:

ADVERTENCIA: Rol de texto interpretado desconocido “ocv: pyfunction”.

Un poco de Google reveló que el proyecto OpenCV tiene su propio dominio “ocv” sphinx: https://github.com/opencv/opencv/blob/2.4/doc/ocv.py – probablemente porque necesitan documentar C, C ++ y las API de Python al mismo tiempo.

Para usarlo, guarde ocv.py lado de su Sphinx conf.py , y modifique su conf.py :

 sys.path.insert(0, os.path.abspath('.')) import ocv extensions = [ 'ocv', ] intersphinx_mapping = { 'cv2': ('http://docs.opencv.org/2.4/', None), } 

En tus primeros archivos necesitas decir :ocv:pyfunc:`cv2.imread` (no :ocv:pyfunction: .

Sphinx imprime algunas advertencias (no se puede unparseable C++ definition: u'cv2.imread' ) pero la documentación html generada realmente se ve bien con un enlace a http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html# cv2.imread . Puede editar ocv.py y eliminar la línea que imprime esa advertencia.

La respuesta aceptada ya no funciona en la nueva versión (1.5.x) …

 import requests import posixpath from sphinx.ext.intersphinx import read_inventory uri = 'http://docs.python.org/2.7/' r = requests.get(uri + 'objects.inv', stream=True) r.raise_for_status() inv = read_inventory(r.raw, uri, posixpath.join)