Columnizer (jetzt: shcol)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu
Planst Du für eine kommende Version auch die Möglichkeit, separators zu definieren? Also sowas in der Art:

Code: Alles auswählen

>>> shcol.print_columnized(xrange(10), separator='|', spacing=6, line_width=25)
0   |   1   |   2   |   3
4   |   5   |   6   |   7
8   |   9
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

War bisher nicht geplant, kann ich aber durchaus einbauen, wenn Interesse besteht. Der Columnizer-Algorithmus macht übrigens eine spaltenweise Anzeige, d.h. von oben nach unten. Siehe: http://shcol.readthedocs.org/en/latest/ ... line-width

@mutetella: Welches Verhalten würdest du denn bei einem Spacing von 7 (ungerade Zahl) erwarten? Und würde sich deine Erwartung ändern, wenn der Trenner aus mehr als 1 Zeichen besteht?

Wenn ich so darüber nachdenke, dann ist es wahrscheinlich am besten, eine ``set_spacing(num_blanks, border='')``-Methode für Formatter-Klassen zu definieren. Dazu könnte man eine Standard-Implementierung bauen, die vom Anwender bei Bedarf überschrieben werden kann.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu
Als Lösung könnte ich mir vorstellen, dass
  • sich die Übergabe eines `separators`- mit der Übergabe eines `spacing`- Parameters ausschließen. Somit liegt die Entscheidung, wie ein ungerades Spacing oder mehrzeichiger Separator gehandelt werden soll, beim Nutzer.
  • der `spacing`-Parameter in `spacing_left` und `spacing_right` aufgeteilt ist.
  • ein klitzekleines bischen Magie :wink: Ungerades einfach gerade macht.
Langsam aber stetig gelange ich endlich zu der Einsicht, nicht alles selbst machen zu können/müssen... :? Deshalb bin ich am Überlegen, Deinen Columnizer für meinen Kalender zu verwenden. Und da fände ich den Einsatz von Separatoren ganz schön.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Okay, das wird jetzt ein bißchen sehr speziell. Insbesondere sehe ich wenig Sinn in `spacing_left` und `spacing_right`. Wozu soll das gut sein?

Du kannst dir übrigens einen eigenen Formatter schreiben, basierend auf `shcol.core.IterableFormatter`. Kandidaten zum Überschreiben wären vermutlich mindestens eine der letzten 3 Methoden dieser Klasse (aktuell ab Zeile 293). Dort werden die Templates erstellt, welche dann an anderer Stelle für jede einzelne Zeile via ``template % items`` vom Formatter verwendet werden. Hier könntest du ja mit deinem Trenner ansetzen und einen abgeleiteten `CalendarFormatter` erstellen.

Die spätere Verwendung deines Formatters ist dann recht unkompliziert. Ein Beispiel mit den zuvor von dir genutzten Werten:

Code: Alles auswählen

formatter = CalendarFormatter.for_line_config(spacing=6, line_width=25)
print(formatter.format(items))
Und übrigens: Das `calendar`-Modul aus Pythons Standardbibliothek ist dir ja bekannt, oder? Reichen dir die dortigen Formatierungsmöglichkeiten nicht aus?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu
Das mit dem eigenen Formatter schau' ich mir an. Das `calendar` Modul kenn' ich natürlich, hilft mir aber bei der Ausgabe von Terminen mit all' seinen Infos nicht weiter.

Aber ok, ich schau' mir `shcol` jetzt mal tiefer an. Danke für Deine Arbeit!

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

