kleine irc lib

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
DasIch
User
Beiträge: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Dienstag 4. November 2008, 18:20

Danke, dass ist natürlich genial :)
DasIch
User
Beiträge: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mittwoch 19. November 2008, 00:11

Leonidas hat geschrieben:Das Problem ist bei IRC leider das, dass man nicht weiß was da für eine Antwort auf welchen Request kommt.
Man kennt ja die Möglichkeiten.
Insbesondere mit NAMES hatte ich recht viel Ärger. Da müsste man ein wenig Arbeit investieren und masochistisch genug sein, die Unittests weiterzuschreiben[...]
Names? Wo ist da die Problematik? Hast du Unittests selbst für die Deferreds bei jedem Befehl? :shock:

Momentaner Stand ist dass ich isupport implementiert habe und dabei bin Befehl für Befehl aus dem RFC zu implementieren. Ich muss noch den ganzen Mode Kram implementieren und einige Befehle. Ich möchte vorallem verhindern Dinge an den Server zu senden bei denen ich schon vorher weiß dass dabei nichts bei rum kommt(kicken ohne dass man OP ist usw.).

Nur damit ihr nicht glaubt dass ganze wäre schon Tod ;)
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Mittwoch 19. November 2008, 01:08

Warum verwendest du locals?

Ersetz doch einfach jeden Namen mit dem fertig konfigurierten Objekt in dem dict. Ausnahmebehandlung geht dann direkt über dict Zugriff. Und das "copy" Zeug da würd ich in eine "clone" Methode des Exception Prototyps auslagern.

Klassen Klonen würde ich so machen:

Code: Alles auswählen

In [6]: class A(object):
    @classmethod
    def clone(cls, name=None):
        if name is None: name = cls.__name__
        cloned = cls.__class__(name, (object,), cls.__dict__.copy())
        return cloned
   ...:     
   ...:     

In [10]: B = A.clone("Fish")

In [11]: B
Out[11]: <class '__main__.Fish'>
Übringens habe ich prototyping durch die Sprache Io vor kurzem zu Schätzen gelernt, insofern empfinde ich das als nichts, wofür man sich entschuldigen müsste (und "to much stupid code" meint wogl zig Subklassen?) ;)

Statt dem hier:

Code: Alles auswählen

    wrapper.__name__ = f.__name__
    wrapper.__doc__ = f.__doc__
kannst du wie weiter oben erwähnt functools.wraps benutzen.

Die vielen Strings unbedingt noch in Konstante, globale Variablen umwandeln. Liest sich besser und ist flexibler. Insbesondere "\r\n" macht bei sowas viel Spaß. Ist das eigentlich was IRC internes? Ansonsten gibts os.linesep.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 19. November 2008, 01:42

DasIch hat geschrieben:Man kennt ja die Möglichkeiten.
Eben nicht. Wenn man mehrere Parallele NAMES ausführt, einige für einen Channel, einige führ mehrere Channels und einen für alle Channels kann man nicht mehr zuordnen, welche Antowort zu welchem Reuest passt und kann also nicht zuverlässig die entsprechenden Deferreds auslösen.
DasIch hat geschrieben:Hast du Unittests selbst für die Deferreds bei jedem Befehl? :shock:
Natürlich teste ich die Deferreds und gucke ob die richtig ausgelöst werden. Und da teste ich lieber in Unittests als dann die Clients im Real-World Betrieb aufgrund von Race-Conditions nichtreproduzierbaren Müll zurückbekommen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
DasIch
User
Beiträge: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mittwoch 19. November 2008, 06:51

Leonidas hat geschrieben:Wenn man mehrere Parallele NAMES ausführt[...]
Hm, daran hab ich nicht gedacht, allerdings könnte ich meinen Wrapper anpassen dann passt dass wieder.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 19. November 2008, 10:08

DasIch hat geschrieben:Hm, daran hab ich nicht gedacht, allerdings könnte ich meinen Wrapper anpassen dann passt dass wieder.
Und wie ordnerst du den NAME-Reply den richtigen Deferred zu? Spätestens wenn jemand einen Channel anfordert und danach alle, weißt du nicht welche Antwort zu welchem Request gehört.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
DasIch
User
Beiträge: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mittwoch 19. November 2008, 15:58

