Upload
roskakori
View
932
Download
1
Embed Size (px)
Citation preview
Python-Builds mit antThomas Aglassinger
Agenda
● Was ist ant?● Grundkonzepte und allgemeine Verwendung.● Konkrete Beispiele für Python.● Ausgewählte Features von ant.
Was ist ant?
● Ant ist ein Build-Tool.● Ursprung in der Java-Welt.● Bewährt seit 2000.● Einfache Einbindung in Jenkins.
● Auch für Python-Projekte verwendbar als Ergänzung zu distutils / setup.py.
● Sehr gutes Handbuch mit vielen Beispielen.
Vergleich mit anderen Build-Tools
● Oft kompakter als distutils / setup.py. → Standard-Aufgaben und leistungsfähige Dateimuster statt komplexe shutils-Aufrufe.
● Weiter verbreitet als Scons.http://www.scons.org/
● Robuster als Shell-Scripts → Abbruch bei Fehlern.● Deterministischeres Verhalten als Make.
http://en.wikipedia.org/wiki/Make_(software)● Einfacher zu verwenden als Maven.
http://maven.apache.org/
Grundlagen zu ant
● Build.xml beschreibt Projekt.
● Projekt besteht aus Zielen („targets“).
● Ziele führen Aufgaben („tasks“) aus und erstellen Dateien.
● Ziele können von anderen Zielen abhängig sein.
● Aufgaben sind i.d.R. auf mehrere Dateien anwendbar – ausgewählt mit leistungsfähigen Dateimustern.
● Eigenschaften („properties“) sind verwendbar als Variablen oder Konstante. Allerdings kaum Funktionen für String-Manipulation oder mathematische Berechnungen.
● Einfache Makros zum parameterisierten Aufruf von mehreren Aufgaben.
Beispiel für build.xml
<project name="hello" default="build" basedir=".">
<description>Say hello.</description>
<property name="greeting" value="Hello" />
<property environment="env" />
<target name="build" depends="hello">
<!-- Do nothing. -->
</target>
<target name="hello">
<echo message="${greeting} ${env.USER}! How are you?" />
</target>
</project>
Setzt Eigenschaft „greeting“ auf „Hello“
Definiert Ziel „build“ mitAbhängigkeit zu Ziel „hello“
Definiert Ziel „hello“ zurAusgabe einer Begrüßung.
Setzt Präfix für Zugriff auf Umgebungsvariablen.
Aufruf und Ausgabe
$ ant
Buildfile: /Users/someone/hello/build.xml
hello:
[echo] Hello someone! How are you?
build:
BUILD SUCCESSFUL
Total time: 0 seconds
Bearbeitung vonZiel „hello“
Bearbeitung vonZiel „build“
Beispiel-Ziele
● PEP8 Style-Prüfung.● Anzahl der Quellcode-Zeilen.● Tests inklusive Testabdeckung.● Aufrufe von setup.py.
Quelle für vollständiges build.xml: http://sourceforge.net/apps/trac/cutplace/browser/trunk/build.xml
PEP8 Style-Prüfung
<target name="pep8" description="build pep8 violations report">
<echo message="build pep8 violations report" />
<exec executable="pep8">
<arg value="--repeat" />
<arg value="--ignore" />
<arg value="E501" />
<arg value="cutplace" />
<redirector output="pep8.txt" />
</exec>
</target>
Entspricht:
pep8 –-repeat –-ignore E501 cutplace >pep8.txt
Zeilen dürfen mehrals 80 Zeichen haben
Lenkt Ausgabe umin Datei „pep8.txt“.
Anzahl der Quellcode-Zeilen
<target name="sloccount" description="build sloccount report">
<echo message="build sloccount report" />
<exec executable="sloccount" failonerror="true">
<arg value="--details" />
<arg value="--wide" />
<arg value="cutplace" />
<redirector output="sloccount.sc">
<outputfilterchain>
<linecontains negate="true">
<contains value=".svn" />
</linecontains>
</outputfilterchain>
</redirector>
</exec>
</target>
Download über Package Manager oderhttp://www.dwheeler.com/sloccount/
Entfernt Zeilen mit „.svn“,um interne Kopie vonSubversion nicht mit
zu zählen.
Tests inklusive Testabdeckung (1/2)
● Unter Verwendung von nose und coverage.http://pypi.python.org/pypi/nose/http://pypi.python.org/pypi/coverage/
● Ausgabe von nose im Format von JUnit.● Ausgabe von coverage im Format von
Cobertura.
Tests inklusive Testabdeckung (2/2)
<target name="test" depends="testdata" description="run test suite">
<exec executable="nosetests" failonerror="false">
<arg value="--with-coverage" />
<arg value="--with-doctest" />
<arg value="--with-xunit" />
<arg value="--cover-erase" />
<arg value="--exclude" />
<arg value="(.*setup.*)|(.*test_performance.*)" />
</exec>
<exec executable="coverage" failonerror="true">
<arg value="xml" />
</exec>
</target>Keine Testabdeckung für
setup.py („Test“ im Rahmen des builds) und des
Performance-Test (erfolgtmit eigenem Ziel).
Nach fehlgeschlagenen Testsden Build fortsetzen und
Jenkins-Berichte erzeugen.
Performance-Test
<target name="performance" description="run performance test" ...>
<exec executable="nosetests" failonerror="false">
<arg value="--with-xunit" />
<arg value="--xunit-file" />
<arg file="nosetests_performance.xml" />
<arg file="cutplace/test_performance.py" />
</exec>
</target>
Aufruf von setup.py (1/2)
<macrodef name="pyst">
<!-- Macro to run a setup.py command. -->
<attribute name="command" />
<sequential>
<exec executable="python" failonerror="true">
<arg value="setup.py" />
<arg value="@{command}" />
</exec>
</sequential>
</macrodef>
Definiert Macro <pyst>
Definiert Parameter „command“
Aufruf vonpython setup.py
Übergabe von Parameter„command“ mit @{...}
statt ${...}.
Aufruf von setup.py (2/2)
<target name="bdist_egg" depends="docs" description="build binary distribution">
<pyst command="bdist_egg" />
</target>
<target name="develop" depends="bdist_egg" description="install current development version">
<pyst command="develop" />
</target>
Aufruf:
$ ant bdist_egg
$ sudo ant develop
Entspricht:python setup.py bdist_egg
Entspricht:python setup.py develop
Nützliche Ant-Aufgaben
● <copy>, <delete>, <move> - Dateioperationen.● <mkdir> - Ordner anlegen (auch verschachtelt).● <get> - Download einer URL.● <replace> - Suchen und Ersetzen von Texten.● <FixCRLF> - Zeilenenden vereinheitlichen.● <scp> - Secure remote copy.● <zip>, <unzip> - Dateien und Ordner komprimieren.● <XmlValidate> - XML mit DTD prüfen.● <xslt> - XSL Transformationen.
Plugins, Muster, Filter
<taskdef classname="org.acm.seguin.ant.Pretty" classpath="lib/pretty.jar;lib/JavaStyle.jar" name="pretty"/>
<target depends="init" description="reformat java source code" name="reformat-java">
<pretty settingsDir="${settings.dir}">
<fileset dir="${source.dir}">
<include name="**/*.java"/>
<not><contains text="/*@"/></not>
</fileset>
</pretty>
</target>
„**“ = alle Ordner undenthaltene Unterordner
Aufruf derimportierten
Aufgabe
Import einer externen Aufgabe
Dateien, auf dieAufgabe an zu
wenden ist.
Zusammenfassung
● Bewährtes Werkzeug aus der Java-Welt.● Vergleichsweise einfach und deterministisch.● Viele fertige Aufgaben (Tasks).● Einfache Einbindung von Python-Projekten in
Jenkins.