MEP26: Stile dell'artista #
Stato n.
Respinto
Filiali e Pull request #
Estratto n.
Questo MEP propone una nuova implementazione del foglio di stile per consentire uno stile più completo e dinamico degli artisti.
L'attuale versione di matplotlib (1.4.0) consente di applicare fogli di stile basati sulla sintassi rcParams prima della creazione di un grafico. La metodologia di seguito propone una nuova sintassi, basata su CSS, che consentirebbe lo styling di singoli artisti e proprietà, che possono essere applicati dinamicamente agli oggetti esistenti.
Ciò è correlato (e fa passi verso) l'obiettivo generale di passare a un'architettura DOM/simile ad un albero.
Descrizione dettagliata #
Attualmente, l'aspetto e l'aspetto degli oggetti dell'artista esistenti (figura, assi, Line2D, ecc.) possono essere aggiornati solo tramite set_
e get_
metodi sull'oggetto dell'artista, il che è piuttosto laborioso, soprattutto se non è stato memorizzato alcun riferimento all'artista o agli artisti . I nuovi fogli di stile introdotti nella versione 1.4 consentono lo styling prima della creazione di una trama, ma non offrono alcun mezzo per aggiornare dinamicamente le trame o distinguere tra artisti dello stesso tipo (ovvero specificare e separatamente per oggetti diversi).line color
line
style
Line2D
Lo sviluppo iniziale dovrebbe concentrarsi sul consentire lo styling delle primitive dell'artista (quelle Artist
s che non contengono altri
Artist
s), e un ulteriore sviluppo potrebbe espandere le regole di sintassi CSS e il parser per consentire uno styling più complesso. Vedere l'appendice per un elenco di primitive.
La nuova metodologia richiederebbe lo sviluppo di una serie di fasi:
Una nuova sintassi del foglio di stile (probabilmente basata su CSS) per consentire la selezione di artisti per tipo, classe, id, ecc.
Un meccanismo mediante il quale analizzare un foglio di stile in un albero
Un meccanismo con cui tradurre l'albero di analisi in qualcosa che può essere utilizzato per aggiornare le proprietà di artisti rilevanti. Idealmente questo implementerebbe un metodo con cui attraversare gli artisti in una struttura ad albero.
Un meccanismo mediante il quale generare un foglio di stile dalle proprietà dell'artista esistenti. Ciò sarebbe utile per consentire a un utente di esportare un foglio di stile da una figura esistente (dove l'aspetto potrebbe essere stato impostato utilizzando l'API matplotlib)...
Implementazione n.
Sarà più semplice consentire a una "terza parte" di modificare/impostare lo stile di un artista se lo "stile" viene creato come classe separata e memorizzato sull'artista come proprietà. La GraphicsContextBase
classe fornisce già una base di una
Style
classe e il metodo di un artista draw
può essere rifattorizzato per utilizzare la Style
classe piuttosto che impostarne una propria GraphicsContextBase
e trasferirvi le sue proprietà relative allo stile. Un esempio minimo di come questo potrebbe essere implementato è mostrato qui: https://github.com/JamesRamm/mpl_experiment
IMO, questo renderà anche l'API e la base di codice molto più ordinate poiché i singoli metodi get/set per le proprietà dello stile dell'artista sono ora ridondanti ... Indirettamente correlato sarebbe un'unità generale per sostituire i metodi get/set con le proprietà. L'implementazione della classe di stile con le proprietà sarebbe un grande passo avanti verso questo ...
Per lo sviluppo iniziale, suggerisco di sviluppare una sintassi basata su una versione molto (molto) semplificata di CSS. Sono favorevole al doppiaggio di questo foglio di stile dell'artista :+1: :
BNF Grammatica #
Propongo una sintassi molto semplice da implementare inizialmente (come una prova di concetto), che può essere ampliata in futuro. La forma BNF della sintassi è data di seguito e poi spiegata
RuleSet ::= SelectorSequence "{"Declaration"}"
SelectorSequence :: = Selector {"," Selector}
Declaration ::= propName":" propValue";"
Selector ::= ArtistIdent{"#"Ident}
propName ::= Ident
propValue ::= Ident | Number | Colour | "None"
ArtistIdent
, Ident
, Number
e Colour
sono token (gli elementi costitutivi di base dell'espressione) definiti da espressioni regolari.
Sintassi #
Un foglio di stile CSS è costituito da una serie di set di regole in ordine gerarchico (le regole vengono applicate dall'alto verso il basso). Ogni regola segue la sintassi
selector {attribute: value;}
Ogni regola può avere un numero qualsiasi di coppie e un foglio di stile può avere un numero qualsiasi di regole.attribute: value
La sintassi iniziale è progettata solo per Artist
le primitive. Non affronta la questione di come impostare le proprietà sui Container
tipi (le cui proprietà possono esse stesse essere Artist
s con proprietà impostabili), tuttavia, una soluzione futura a questo potrebbe essere semplicemente nidificata
RuleSet
s
Selettori #
I selettori definiscono l'oggetto a cui devono essere applicati gli aggiornamenti degli attributi. Come punto di partenza, propongo solo 2 selettori da utilizzare nello sviluppo iniziale:
Selettore del tipo di artista
Seleziona un Artist
in base al suo tipo. Es . Line2D
oppure Text
:
Line2D {attribute: value}
La regex per la corrispondenza del selettore del tipo di artista ( ArtistIdent
nella grammatica BNF) sarebbe:
ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'
Selettore GID #
Seleziona un Artist
per il suo gid
:
Line2D#myGID {attribute: value}
A gid
può essere qualsiasi stringa, quindi la regex potrebbe essere la seguente:
Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'
I selettori di cui sopra corrispondono approssimativamente alle loro controparti CSS ( http://www.w3.org/TR/CSS21/selector.html )
Attributi e valori #
Attributes
sono qualsiasi proprietà valida (impostabile) per l'Artist
oggetto in questione.Values
sono qualsiasi valore valido per la proprietà (solitamente una stringa o un numero).
#analisi _
L'analisi consisterebbe nel suddividere il foglio di stile in token (il ricettario di Python fornisce una bella ricetta per la tokenizzazione a pagina 66), applicando le regole di sintassi e costruendo un file Tree
. Ciò richiede la definizione della grammatica del foglio di stile (di nuovo, possiamo prendere in prestito dai CSS) e la scrittura di un parser. Fortunatamente, c'è anche una ricetta per questo nel ricettario di Python.
Schema dei visitatori per la figura matplotlib n.
Per applicare le regole del foglio di stile agli artisti pertinenti, dobbiamo "visitare" ogni artista in una figura e applicare la regola pertinente. Ecco una classe di visitatori (di nuovo, grazie al libro di cucina di Python), in cui ognuno
node
sarebbe un artista nella figura. visit_
Sarebbe necessario implementare un metodo per ogni artista mpl, per gestire le diverse proprietà per ciascuno
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)
Una evaluator
classe prenderebbe quindi le regole del foglio di stile e implementerebbe il visitatore su ciascuna di esse.
Compatibilità con le versioni precedenti #
L'implementazione di una Style
classe separata interromperebbe la compatibilità con le versioni precedenti poiché molti metodi get/set su un artista diventerebbero ridondanti. Mentre sarebbe possibile modificare questi metodi per agganciarsi alla Style
classe (memorizzata come proprietà contro l'artista), sarei favorevole a rimuoverli semplicemente sia per migliorare/semplificare la base di codice sia per fornire un'API semplice e ordinata. .
Alternative #
Nessuna alternativa, ma parte del terreno coperto qui si sovrappone a MEP25, il che potrebbe aiutare in questo sviluppo
Appendice #
Primitive Matplotlib #
Questo formerà i selettori iniziali che i fogli di stile possono usare.
Linea2D
Testo
AxesImage
FiguraImmagine
Toppa