str1442 hat geschrieben:Warum verwendest du locals?
Das war quick'n'dirty und auf jedenfall kürzer als dein Code ;)
Ersetz doch einfach jeden Namen mit dem fertig konfigurierten Objekt in dem dict. Ausnahmebehandlung geht dann direkt über dict Zugriff.
Bisschen großer Aufwand für Informationen die statisch vorliegen könnten oder?
Und das "copy" Zeug da würd ich in eine "clone" Methode des Exception Prototyps auslagern.
Wieder jede Menge Code dafür ;)
Übringens habe ich prototyping durch die Sprache Io vor kurzem zu Schätzen gelernt, insofern empfinde ich das als nichts, wofür man sich entschuldigen müsste (und "to much stupid code" meint wogl zig Subklassen?) ;)
Ich hatte keine Lust die alle selbst einzutippen. Inzwischen hab ich mir den Code einmal komplett generieren lassen und hab nun ein exc Modul wo die ganzen Exceptions drin sind. War mit einem kleinen Skript schnell erledigt und die Lösung ist imho am sinnvollsten.
Die vielen Strings unbedingt noch in Konstante, globale Variablen umwandeln.
Welche vielen Strings?
Insbesondere "\r\n" macht bei sowas viel Spaß. Ist das eigentlich was IRC internes?
Ja. damit werden die Nachrichten voneinander getrennt, dafür brauche ich aber keine Konstante. Das wäre ja als ob man sich SQL Strings selbst zusammensetzt.
Leonidas hat geschrieben:Spätestens wenn jemand einen Channel anfordert und danach alle, weißt du nicht welche Antwort zu welchem Request gehört.
Ich gehe mal davon aus dass der Server die Replys nicht willkürlich durcheinander schickt, dann wäre es tatsächlich unmöglich. Wenn ich die RPL_ENDOFNA MES bekomme sollte es möglich sein die vorher erhaltenen RPL_NAMREPLYs anhand der übergebenen Argumente zuzuordnen.

Wobei ich sowieso vorhabe einfach JOIN, PART und QUIT Nachrichten zu verfolgen und so selbst eine lokale User Liste vorzuhalten für die Channels in denen ich bin. NAMES sendet mir sowieso nur Informationen über User die ich sowieso sehe.
Wenn man eine Liste der Nicks für einen IRC Client oder so haben will, bleibt mir sowieso nichts anderes übrig. Man kann ja schlecht alle paar Minuten ein NAMES an den Server schicken.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Mittwoch 19. November 2008, 22:36

Das war quick'n'dirty und auf jedenfall kürzer als dein Code Wink
Und die Ersparnis von vielleicht 10 Zeilen spricht nun für locals? Warum benutzt du dann nicht gleich

Code: Alles auswählen

setattr(__builtins__, numeric_to_symbolic[number], eval("type(%s, (Exception,), {})" % numeric_to_symbolic[number])
.
Ich hatte keine Lust die alle selbst einzutippen. Inzwischen hab ich mir den Code einmal komplett generieren lassen und hab nun ein exc Modul wo die ganzen Exceptions drin sind. War mit einem kleinen Skript schnell erledigt und die Lösung ist imho am sinnvollsten.
Codegenerierung ist idR keine gute Idee. Damit machst du Dinge nur unnötig statisch, unanpassbar, unmaintainable weil groß.
Warum willst du es überhaupt statisch haben?

Ist ja nicht so, das ich hier von 400 extra Zeilen spreche.
Wieder jede Menge Code dafür ;)
14 Zeilen? Erzähl mir nicht, deine Ausflüge in die Metaprogrammierung ergaben kürzeres.
Welche vielen Strings?
In parse(). Gut, globals müssens nicht sein, aber locals vielleicht. ":" und " :" sind zb kontextbehaftet, und sowas sollte man imho immer mit einem Variablennamen versehen, der natürlich auch gut benannt ist. Liest sich besser, macht keinen Aufwand und solltest du die Funktion erweitern wollen, ist das auch einfacher. Dann überprüfst du in "to_irc" direkt mit einem hardgecodeten String, ob eben dieser im Dict zu finden ist. Das ist doch wieder vom Kontext komplett losgelöst. Irgendein Dict kommt rein, irgendein hardgecodeter String wird benutzt, der per se mit dem Rest des Programmes höchstens semantisch etwas zu tun hat. Sowas gehört imho in globale Variablen.
Ja. damit werden die Nachrichten voneinander getrennt, dafür brauche ich aber keine Konstante. Das wäre ja als ob man sich SQL Strings selbst zusammensetzt.
Rein prinzipiell würde ich für sowas Konstanten benutzen. Aus oben genannten Gründen. Was du da machst, ist (wenn im größeren Stil eingesetzt) in etwa so, wie jeden String aus Gründen des Speichersparens in einem Programm komplett auszuschreiben, nur weil man weiß, das höchstwahrscheinlich keine anderen Strings irgendwo ankommen. Oder überall lambda Statements statt Funktionen und die auch nicht in Variablen festzuhalten. Klingt jetzt extrem, aber so rein prinzipiell...
DasIch
User
Beiträge: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Mittwoch 19. November 2008, 23:06

str1442 hat geschrieben:Codegenerierung ist idR keine gute Idee. Damit machst du Dinge nur unnötig statisch, unanpassbar, unmaintainable weil groß.
Warum willst du es überhaupt statisch haben?
Richtig, aber beim IRC Protokoll wird sich nicht alle paar Wochen was ändern.

Genauso sieht es mit den IRC Messages aus, die werden auch noch ewig so aussehen ohne dass sich daran irgendwas grundlegendes ändert. Statt irgendwelche Konstanten zu verwenden die den Code verständlicher machen sollen, schreibe ich lieber gleich Kommentare, die dass ganze erklären. Dann bekomme ich auch nicht solche Probleme ;)
Antworten