python - software - ¿Cómo escribir correctamente referencias cruzadas a la documentación externa con intersphinx?
sphinx software (4)
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 de esfinge "ocv": 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.
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 mapeo intersphinx está configurado 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 forma 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?
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
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 del 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 nos fijamos en 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. Así que 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<string>&'',
u''Algorithm::name()'',
u''Algorithm::read(const'',
u''Algorithm::set(const''
...]
Y si tomamos el valor del primero:
{u''Ptr<AdjusterAdapter>'': (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 uno debería inspeccionar un objeto de inventario específico para ver qué hay disponible.
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)