Trac Plug-In Programmierung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Hallo,
ich programmiere gerade für Trac ein Plug-In. Mein Problem ist, dass die Instanz des Plug-Ins auf Daten zugreifen soll die im Plugin abgelegt sind. Wie kann ich diese Daten (zB ein Javascript) richtig adressieren?
Muss ich dass mit dem ITemplateProvider machen?

Kennt sich da jemand aus? Würde mich über eine Antwort freuen.

Viele Grüße
Micha
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

Hi,

an sich gibts dafür ein tolles cookingegg beispiel. Diese ist zwar für Version 0.11, aber für das Grundverständnis ist das ganz gut.

http://trac-hacks.org/wiki/EggCookingTutorialTrac0.11

Mach das einfach mal schnell durch, da wird dir erlkärt wie du externe Resourcen einbindest, Tabs in der NavBar anlegst und neue Seiten mit der Template Engine erstellt.

An sich pflegst du CSS wie folgt ein:

Code: Alles auswählen

 # IRequestHandler methods
    def match_request(self, req):
        return re.match(r'/helloworld(?:_trac)?(?:/.*)?$', req.path_info)

    def process_request(self, req):
        data = {}
        add_stylesheet(req, 'hw/css/helloworld.css')
        # This tuple is for Genshi (template_name, data, content_type)
        # Without data the trac layout will not appear.
        return 'helloworld.html', data, None
zusätzlich must du aber die setup konfiguration anpassen.
Das zu erklären ist jetzt eher sinnfrei, da es auf der Seite gut erklärt ist. Mach das einfach schnell durch.

Ansonsten wenn du Fragen hast, meld ich ruhig nochmal

Ich schreibe seit 5 Monaten an meiner Abschlussarbeit, die sich genau damit beschäftigt.
d.h. Plugin Entwicklung für Trac

Grüße

Stefan
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

rads hat geschrieben:Ich schreibe seit 5 Monaten an meiner Abschlussarbeit, die sich genau damit beschäftigt.
d.h. Plugin Entwicklung für Trac
Die könntest du ja nach Abgabe ins Netz stellen. *bettel*
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

/me hat geschrieben: Die könntest du ja nach Abgabe ins Netz stellen. *bettel*
Noch bin ich mir nicht sicher ob das einen interessierten oder bösartigen Hintergedanken hat,
auch ist es ja nach Anspruch der Professoren ein "wissenschaftliches" Dokument und
kein Handbuch.

Aber sollte echtes Interesse bestehen, ohne das ich mir danach 100 Ohrfeigen abholen
muss, so kann ich gerne Teile daraus zu Verfügung stellen.

Die Plugins(kostenverrechnung, odf report, odc fremdsystemanbindung, "frames-like-look"..)
darf ich leider nicht veröffentlichen, da diese Eigentum der Firma sind.

Auch bin ich froh wenn das "schöne" Thema endlich rum ist.

Grüße

Stefan
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

rads hat geschrieben:Noch bin ich mir nicht sicher ob das einen interessierten oder bösartigen Hintergedanken hat,
auch ist es ja nach Anspruch der Professoren ein "wissenschaftliches" Dokument und
kein Handbuch.
Kenne ich. Wir haben neulich noch mit einem Team von drei Leuten eine 30seitige Arbeit über "Kollaboratives Projektmanagement mit Trac" abgeliefert. Aufgrund des wissenschaftlichen Anspruchs waren insbesondere Zitate immer seeehr wichtig. Für den Enduser ist es aber wahrscheinlich weniger zu gebrauchen.
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

Genau so ist es leider.
Ich bin momentan auf Seite 50 und hab bis dato neben zwei SQL Statements noch keine 10 Zeilen code im Dokument.
Aber dafür viel UML :)

Grüße
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Danke für die Antwort. Ich hätte die Frage ein wenig spezifischer stellen sollen. Das HelloWorld Beispiel habe ich bereits nachgemacht (dennoch danke für den Tipp)

Mein Plugin funktioniert aber ein wenig anders (soll anders funktionieren). Es basiert auf einem Plugin Namens "GoogleChartPlugin. http://trac-hacks.org/wiki/GoogleChartPlugin
Man kann dort z.B. wenn man eine Wiki Seite bearbeitet direkt SQL Statements in hübsche Graphen transformieren. Ich will jetzt hauptsächlich anstelle von statischen Bildern wie beim GoogleChartPlugin, Flash Charts anzeigen lassen (m.H.v. pyOFC2), muss dazu aber ermöglichen dass innerhalb des HTML codes der Wiki Seite auf z.B. ein Javascript zugegriffen werden kann.

