@jskeletti: Du könntest Dir eine Funktion zum dekodieren der Zeichenketten nach Unicode schreiben, oder zumindest die ``?\123``-Sequenzen das (Byte-)Zeichen mit dem entsprechenden Wert umwandeln. Das ginge mit dem `re`-Modul recht einfach. Bei `re.sub()` kann man als Ersetzung auch eine Funktion angeben die das `Match`-Objekt übergeben bekommt und die Ersetzung zurück geben muss.
Sonstige Anmerkungen zum Quelltext: Der hält sich in so einigem nicht an den
Style Guide for Python Code. Insbesondere mit der Einrücktiefe sollte man nicht experimentieren, damit erschwert man die Zusammenarbeit mit anderen nur unnötig.
Auf Modulebene sollte man nur Konstanten, Funktionen, und Klassen definieren und keinen Programmcode schreiben. Denn dann kann man ein Modul nicht importieren ohne dass der Code abläuft, zum Beispiel um einzelne Funktionen zu manuell oder automatisiert zu testen, oder wieder zu verwenden. Wenn der Code in Funktionen steckt, besteht auch nicht Gefahr, dass man aus versehen (oder absichtlich) auf Datenstrukturen zugreift, die eine Funktion nicht als Argument betreten haben, und man sich so undurchsichtige Abhängigkeiten bastelt. Noch unübersichtlicher wird es wenn man Programmlogik auf Moduleben mit der Definition von Funktionen vermischt, weil man sich den Programmablauf dann zwischen den Funktionsdefinitionen zusammen suchen muss.
Der Kommentar ``Helper Methods`` ist technisch gesehen falsch, weil es Funktionen sind. Bringt der überhaupt einen Mehrwert? Gibt es denn in dem Programm noch andere Funktionen die nicht unter diese Überschrift passen?
Die Kommentare über den beiden gezeigten Funktionen wären als DocStrings besser platziert.
``import``-Anweisungen sollten am Anfang des Moduls stehen und nicht innerhalb von Funktionen, solange man dafür keinen guten Grund hat.
So wie Du mit dem `command` verfährst handelst Du Dir Probleme ein wenn der Pfad zum Beispiel Leerzeichen oder andere „whitespace”-Zeichen enthält.
Die `changed()`-Funktion bekommt ein Argument übergeben, verwendet das dann aber gar nicht.
Die ``while``-Schleife zum entfernen der Leerzeilen am Ende ist ineffizient, weil da in jedem Durchlauf die gesamte Liste minus des letzten Elements kopiert wird. Ein entfernen des letzten Elements mittels `pop()` wäre effizienter. Aber der ganze Code nach dem Filtern ist sowieso unnötig weil Leerzeilen doch schon an dem Test mit der `change()`-Funktion gescheitert und rausgeflogen wären.
`file` ist der Name eines eingebauten Typs, den sollte man nicht an ein anderes Objekt binden. Zumal es sich gar nicht um Dateien sondern Datei*namen* handelt.
Bist Du sicher dass Deine Lösung auch verbotene Zeichen in Verzeichnisnamen findet?
Das Ganze könnte dann ungefähr so aussehen:
Code: Alles auswählen
#!/usr/bin/env python
import os
import re
import sys
from subprocess import PIPE, Popen
SVNLOOK = 'svnlook'
SVN_ESCPAPE_RE = re.compile(r'\?\\(\d{1,3})')
def decode_svn_filename(path):
SVN_ESCPAPE_RE.sub(path, lambda m: chr(int(m.group(1))))
def execute_command(command):
"""Gets a command's output."""
process = Popen(command, stdout=PIPE)
output, _error_output = process.communicate()
return output
def iter_changed_paths(repo_path, transaction):
"""Returns an array of the changed files' names"""
#
# Run svnlook to find the files that were changed.
#
output = execute_command(
[SVNLOOK, 'changed', repo_path, '--transaction', transaction]
)
#
# The output from svnlook looks like the following:
# U folder/file1.cpp
# A folder/file2.cpp
# where U means updated and A means added.
#
return (
line.split(None, 1)[-1]
for line in output.splitlines()
if line.startswith(('A', 'U'))
)
def main():
result = 0
forbidden_chars = set('<>:"/\|?*')
# ...
repo_path = '/'
transaction = 42 # XXX: Just an example, not a real value.
#
# Verify filenames if compatible with windows.
#
filenames = (
decode_svn_filename(os.path.basename(path))
for path in iter_changed_paths(repo_path, transaction)
)
for filename in filenames:
print filename + '\n'
if any((c in forbidden_chars) for c in filename):
sys.stderr.write(
'Filename (%r) not compatible with Windows!\n' % filename
)
result = 1
if result == 1:
sys.stderr.write('Please check the characters in the filename(s)!\n')
sys.exit(result)
if __name__ == '__main__':
main()