python xml subclass pretty-print docbook

python - La mejor manera de implementar impresoras bonitas personalizadas.



xml subclass (4)

Considera usar el módulo pretty :

Personalizando pprint.PrettyPrinter

La documentación para el módulo pprint menciona que el método PrettyPrinter.format está destinado a hacer posible personalizar el formato.

Supongo que es posible anular este método en una subclase, pero esto no parece proporcionar una manera de hacer que los métodos de la clase base apliquen el ajuste de línea y la sangría.

  • ¿Me estoy perdiendo de algo?
  • ¿Hay una mejor manera de hacerlo (por ejemplo, otro módulo)?

¿Alternativas?

He comprobado el pretty módulo, que parece interesante, pero no parece proporcionar una forma de personalizar el formato de las clases de otros módulos sin modificar esos módulos.

Creo que lo que estoy buscando es algo que me permita proporcionar una asignación de tipos (o quizás funciones) que identifique los tipos a las rutinas que procesan un nodo. Las rutinas que procesan un nodo tomarían un nodo y devolverían la cadena que lo representa, junto con una lista de nodos secundarios. Y así.

¿Por qué estoy buscando en la impresión bonita

Mi objetivo final es imprimir de forma compacta las secciones con formato personalizado de un xml.etree.ElementTree formato xml.etree.ElementTree .

(Me sorprendió no encontrar más soporte Python para DocBook. Tal vez me perdí algo allí).

Construí algunas funciones básicas en un cliente llamado xmlearn que usa lxml . Por ejemplo, para volcar un archivo de Docbook, podría:

xmlearn -i docbook_file.xml dump -f docbook -r book

Es bastante medio, pero me dio la información que estaba buscando.

xmlearn tiene otras características, como la capacidad de construir una imagen gráfica y hacer volcados que muestran las relaciones entre las etiquetas en un documento XML. Estos son casi totalmente ajenos a esta pregunta.

También puede realizar un volcado a una profundidad arbitraria, o especificar un XPath como un conjunto de puntos de partida. El tipo de XPath hace que el formato específico del docbook quede obsoleto, por lo que no está realmente bien desarrollado.

Esto todavía no es realmente una respuesta para la pregunta. Todavía estoy esperando que haya una impresora bonita fácilmente personalizable por ahí en algún lugar.


Mi solución fue reemplazar pprint.PrettyPrinter con un envoltorio simple que formatea cualquier flota que encuentre antes de llamar a la impresora original.

from __future__ import division import pprint if not hasattr(pprint,''old_printer''): pprint.old_printer=pprint.PrettyPrinter class MyPrettyPrinter(pprint.old_printer): def _format(self,obj,*args,**kwargs): if isinstance(obj,float): obj=round(obj,4) return pprint.old_printer._format(self,obj,*args,**kwargs) pprint.PrettyPrinter=MyPrettyPrinter def pp(obj): pprint.pprint(obj) if __name__==''__main__'': x=[1,2,4,6,457,3,8,3,4] x=[_/17 for _ in x] pp(x)


Si desea modificar la impresora bonita predeterminada sin _dispatch subclases, puede usar la tabla _dispatch interna en la clase pprint.PrettyPrinter . Puede ver cómo ejemplos de cómo se agrega el envío para tipos internos como diccionarios y listas en la fuente .

Aquí es cómo agregué una impresora bonita personalizada para el tipo de operación de MatchPy :

import pprint import matchpy def _pprint_operation(self, object, stream, indent, allowance, context, level): """ Modified from pprint dict https://github.com/python/cpython/blob/3.7/Lib/pprint.py#L194 """ operands = object.operands if not operands: stream.write(repr(object)) return cls = object.__class__ stream.write(cls.__name__ + "(") self._format_items( operands, stream, indent + len(cls.__name__), allowance + 1, context, level ) stream.write(")") pprint.PrettyPrinter._dispatch[matchpy.Operation.__repr__] = _pprint_operation

Ahora, si uso pprint.pprint en cualquier objeto que tenga la misma __repr__ que matchpy.Operation , usará este método para imprimirlo bastante. Esto también funciona en las subclases, siempre que no anulen el __repr__ , ¡lo cual tiene sentido! Si tiene el mismo __repr__ tiene el mismo comportamiento de impresión bonito.

Aquí hay un ejemplo de la bonita impresión de algunas operaciones MatchPy ahora:

ReshapeVector(Vector(Scalar(''1'')), Vector(Index(Vector(Scalar(''0'')), If(Scalar(''True''), Scalar("ReshapeVector(Vector(Scalar(''2''), Scalar(''2'')), Iota(Scalar(''10'')))"), Scalar("ReshapeVector(Vector(Scalar(''2''), Scalar(''2'')), Ravel(Iota(Scalar(''10''))))")))))


Esta pregunta puede ser un duplicado de:

Usando pprint.PrettyPrinter

Miré a través de la fuente de pprint . Parece sugerir que, para mejorar pprint() , deberías:

  • subclase PrettyPrinter
  • anular _format()
  • prueba para issubclass() ,
  • y (si no es su clase), regrese a _format()

Alternativa

Creo que un mejor enfoque sería tener tu propia pprint() , que difiere de pprint.pformat cuando no sabe lo que pasa.

Por ejemplo:

''''''Extending pprint'''''' from pprint import pformat class CrazyClass: pass def prettyformat(obj): if isinstance(obj, CrazyClass): return "^CrazyFoSho^" else: return pformat(obj) def prettyp(obj): print(prettyformat(obj)) # test prettyp([1]*100) prettyp(CrazyClass())

La gran ventaja aquí es que no dependes de los pprint internos de la pprint . Es explícito y conciso.

El inconveniente es que tendrás que cuidar la sangría manualmente.