Proyecto matplotlib

Esta página contiene los detalles de un proyecto de redacción técnico aceptado para Google Season of Docs.

Resumen del proyecto

Organización de código abierto:
Matplotlib
Redactor técnico:
brunobeltrán
Nombre del proyecto:
Mejorar la visibilidad de las funciones con la estandarización de la documentación de tipos "implícitos"
Duración del proyecto:
Larga duración (5 meses)

Project description

Motivación

Históricamente, la API de matplotlib se ha basado en gran medida en "tipos implícitos" de strings como enumeraciones. Además de imitar la API de matlab, estas cadenas de parámetros permiten al usuario pasar valores con mucha semántica como argumentos a las funciones de matplotlib sin tener que importar explícitamente o prefijar de forma detallada un valor enum real solo para pasar opciones de trazado básicas (es decir, plt.plot(x, y, linestyle='solid') es más fácil de escribir y menos redundante que algo como plt.plot(x, y, linestyle=mpl.LineStyle.solid)).

Desde entonces, muchos de estos tipos implícitos de string como enumeración evolucionaron con funciones más sofisticadas. Por ejemplo, un objeto linestyle ahora puede ser una cadena o una tupla de 2 secuencias, y un elemento MarkerStyle ahora puede ser una cadena o un matplotlib.path.Path. Si bien esto se aplica a muchos tipos implícitos, (hasta donde sabemos) MarkerStyle es el único que tiene el estado de actualizarse a una clase de Python adecuada.

Debido a que estos tipos implícitos no son clases en sí mismos, Matplotlib históricamente tuvo que lanzar sus propias soluciones para centralizar la documentación y la validación de estos tipos implícitos (p.ej., el patrón de interpolación de docstring docstring.interpd.update y el patrón del validador cbook._check_in_list, respectivamente) en lugar de usar las cadenas de herramientas estándar que proporcionan las clases Python (p.ej., docstrings y el patrón de validación en __init__, respectivamente).

Si bien estas soluciones funcionaron bien para nosotros, la falta de una ubicación explícita para documentar cada tipo implícito significa que la documentación suele ser difícil de encontrar, las tablas grandes con valores permitidos se repiten en toda la documentación y, a menudo, falta por completo una declaración explícita del alcance de un tipo implícito en los documentos. Toma los documentos de plt.plot, por ejemplo, en "Notes", una descripción del método de estilo de cadena de formato similar a Matlab menciona las opciones linestyle, color y markers. Hay muchas más formas de pasar estos tres valores de las que se sugieren, pero, para muchos usuarios, esta es su única fuente de comprensión sobre qué valores son posibles para esas opciones hasta que descubren uno de los instructivos relevantes. Se incluye una tabla de atributos Line2D para intentar mostrarle al lector las opciones que tiene para controlar su diagrama. Sin embargo, aunque la entrada linestyle realiza un buen trabajo de vinculación con Line2D.set_linestyle (se requieren dos clics), donde se describen las entradas posibles, las entradas color y markers no lo hacen. color simplemente se vincula a Line2D.set_color, lo que no ofrece ninguna intuición sobre qué tipos de entradas están permitidas.

Se podría decir que esto es algo que se puede solucionar simplemente ordenando las docstrings individuales que causan problemas, pero lamentablemente, el problema es mucho más sistémico que eso. Sin un lugar centralizado para encontrar la documentación, esto simplemente nos llevará a tener cada vez más copias de documentación cada vez más detallada que se repitan en todos los lugares donde se use cada uno de estos tipos implícitos, lo que dificulta mucho que los usuarios principiantes encuentren el parámetro que necesitan. Sin embargo, el sistema actual, que obliga a los usuarios a unir lentamente su modelo mental de cada tipo implícito a través de un recorrido de estilo de wiki-divinación en toda nuestra documentación, o fragmentado de los ejemplos de StackOverflow, tampoco es sostenible.

Objetivo final

Lo ideal es que cualquier mención de un tipo implícito se relacione con una sola página que describa todos los valores posibles que puede tomar ese tipo, ordenados desde los más simples y comunes hasta los más avanzados o esotéricos. En lugar de usar un espacio visual valioso en la documentación de la API de nivel superior para enumerar todos los tipos de entrada posibles en un parámetro en particular, podemos usar ese mismo espacio para brindar una descripción sencilla de la abstracción de trazado que debe controlar el parámetro.

Para volver a usar el ejemplo de linestyle, lo que se necesita en los documentos de LineCollection es simplemente lo siguiente:

  1. Un vínculo para completar los documentos de las entradas permitidas (una combinación de las que se encuentran en Line2D.set_linestyle y el instructivo de estilo de línea)
  2. Es una descripción sencilla de lo que se pretende que el parámetro logre. Para los power users de matplotlib, esto es evidente a partir del nombre del parámetro, pero no es necesario que sea así para los usuarios nuevos.