Geht dass genau so wie wenn ich mein Plugin in einem Reiter erscheinen lasse? Der erste Versuch einfach die ITemplateProvider Methoden zu übernehmen und (aus Versuchszwecken) den HTML Code des Hello World templates als return des Plug-Ins zu verwenden, führt dazu dass zwar in der bearbeiteten Seite die Überschriften usw. richtig angezeigt werden aber nicht z.B. ein Bild.

Vielen Dank fürs Helfen!

Gruß
Micha

Edit: Im HelloWorld Plug-In habe ich es hinbekommen das Flash Chart anzeigen zu lassen, also im Prinzip gehts schon irgendwie.
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

Ach mist, du wolltest JS und nicht CSS

Code: Alles auswählen

 def process_request(self, req):
        data = {}  
        if req.path_info .startswith('/page'):
            add_script(req, 'hw/select.js')      
        return 'page.html', data, None
Also wie bei CSS oben, nur das es dafür die Function add_script gibt.

Natürilch musst du dann das Wiki Template anpassen, dass dein JavaScript auch entsprechend
verwendet wird.
Hierfür schlag ich immer gerne von ITemplateStreamsFilter die Methode filter_Stream und von
Genshi das Modul Transformer vor.

Grüße

Edit: HW steht hier für das in get_htdocs_dir angegebene htdocs verzeichnis.
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Ah okay so langsam verstehe ich, danke. Für was steht /page?
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

Page steht für die aufgerufen Seite, du willst ja das JS z.b. nur in einer Ticket Seite einfügen, so würde dort Ticket statt Page stehen.
Für Wiki sollte der Pfad mit /wiki anfangen, glaub ich zumindest. Hab im Moment keinen Zugriff auf das System, falls es probleme gibt, meld dich ruhig nochmal.

Grüße
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Hmm... also was mir aber gerade einfiel ist, dass ich das im Hello World Beispiel hinbekommen habe, auch ohne process_request zu spezifizieren. Es scheint zu langen wenn man dass im HTML Code richtig macht.... oder wird das nötig weil ich kein extra Tab haben möchte?
Auch komisch ist, warum ich es noch nicht einmal schaffe ein statisches Bild anzeigen zu lassen - müsste ich das dann auch extra angeben?

Gruß
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

So wie ich das sehe wird im EggCooking Beispiel auch mit process_request gearbeitet.
Was ich jetzt nicht ausprobieren kann, ob wenn man die Einschränkung weglässt das JS
in jeder Seite eingebaut wird, was ja nicht notwenig ist, oder ob über match_request
bereits die Einschränkung vorgenommen wurde.

Um dein Bild zu sehen musst die Egg Ordnerstruktur mit der in setup.py angegebenen Struktur
übereinstimmen

Beispiel (EggCooking Bsp 3)

Code: Alles auswählen

  package_data={'helloworld': ['templates/*.html', 
                                 'htdocs/css/*.css', 
                                 'htdocs/images/*']},
Und es ist zwingend notwendig ITemplateProvider entsprechend zu definieren, wie du den Link in
der HTML Seite setzt.

Am besten du kopierst dir schnell egg beispiel 3 und baust deine egg-struktur genauso auf.
Vielleicht hilft das.

Ansonsten müsste ich Programmcode, sowie die Ordnerstruktur sehen, um dir helfen zu können.

Grüße
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Danke mal soweit. Die Ordnerstruktur stimmt schon.

Im HelloWorld Beispiel wurde schon mit process_request gearbeitet. ich meinte damit ich konnte auch ohne dort mein Javascript zu erwähnen später folgendes lauffähig verwenden:
Das ist jetzt ein Auschnitt von dem was im Extratab im helloWorld Beispiel erfolgreich in ein Flashobjekt umgewandelt wird, aber nicht innnerhalb der Wikiseite.
<head>
<script type="text/javascript" src="${href.chrome('/hw/js/swfobject.js')}"></script>
<script type="text/javascript">
swfobject.embedSWF(
"${href.chrome('/hw/swf/open-flash-chart.swf')}", "chart_bar_2", "780", "300",
"9.0.0", "expressInstall.swf",
{"data-file":"${href.chrome('/hw/data/bar_2.json')}"}
);
</script>
</head>

Also ich referenziere die Dinge wie es im HW Plugin gemacht wird und es klappt ohne dass ich diese nochmals im process_request erwähnen müsste.
Mein Problem ist, dass ich es nicht schaffe diesen Code erfolgreich in zB eine Trac-Seite die ich neu erstelle einzubetten.

