MEP26: Estilo de artista #
Estado #
Rechazado
Sucursales y solicitudes de extracción #
Resumen #
Este eurodiputado propone una nueva implementación de hoja de estilo para permitir un estilo más completo y dinámico de los artistas.
La versión actual de matplotlib (1.4.0) permite aplicar hojas de estilo basadas en la sintaxis rcParams antes de la creación de un gráfico. La metodología a continuación propone una nueva sintaxis, basada en CSS, que permitiría diseñar artistas y propiedades individuales, que se pueden aplicar dinámicamente a objetos existentes.
Esto está relacionado con (y da pasos hacia) el objetivo general de pasar a una arquitectura DOM/tipo árbol.
Descripción detallada #
Actualmente, el aspecto y la apariencia de los objetos de artista existentes (figura, ejes, Line2D, etc.) solo se pueden actualizar a través set_
de get_
métodos en el objeto de artista, lo cual es bastante laborioso, especialmente si no se ha almacenado ninguna referencia al artista. . Las nuevas hojas de estilo introducidas en 1.4 permiten diseñar antes de crear una trama, pero no ofrecen ningún medio para actualizar dinámicamente las tramas o distinguir entre artistas del mismo tipo (es decir, para especificar y por separado para diferentes objetos).line color
line
style
Line2D
El desarrollo inicial debe concentrarse en permitir el estilo de las primitivas de artista (aquellos Artist
que no contienen otros
Artist
), y un desarrollo posterior podría expandir las reglas de sintaxis de CSS y el analizador para permitir un estilo más complejo. Consulte el apéndice para obtener una lista de primitivas.
La nueva metodología requeriría el desarrollo de una serie de pasos:
Una nueva sintaxis de hoja de estilo (probablemente basada en CSS) para permitir la selección de artistas por tipo, clase, id, etc.
Un mecanismo por el cual analizar una hoja de estilo en un árbol
Un mecanismo por el cual traducir el árbol de análisis en algo que se puede usar para actualizar las propiedades de los artistas relevantes. Idealmente, esto implementaría un método por el cual atravesar a los artistas en una estructura similar a un árbol.
Un mecanismo por el cual generar una hoja de estilo a partir de propiedades de artistas existentes. Esto sería útil para permitir que un usuario exporte una hoja de estilo de una figura existente (donde la apariencia puede haberse configurado usando la API de matplotlib)...
Implementación #
Será más fácil permitir que un 'tercero' modifique/establezca el estilo de un artista si el 'estilo' se crea como una clase separada y se almacena contra el artista como una propiedad. La GraphicsContextBase
clase ya proporciona la base de una
Style
clase y el método de un artista draw
se puede refactorizar para usar la Style
clase en lugar de configurar la suya propia GraphicsContextBase
y transferirle sus propiedades relacionadas con el estilo. Aquí se muestra un ejemplo mínimo de cómo se podría implementar esto: https://github.com/JamesRamm/mpl_experiment
En mi opinión, esto también hará que la API y el código base sean mucho más ordenados, ya que los métodos get/set individuales para las propiedades de estilo de artista ahora son redundantes... Indirectamente relacionado sería un impulso general para reemplazar los métodos get/set con propiedades. Implementar la clase de estilo con propiedades sería un gran paso hacia esto...
Para el desarrollo inicial, sugiero desarrollar una sintaxis basada en una versión mucho más simplificada de CSS. Estoy a favor de doblar estas hojas de estilo de artista :+1: :
BNF Gramática #
Propongo una sintaxis muy simple para implementar inicialmente (como una prueba de concepto), que se puede ampliar en el futuro. La forma BNF de la sintaxis se proporciona a continuación y luego se explica
RuleSet ::= SelectorSequence "{"Declaration"}"
SelectorSequence :: = Selector {"," Selector}
Declaration ::= propName":" propValue";"
Selector ::= ArtistIdent{"#"Ident}
propName ::= Ident
propValue ::= Ident | Number | Colour | "None"
ArtistIdent
, Ident
y son tokens Number
( Colour
los componentes básicos de la expresión) que se definen mediante expresiones regulares.
Sintaxis #
Una hoja de estilo CSS consta de una serie de conjuntos de reglas en orden jerárquico (las reglas se aplican de arriba a abajo). Cada regla sigue la sintaxis
selector {attribute: value;}
Cada regla puede tener cualquier número de pares y una hoja de estilo puede tener cualquier número de reglas.attribute: value
La sintaxis inicial está diseñada solo para Artist
primitivas. No aborda la cuestión de cómo establecer propiedades en Container
tipos (cuyas propiedades pueden ser Artist
s con propiedades configurables), sin embargo, una solución futura a esto podría simplemente anidarse
RuleSet
s
Selectores #
Los selectores definen el objeto al que se deben aplicar las actualizaciones de atributos. Como punto de partida, propongo solo 2 selectores para usar en el desarrollo inicial:
Selector de tipo de artista
Seleccione una Artist
por su tipo. Por ejemplo , Line2D
o Text
:
Line2D {attribute: value}
La expresión regular para hacer coincidir el selector de tipo de artista ( ArtistIdent
en la gramática BNF) sería:
ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'
Nº de selector de GID
Seleccione una Artist
por su gid
:
Line2D#myGID {attribute: value}
A gid
puede ser cualquier cadena, por lo que la expresión regular podría ser la siguiente:
Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'
Los selectores anteriores corresponden aproximadamente a sus homólogos de CSS ( http://www.w3.org/TR/CSS21/selector.html )
Atributos y valores #
Attributes
son cualquier propiedad válida (configurable) para elArtist
en cuestión.Values
son cualquier valor válido para la propiedad (normalmente una cadena o un número).
Analizando #
El análisis consistiría en dividir la hoja de estilo en tokens (el libro de cocina de Python ofrece una buena receta para tokenizar en la página 66), aplicar las reglas de sintaxis y construir un archivo Tree
. Esto requiere definir la gramática de la hoja de estilo (nuevamente, podemos tomar prestado de CSS) y escribir un analizador. Afortunadamente, también hay una receta para esto en el libro de cocina de Python.
Patrón de visitante para matplotlib figura #
Para aplicar las reglas de la hoja de estilo a los artistas relevantes, necesitamos 'visitar' a cada artista en una figura y aplicar la regla relevante. Aquí hay una clase de visitante (nuevamente, gracias al libro de cocina de Python), donde cada uno
node
sería un artista en la figura. Se visit_
necesitaría implementar un método para cada artista mpl, para manejar las diferentes propiedades para cada
class Visitor:
def visit(self, node):
name = 'visit_' + type(node).__name__
meth = getattr(self, name, None)
if meth is None:
raise NotImplementedError
return meth(node)
Luego, una evaluator
clase tomaría las reglas de la hoja de estilo e implementaría el visitante en cada una de ellas.
Compatibilidad con versiones anteriores #
La implementación de una Style
clase separada rompería la compatibilidad con versiones anteriores, ya que muchos métodos get/set en un artista se volverían redundantes. Si bien sería posible modificar estos métodos para vincularlos a la Style
clase (almacenados como una propiedad contra el artista), estaría a favor de simplemente eliminarlos para mejorar/simplificar la base de código y proporcionar una API simple y despejada. .
Alternativas #
No hay alternativas, pero parte del terreno cubierto aquí se superpone con MEP25, lo que puede ayudar en este desarrollo.
Apéndice #
Primitivas de matplotlib #
Esto formará los selectores iniciales que pueden usar las hojas de estilo.
Línea2D
Texto
EjesImagen
FiguraImagen
Parche