C sei deine Sprache

Vor einiger Zeit wollte ich gerne dieses schöne Script https://github.com/joshpetit/rofi-mixer zur Audio-Steuerung in meinem Window-Manager QTile benutzen.
An sich soll da eine Auswahl kommen über welches Gerät man denn gerne Audio abspielen möchte, bei mir war die Liste leider leer.
Zu meinem Glück handelt es sich hier um Python-Code und das Programm ist auch nicht all zu groß, der relevante Code ist in etwa das was hier passiert:

Weiterlesen…

Es werde mehr Licht

💡

In Desktop-Umgebungen wie LXDE, Gnome, KDE, XFCE kann die Helligkeit in der Regel über einen entsprechenden Dienst der Umgebung, der über Applets und Tastenkürzel angesteuert werden kann, eingestellt werden.

Die Helligkeit von Bildschirmen (gemeint sind hier die von Laptops und ähnlichen Geräten) wird unter Linux durch die Datei /sys/class/backlight/<Gerätename>/brightness dargestellt.
Der konkrete Pfad hängt davon ab wie der entsprechende Kernel-Treiber das Gerät nennt, auf meinem aktuellen Laptop ist es zum Beispiel /sys/class/backlight/amdgpu_bl1/brightness .
Ließt man die Datei:

cat /sys/class/backlight/<Gerätename>/brightness
133

Weiterlesen…

Datalist das bessere selection?!

Selection-Lists sind schon eine nette Sache.
Für den Benutzer, er muss nicht erraten was zur Auswahl steht und ggf. wie es richtig zu schreiben ist damit die Anwendung es auch versteht.
Und für Ersteller, er braucht nicht aus der Benutzereingabe zu erraten welche der Optionen wohl die richtige sein könnte - validieren muss er das was er zurückbekommt natürlich trotzdem.
Also eigentlich alles in Butter… bis sagen wir die Liste nicht mehr aus 4 Arten von Eiscreme besteht, sondern lang wird… sehr lang…
Dann wird es nervend durch die Liste zu scrollen und den richtigen Eintrag zu suchen.
Leider gibt es in selection keine Möglichkeit zu suchen.

Und noch ein Szenario gibt es wo selection an die Grenzen stößt: Was wenn man dem Benutzer eine Liste mit Auswahl geben will, aber gleichzeitig die Option einen anderen Wert manuell einzugeben?

Datalist zur Rettung

Angehängt

Ich hatte die Notwendigkeit (habe ich dann letzen Endes anders/sauberer gelöst) in Flask an eine URL Parameter anzuhängen.

Szenario

Das Szenario war:

  • Link löst Get-Request aus, mit Parameter refer_to="https://whatever.com"

  • Route verarbeitet Get-Request und bettet refer_to als Form-Feld ein

  • Form wird abgesendet und generiert Post-Request mit Form-Feldern refer_to="https://whatever.com" und customer_id=5748

  • Route verarbeitet Post-Request und sendet redirect auf "https://whatever.com?customer_id=5748"

Ziel war also im letzten Schritt die URL und die custome_id zu verheiraten.

Normalerweise würde man url_for(Funktionsname, parameter) aufrufen und das würde dann für die Funktion Funktionsname die URL ermitteln und ggf. (wenn es in der Route keine Platzhalter für die Parameter gibt) die Parameter hinten anhängen.
In diesem Fall hatte ich aber schon eine URL, nicht den Namen einer Funktion/Methode.

Lösung

Tatsächlich war es tatsächlich weniger trivial als gedacht, weder Flask, noch Werkzeug boten irgendeine Möglichkeit das zu machen, urllib aus der Standardbibliothek konnte es theoretisch umständlich über das zerlegen der URL in ihre Teile und dann neu zusammenbauen…
Und natürlich könnte man es auch über String-cocanation machen, aber das ist auch nicht sauber und kann Probleme geben mit der Kodierung.

Letzten Endes habe ich eine Lösung bei Stackoverflow gefunden https://stackoverflow.com/questions/2506379/add-params-to-given-url-in-python:

1
2
3
4
5
6
7
from requests import PreparedRequest

raw_url="https://whatever.com"
customer_id = "5748"
fakerequest = PreparedRequest()
fakerequest.prepare_url(raw_redirect_url, {"customer_id": customer_id})
redirect_url = fakerequest.url
  • Zeile 4 erstellt pro forma einen PreparedRequest → einen Request den man zusammenbaut, aber erst später absenden kann

  • Zeile 5 baut die URL zusammen, aus der URL die wir schon haben + dem Parameter den wir anhängen wollen. Die Parameter werden als Dictionary als 2 Parameter von prepare_url übergeben

  • Zeile 6 holt sich die URL die der PreparedRequest nutzen würde aus dem Objekt → das ist die zusammengesetzte URL

Und schon hat man die URL wie man sie haben will.

Schreibgeschützt

Flask (und andere Frameworks) können WTForm nutzen um das erstellen von Formularen zu vereinfachen.

class InvoiceForm(FlaskForm):
    customer = StringField("Kunde")

Die Feld-Klassen (hier "StringField") haben in der Regel nur Attribute die man in der Regel (also das minimale Set) für dieses HTML-Element setzen wird - hier also den Namen, man könnte auch einen Anzeige-Wert setzen oder einen Default-Wert.
In meinem Fall fehlte mir das Attribut um ein Feld "readonly" zu machen.

class InvoiceForm(FlaskForm):
    customer = StringField("Kunde", render_kw={"readonly": "True"})

Für diese Fälle kann in jeder Feldklasse das Attribut "render_kw" gesetzt werden.
Dieses nimmt ein Ditctionary entgegen, der Key ist zu setzende HTML-Attribut und der Wert der Wert der diesem HTML-Attribut zugewiesen werden soll.

Das resultierende HTM sähe also so aus:

<input id="customer" name="customer" type="text" readonly="True"></input>

"render_kw" kann also benutzt werden um beliebige zusätzliche Attribute in einem Form-Element zu setzen.

class InvoiceForm(FlaskForm):
    customer = StringField("Kunde", render_kw={"readonly": "True", "whatever":"whoever"})

ergibt:

<input id="customer" name="customer" type="text" readonly="True" whatever="whoever"></input>

Das Setzen von readonly in render_kw wirkt sich nur in der Darstellung im Browser aus.
Diese Einschränkung lässt sich (im Browser oder in dem man keinen Browser nutzt um es zu senden) einfach umgehen und das Feld auf einen beliebigen Wert setzen.
Das das Feld nicht geändert wurde/werden kann muss auf Server-Seite (also in Flask usw) sichergestellt werden.
Flask reicht render_kw einfach durch, daraus resultieren keine Validatoren/Cheks! Das muss anderweitig sichergestellt werden.
Vertraue niemals Daten die von Außen kommen!