La forma en que se vería en los documentos de LineCollection reales es solo python """""" linestyles: `LineStyle` or list thereof, default: :rc:`lines.linestyle` ('-') A description of whether the stroke used to draw each line in the collection is dashed, dotted or solid, or some combination thereof. """""", donde Sphinx resolvería la referencia de tipo LineStyle para apuntar a un conjunto de documentación único y completo sobre cómo Matplotlib trata los estilos de línea.

Beneficios

Algunas funciones potentes de este enfoque incluyen

  1. Hacer que el alcance completo de cada función sea evidente en texto sin formato (sin necesidad de hacer clics).
  2. Hacer visible la opción predeterminada (sin clics) Ver la opción predeterminada es suficiente para refrescar la memoria de los usuarios recurrentes.
  3. Haz una descripción completa de las opciones "más común" y "más fácil" para un parámetro que esté disponible de forma sencilla cuando se navega (con un solo clic).
  4. Haz que el proceso de descubrimiento de funciones y métodos de entrada más potentes sea tan fácil como "desplazarse hacia abajo" para ver opciones más avanzadas (con solo un clic).
  5. Proporcionar una estrategia centralizada para vincular los documentos de "API" de nivel superior a los "instructivos" relevantes.
  6. Evita la explosión de documentos de API, en la que analizar las muchas opciones posibles para cada parámetro hace que las docstrings individuales sean difíciles de manejar.

Otros beneficios de este enfoque en comparación con los documentos actuales son los siguientes:

  1. Es menos probable que los documentos se vuelvan obsoletos debido a la centralización.
  2. Canonicalización de muchos de los ""estándares implícitos" de matplotlib (como lo que es un ""límites"" frente a una ""extensión") que actualmente deben aprenderse mediante la lectura del código.
  3. El proceso destacaría los problemas de coherencia de la API de una manera que se pueda rastrear más fácilmente a través de la herramienta de seguimiento de problemas de GitHub, lo que ayuda con el proceso de mejora de nuestra API.
  4. Se aceleran los tiempos de compilación de documentos debido a disminuciones significativas en la cantidad de texto que se debe analizar.

Implementación

Las mejoras descritas anteriormente requerirán dos esfuerzos importantes para los cuales un escritor técnico dedicado será invaluable. La primera es crear una página de “instructivo” centralizada por tipo implícito. Deberás trabajar con el equipo principal de desarrolladores para identificar una lista concreta de tipos implícitos cuya documentación sería valiosa para los usuarios (por lo general, porque contienen funciones ocultas y potentes de nuestra biblioteca cuya documentación solo se encuentra actualmente en instructivos difíciles de encontrar). Para cada tipo implícito, voy a sintetizar los diversos instructivos, documentos de la API y páginas de ejemplo relevantes en una sola fuente autorizada de documentación que se pueda vincular a cualquier lugar de referencia a ese tipo en particular.

Una vez que se completa la documentación centralizada para un tipo implícito determinado, comienza el segundo esfuerzo principal: reemplazar la documentación existente de la API por vínculos a la documentación nueva, con el objetivo de hacer que la experiencia de usar esta nueva documentación sea lo más sencilla posible, tanto para quienes usan la utilidad help() integrada de Python como para quienes exploran nuestra documentación en línea.

Si bien el formato exacto de la documentación propuesta aquí está sujeto a cambios a medida que evoluciona este proyecto, trabajé con el equipo principal de Matplotlib durante sus "llamadas de desarrollo" semanales para establecer un consenso de que la estrategia propuesta aquí es el enfoque más conveniente, útil y técnicamente manejable para comenzar a documentar estos "tipos implícitos" (hay notas sobre estos "tipos implícitos"). Usaré la infraestructura de "instructivos" existente para las etapas iniciales de creación de la documentación centralizada para cada tipo implícito, lo que me permite hacer referencia fácilmente a estas páginas de la siguiente manera, sin tener que crear ninguna clase pública nueva (de nuevo, usando los documentos LineCollection como ejemplo):

""""""
linestyles: LineStyle or list thereof, default: :rc:`lines.linestyle` ('-')
    A description of whether the stroke used to draw each line in the collection
    is dashed, dotted or solid, or some combination thereof. For a full
    description of possible LineStyle's, see :doc:`tutorials/types/linestyle`.
""""""

En el futuro, podríamos cambiar fácilmente la forma en que se escriben estas referencias una vez que el equipo principal de desarrolladores acuerde cuál es la mejor estrategia a largo plazo para incorporar nuestra nueva documentación de "tipos" a clases de Python de buena fe, por ejemplo, según lo que propongo en la propuesta de mejoras de Matplotlib 30.

Por último, la lista preliminar de tipos implícitos que propongo que se documenten durante esta temporada de Documentos de Google es la siguiente:

  1. capstyle
  2. joinstyle
  3. bounds
  4. extents
  5. linestyle
  6. colors/lists of colors
  7. colornorm/colormap
  8. tick formatters

Puedes encontrar una versión publicada de este documento en nuestro Discourse.