MEP26: Estilo do artista #

Estado #

rejeitado

Filiais e solicitações pull #

Resumo #

Este MEP propõe uma nova implementação de folha de estilo para permitir um estilo mais abrangente e dinâmico dos artistas.

A versão atual do matplotlib (1.4.0) permite que folhas de estilo baseadas na sintaxe rcParams sejam aplicadas antes da criação de um gráfico. A metodologia abaixo propõe uma nova sintaxe, baseada em CSS, que permitiria estilizar artistas e propriedades individuais, que podem ser aplicadas dinamicamente a objetos existentes.

Isso está relacionado (e dá passos em direção a) ao objetivo geral de mudar para uma arquitetura DOM/tipo árvore.

Descrição detalhada #

Atualmente, a aparência dos objetos de artista existentes (figura, eixos, Line2D, etc.) só podem ser atualizados por meio set_de métodos e get_no objeto de artista, o que é bastante trabalhoso, especialmente se nenhuma referência ao(s) artista(s) foi armazenada . As novas folhas de estilo introduzidas em 1.4 permitem estilizar antes que um gráfico seja criado, mas não oferece nenhum meio de atualizar gráficos dinamicamente ou distinguir entre artistas do mesmo tipo (ou seja, especificar o e separadamente para objetos diferentes).line colorline styleLine2D

O desenvolvimento inicial deve se concentrar em permitir o estilo dos primitivos do artista (aqueles Artists que não contêm outros Artists), e o desenvolvimento posterior pode expandir as regras de sintaxe CSS e o analisador para permitir um estilo mais complexo. Consulte o apêndice para obter uma lista de primitivos.

A nova metodologia exigiria o desenvolvimento de uma série de etapas:

  • Uma nova sintaxe de folha de estilo (provavelmente baseada em CSS) para permitir a seleção de artistas por tipo, classe, id, etc.

  • Um mecanismo para analisar uma folha de estilo em uma árvore

  • Um mecanismo para traduzir a árvore de análise em algo que pode ser usado para atualizar as propriedades de artistas relevantes. Idealmente, isso implementaria um método para atravessar os artistas em uma estrutura semelhante a uma árvore.

  • Um mecanismo para gerar uma folha de estilo a partir das propriedades existentes do artista. Isso seria útil para permitir que um usuário exporte uma folha de estilo de uma figura existente (onde a aparência pode ter sido definida usando a API matplotlib)...

Implementação #

Será mais fácil permitir que um 'terceiro' modifique/defina o estilo de um artista se o 'estilo' for criado como uma classe separada e armazenado no artista como uma propriedade. A GraphicsContextBaseclasse já fornece a base de uma Styleclasse e o método de um artista drawpode ser refatorado para usar a Styleclasse em vez de configurar sua própria GraphicsContextBasee transferir suas propriedades relacionadas ao estilo para ela. Um exemplo mínimo de como isso pode ser implementado é mostrado aqui: https://github.com/JamesRamm/mpl_experiment

IMO, isso também tornará a API e a base de código muito mais organizadas, já que métodos get/set individuais para propriedades de estilo de artista agora são redundantes... Indiretamente relacionado seria uma unidade geral para substituir métodos get/set por propriedades. Implementar a classe de estilo com propriedades seria um grande passo em direção a isso...

Para o desenvolvimento inicial, sugiro desenvolver uma sintaxe baseada em uma versão muito (muito) simplificada do CSS. Sou a favor de dublar as Folhas de Estilo do Artista :+1: :

Gramática BNF #

Proponho uma sintaxe muito simples de implementar inicialmente (como uma prova de conceito), que pode ser expandida no futuro. A forma BNF da sintaxe é fornecida abaixo e depois explicada

RuleSet ::= SelectorSequence "{"Declaration"}"

SelectorSequence :: = Selector {"," Selector}

Declaration ::= propName":" propValue";"

Selector ::= ArtistIdent{"#"Ident}

propName ::= Ident

propValue ::= Ident | Number | Colour | "None"

ArtistIdent, Ident, Numbere Coloursão tokens (os blocos de construção básicos da expressão) que são definidos por expressões regulares.

Sintaxe #

Uma folha de estilo CSS consiste em uma série de conjuntos de regras em ordem hierárquica (as regras são aplicadas de cima para baixo). Cada regra segue a sintaxe

selector {attribute: value;}

Cada regra pode ter qualquer número de pares e uma folha de estilo pode ter qualquer número de regras.attribute: value

A sintaxe inicial é projetada apenas para Artistprimitivos. Ele não aborda a questão de como definir propriedades em Containertipos (cujas propriedades podem ser Artists com propriedades configuráveis), no entanto, uma solução futura para isso poderia ser simplesmente RuleSets aninhados

Seletores #

Os seletores definem o objeto ao qual as atualizações de atributo devem ser aplicadas. Como ponto de partida, proponho apenas 2 seletores para usar no desenvolvimento inicial:

Seletor de tipo de artista

Selecione um Artistpor seu tipo. Ex.: Line2Dou Text:

Line2D {attribute: value}

O regex para corresponder ao seletor de tipo de artista ( ArtistIdentna gramática BNF) seria:

ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'

Seletor GID #

Selecione um Artistpor seu gid:

Line2D#myGID {attribute: value}

A gidpode ser qualquer string, então o regex pode ser o seguinte:

Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'

Os seletores acima correspondem aproximadamente às suas contrapartes CSS ( http://www.w3.org/TR/CSS21/selector.html )

Atributos e valores #

  • Attributessão quaisquer propriedades válidas (configuráveis) para o Artistem questão.

  • Valuessão qualquer valor válido para a propriedade (geralmente uma string ou número).

Analisando #

A análise consistiria em dividir a folha de estilo em tokens (o livro de receitas do python fornece uma boa receita de tokenização na página 66), aplicar as regras de sintaxe e construir um arquivo Tree. Isso requer definir a gramática da folha de estilo (novamente, podemos pegar emprestado do CSS) e escrever um analisador. Felizmente, também existe uma receita para isso no livro de receitas do python.

Padrão de visitante para figura matplotlib #

Para aplicar as regras da folha de estilo aos artistas relevantes, precisamos 'visitar' cada artista em uma figura e aplicar a regra relevante. Aqui está uma aula de visitante (novamente, graças ao livro de receitas do python), onde cada um nodeseria um artista na figura. Um visit_método precisaria ser implementado para cada artista mpl, para lidar com as diferentes propriedades de 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)

Uma evaluatorclasse então pegaria as regras da folha de estilo e implementaria o visitante em cada uma delas.

Compatibilidade com versões anteriores #

A implementação de uma Styleclasse separada quebraria a compatibilidade com versões anteriores, pois muitos métodos get/set em um artista se tornariam redundantes. Embora seja possível alterar esses métodos para se conectar à Styleclasse (armazenados como uma propriedade contra o artista), eu seria a favor de simplesmente removê-los para limpar/simplificar a base de código e fornecer uma API simples e organizada. .

Alternativas #

Não há alternativas, mas parte do terreno coberto aqui se sobrepõe ao MEP25, o que pode ajudar nesse desenvolvimento

Apêndice #

Primitivas Matplotlib #

Isso formará os seletores iniciais que as folhas de estilo podem usar.

  • Linha2D

  • Texto

  • AxesImage

  • FiguraImagem

  • Correção