`shcol` hat übrigens neben dem, was ich inzwischen in der HTML-Doku aufgeführt habe, noch so nette Features wie `shcol.print_attr_names()`, welches dir auf Basis von `dir()` alle Attribute eines übergebenen Objektes übersichtlich darstellt. Diese Ausgabe finde ich persönlich schöner als die Listenform oder die IPython-Ausgabe. Ebenso ist ``shcol.print_columnized(os.environ)`` sicherlich mal einen Blick wert. Dort sieht man, dass lange Werte in Wörterbüchern bei Bedarf durch `shcol` über mehrere Zeilen verteilt werden und dabei trotzdem in "ihrer" Spalte verbleiben, so wie man es z.B. bei einer Tabelle erwarten würde, wenn man eine mehrzeilige Tabellenzelle hat.
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mutetella hat geschrieben:Aber ok, ich schau' mir `shcol` jetzt mal tiefer an.
Verwende zum Ausprobieren am besten, wie hier beschrieben, den folgenden Befehl:

Code: Alles auswählen

pip install git+git://github.com/seblin/shcol.git
Damit installierst du dir den aktuellen Stand aus dem Github-Repo. Ich achte darauf, dass ich nur lauffähige Versionen ins Repo hochlade.
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@mutetella: Ich habe mal zum Spaß die Version auf meinem Rechner umgeschrieben. Ich bekommen nun folgende Ausgabe hin:

Code: Alles auswählen

>>> print(formatter.format(range(1, 31)))
1   |   9    |   17   |   25
2   |   10   |   18   |   26
3   |   11   |   19   |   27
4   |   12   |   20   |   28
5   |   13   |   21   |   29
6   |   14   |   22   |   30
7   |   15   |   23
8   |   16   |   24
Hast du dir das so in der Art vorgestellt?

Realisiert habe ich dies durch ein `spacer`-Argument. Dafür müsste ich aber an etlichen Stellen Änderungen vornehmen, wenn man den Spacer von Anfang an übergeben könnte. Die hinzugekommene Methode sieht so aus:

Code: Alles auswählen

    def make_column_separator(self, spacing):
        if self.spacer:
            padding = (spacing // 2) * ' '
            sep = padding + self.spacer + padding
        else:
            sep = spacing * ' '
        return sep
Diese wird verwendet in der letzten Zeile von `make_line_template()` (auf die ich bereits verwiesen hatte). Sie lautet dann:

Code: Alles auswählen

return self.make_column_separator(props.spacing).join(parts)
Du kannst dies gerne als Orientierung für den eigenen Formatter benutzen. Ich möchte bald shcol 0.3 rausbringen und aktuell keine Änderungen an der dokumentierten Schnittstelle vornehmen. Daher wird es keinen Spacer in shcol 0.3 geben.

Für Version 0.4 kannst du aber sehr wahrscheinlich damit rechnen. Dafür plane ich, die eigentliche Template-Erzeugung aus dem Formatter-Code rauszunehmen und über einen `TemplateGenerator` zu realisieren. Das ist auf Dauer flexibler sowohl für den Anwender als auch für mich und schränkt die Menge an Argumenten für eine Formatter-Instanz mithilfe der Auslagerung etwas ein. Außerdem möchte ich bis dahin die Erzeugung von Templates für modernes String-Formatting (``'{}'.format('spam')``) als Alternative zum klassischen String-Formatting anbieten. Auch dafür stelle ich mir die Implementierung mit einer gesonderten Klasse einfacher bzw sauberer vor.
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

shcol 0.3 ist draußen!

Habe es vor wenigen Minuten auf PyPI hochgeladen. Installation wie immer mittels ``pip install --upgrade shcol``.

Informationen zu den wichtigsten Features gibt es in der Doku.

@mutetella:
Die Sache mit dem konfigurierbaren Trennzeichen habe ich nicht vergessen, auch wenn sie es nicht ins aktuelle Release geschafft hat. Du kannst davon ausgehen, dass ich dies neben einigen anderen Dingen in die kommende Version einbringen werde.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

snafu hat geschrieben:Die Sache mit dem konfigurierbaren Trennzeichen habe ich nicht vergessen, […]
Ich auch nicht :wink: , bin aber auch immer noch bzw. wieder einmal mit den Innereien meines Kalenders beschäftigt. Das Thema UI hat also noch Zeit… einfach blöd, wenn man oft über Wochen hinweg keine Zeit hat und dann immer wieder erst den Faden aufnehmen muss, bevor man ein Stück weiter kommt…
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mutetella hat geschrieben:einfach blöd, wenn man oft über Wochen hinweg keine Zeit hat und dann immer wieder erst den Faden aufnehmen muss, bevor man ein Stück weiter kommt…
Ging mir genau so, dass ich privat andere Sachen zu tun hatte und `shcol` sogar einige Monate brach lag. Naja, Hobbyprojekte sollen ja Spaß machen und keinen Zwang darstellen. Insofern mache ich mir da keinen unnötigen Stress.
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mutetella hat geschrieben:@snafu
Planst Du für eine kommende Version auch die Möglichkeit, separators zu definieren? Also sowas in der Art:

Code: Alles auswählen

>>> shcol.print_columnized(xrange(10), separator='|', spacing=6, line_width=25)
0   |   1   |   2   |   3
4   |   5   |   6   |   7
8   |   9
mutetella
Ist nun in der Entwicklungsversion auf GitHub enthalten:

Code: Alles auswählen

>>> shcol.print_columnized(xrange(16), extra_sep='|', spacing=6, line_width=25)
0   |   4   |   8    |   12
1   |   5   |   9    |   13
2   |   6   |   10   |   14
3   |   7   |   11   |   15
Die Ausrichtung ist spaltenweise, so wie man es von `shcol` gewohnt ist. Außerdem habe ich die Implementierung noch nicht komplett durchdacht, da es jetzt zu überlangen Zeilen kommen kann. Wird aber noch behoben.
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Habe mich nach zwei Jahren Pause nochmal an die Arbeit gemacht und zunächst den Unterbau komplett neu geschrieben. Er basiert jetzt auf Python 3 (wobei Python 2.7 mit wenigen Anpassungen möglich sein dürfte), nutzt das moderne String-Formatting, kann nun links- und rechtsbündig schreiben. Außerdem ist bestimmbar, ob die Anordnung vertikal oder horizontal sein soll. Was noch fehlt, ist die automatische Erkennung der benötigten Spalten für eine möglichst hohe Zeilenlänge. Da muss man die Spaltenzahl derzeit noch manuell eingeben, aber ich arbeite dran. Hat ja bei der Vorgängerversion auch funktioniert. Hier mein Zwischenstand:

https://gist.github.com/seblin/be07bb48 ... c05dcc4100

Die Funktion columnize() nimmt alles aus dem Config-Dict auch direkt per Parameter an, also z.B.

Code: Alles auswählen

print(columnize(range(1, 31), num_columns=5, align='right', vertical=False, spacer=' | '))
Viel Spaß an alle Interessierten!
Benutzeravatar
snafu
User
Beiträge: 6779
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Nach einer weiteren __kleineren__ Verzögerung habe ich das Skript mal zu Ende gepfuscht und an die Möglichkeiten von Python 3.12 angepasst. Es hört nun auf den Namen "simplecol" und kann mittlerweile mit Mappings und Path-Objekten umgehen. Der Spaltentrenner kann ein beliebiger String sein. Spalten werden als Column-Objekte realisiert, die nun auch eine Maximalbreite annehmen, sowie den Text links-/rechtsbündig oder zentriert ausrichten können (wobei hier der entsprechende Specifier für Pythons String Formatting übergeben wird). Mehrere Spalten werden von einem Frame-Objekt zusammengehalten und von diesem auch gerendert. Sind Inhalte größer als die Spaltenbreite, dann werden Umbrüche gemacht, sodass es am Anfang der Spalte in der nächsten Zeile weitergeht. Bei Mappings passt er die Breiten automatisch an, sodass z. B. die Ausgabe von os.environ bei Bedarf (etwa für den PATH) mit Umbrüchen vollzogen wird. Tests sind quasi nicht vorhanden, eine Doku existiert nicht und die CLI werde ich wahrscheinlich von dem externen fire-Package erzeugen lassen. Aber seht selbst: https://gist.github.com/seblin/0a0825b9 ... 167f5f7dec
Antworten