Hier wie es (für Versuchszwecke) aussehen sollte: Bild

Hier wie es derzeit in meinem Plug-In aussieht: Bild

Edit: Ich glaube man kann es auf folgendes herunterbrechen: Ist es z.B. möglich im Code des Plug-Ins Zugriff auf eine Textdatei test.txt zu bekommen (Also ich meine mittels der Built-in Function open("test.txt", "r") ) und falls ja wie adressiere ich test dann (z.B. wenn es in /hw/txt/ abgelegt ist)?
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

Das Problem hatte ich auch schonmal, auch hier im Forum behandelt.

Siehe: http://www.python-forum.de/viewtopic.ph ... g+struktur

Adressierung

Code: Alles auswählen

os.path.dirname(__file__)+"/htdocs/html/budgetingfieldset.html"
An sich kannst du auch wenn du das template bearbeitest das Javascript einbinden, wenn
es korrekt im setup.py angegeben und die Methode von htdocs korrekt definiert wurden.

Ich persönich finde die separate methode schöner, da ich hier nicht nicht so schnell die Übersicht verliere.

Es kommt allerdings darauf an wie du versuchst den Code einzubetten. Genshi filter aus Sicherheitsgründen "gefährlichen"
Code raus. Deine HTML Vorlage müsste, so wie ich es im Kopf habe, die Anweisungen schon enthalten.
Über Transform bekommst du die nicht rein, höchstens es gibt im Filter Modul noch etwas was ich übesehen hätte.

Wenn du es allerdings direkt im Template einbaust, dann müsste man schauen ob vielleicht der wiki_to_html konverter
irgendwas lustiges macht.
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Wow super! Danke, das hilft mir wirklich sehr weiter!

Gibt es eigentlich eine Möglichkeit auch den Pfad direkt zum chrome Ordner zu bekommen? Also quasi wie "os.path.dirname(__file__) + "/htdocs/file"" nur den Pfad der mir auch mit "${href.chrome('/hw/file')}" geliefert wird?

Grüße

Edit: Also mein Problem ist, dass ich ${href.chrome('/hw/file')} ja nicht einfach so verwenden kann. Also ich suche quasi etwas dass genau das Gleiche macht, dass ich einfach so im Python Code verwenden kann.
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

So wie ich das jetzt im Kopf habe gibt es den Chrome Ordner eigentlich nicht.
Href.Chrome ist glaub ich eher vielmehr eine Komponente, welche dir die Auflösung
des Hrefs Ordners übernimmt.

Wenn du in python das File wie /hw/file ansprichst, müsste eigentlich funktionieren.
Außerhalb des hrefs ordners wirst du allerdings nicht zugreifen können, da die
Komponenten Architekture dir sowas verbietet, da du sonst andere Komponenten
beeinflussen könntest.

Ich schaue morgen in der Arbeit mal nach ob ich den damaligen Source code noch
habe. Ich habe zwar dann das os modul wieder entfernt, glaube mich aber zu
erinneren, etwas vergleichbares gemacht zu haben.

Grüße
mic
User
Beiträge: 17
Registriert: Dienstag 27. Juli 2010, 14:16

Wunderbar danke nochmals für deine Mühe.
rads
User
Beiträge: 153
Registriert: Freitag 26. März 2010, 15:51

So hab glaub ich gefunden, was du meinst.

Code: Alles auswählen

#===========================================================================
# Read the xyz.html into memory 
#===========================================================================
    def _read_budgeting_fieldset_file(self,stream):
        eggFolderStructur = "/htdocs/html/xyz.html"
        fileDestination =  os.path.dirname(__file__)+ eggFolderStructur
        sourceBuffer = ""
        with open(fileDestination, "r") as infile:
            sourceBuffer = infile.readlines()
            infile.close()
            
        if (len(sourceBuffer) > 0):
            stream = self.__inject_Budgeting_Fieldset(sourceBuffer,stream)
        return stream
Funktion: Einlesen einer html Datei (bzw. eines HTML Fragments, welches in xyz.html gespeichert ist) und
anschließend im aktuellen stream einbauen.

Hilft dir das? Ansonsten musst du mir glaub ich doch noch mal das Problem erklären.

Ich wünsch schonmal ein schönes Wochenende.

Grüße

Edit: ist kein perfekter Code, ist schon bisl älter und war damals in trac und python noch ein rechtes frischling.
An sich könntest du das html direkt zu einem Fragment() casten und mit einem schwupps in den html stream packen.
Antworten