meilleure gestion des options, bugfix métadonnées licence

This commit is contained in:
nojhan 2008-03-07 13:08:07 +00:00
commit ab8bf4aad7

View file

@ -7,19 +7,57 @@ import ftplib
import getopt import getopt
from elementtree import ElementTree from elementtree import ElementTree
import unicodedata import unicodedata
import ConfigParser
class Options: class Options:
def __init__(self, argv, usage = "" ): def __init__(self, argv, usage = "", app_name = None ):
# Message à afficher en cas de mauvaise utilisation des options
self.usage = usage
self.options = {} self.options = {}
self.argv = argv self.argv = argv
def parse(self): if app_name:
self.app_name = app_name
else:
# si aucun nom n'est précisé, on l'extrait de l'argv, mais sans l'extension
self.app_name = os.path.splitext( os.path.basename( argv[0] ) )[0]
# Message à afficher en cas de mauvaise utilisation des options
usage += "\nUsage: %s [OPTIONS] arguments" % self.app_name
self.usage = usage
def __configure_file( self, filename ):
# prend les valeurs indiquées dans le fichier de configuration
config = ConfigParser.ConfigParser()
try:
config.readfp( open( filename ) )
except:
return
# Pour chaque option prévue
for o in self.options:
try:
# essaye de la lire dans le fichier de conf
a = config.get('default',o)
# si c'est un flag
if self.options[o]['flag'] == True:
# il faut convertir en booléen
self.options[o]['value'] = bool( eval( a ) )
else:
# sinon c'est un string
self.options[o]['value'] = a
# on ajoute que ce fichier de conf à changer la valeur
self.options[o]['origin'] = filename
except:
pass
def __configure_command( self ):
# construction de la chaine argument pour getopt # construction de la chaine argument pour getopt
gos_short = '' gos_short = ''
gos_long = '' gos_long = ''
@ -44,14 +82,14 @@ class Options:
self.print_usage() self.print_usage()
sys.exit(2) sys.exit(2)
# création des dicionnaires pour les valeurs
self.param = {}
self.is_flag = {}
s2l = {} # associations court:long s2l = {} # associations court:long
for o in self.options: for o in self.options:
short = self.options[o]['short']
# lève une erreur si l'option courte a déjà été déclarée
if short in s2l:
raise "Short option '%s' already declared for the options '%s', please use another letter for the option '%s'." % (short, s2l[short], o )
s2l[ self.options[o]['short'] ] = self.options[o]['long'] s2l[ self.options[o]['short'] ] = self.options[o]['long']
# prend les valeurs indiquées sur la ligne de commande # prend les valeurs indiquées sur la ligne de commande
for o,a in opts: for o,a in opts:
# court => on enlève un tiret # court => on enlève un tiret
@ -68,34 +106,64 @@ class Options:
else: else:
# prend la valeur indiquée # prend la valeur indiquée
self.options[ s2l[os] ]['value'] = a self.options[ s2l[os] ]['value'] = a
self.options[ s2l[os] ]['origin'] = 'command line'
# si c'est une option longue # si c'est une option longue
elif ol in self.options: elif ol in self.options:
if self.options[ol]['flag']: if self.options[ol]['flag']:
self.options[ ol ]['value'] = True self.options[ ol ]['value'] = True
else: else:
self.options[ol]['value'] = a self.options[ol]['value'] = a
self.options[ol]['origin'] = 'command line'
# retourne tout ce qui n'a pas été parsé # retourne tout ce qui n'a pas été parsé
return args return args
def parse(self):
# on essaye d'abord le fichier de conf général
self.__configure_file( '%s.conf' % self.app_name )
# puis on essaye le fichier de conf utilisateur
self.__configure_file( os.path.join( os.path.expanduser('~'), '.%s.conf' % self.app_name ) )
# enfin, la ligne de commande
args = self.__configure_command()
return args
def add( self, short, long, description, default='' ): def add( self, short, long, description, default='' ):
flag = False flag = False
if default==True or default==False: if default==True or default==False:
flag = True flag = True
self.options [ long ] = { 'short':short, 'long':long, 'description':description, 'default':default, 'flag':flag, 'value':default }
# si l'option est déjà présente
if long in self.options:
raise "Long option '%s' already declared, please use another one." % long
else:
self.options [ long ] = {
'short':short, # identifiant court (une lettre)
'long':long, # identifiant long
'description':description, # texte de description
'origin':'hard coded', # source de la valeur
'flag':flag, # indicateur de flag
'value':default } # valeur de l'option
def print_usage(self): def print_usage(self):
print self.usage print self.usage
for o in self.options: for o in self.options:
print "\t-%s, --%s\t%s." % ( self.options[o]['short'], self.options[o]['long'], self.options[o]['description'] ) fs = "\t-%s, --%s\t\t%s"
# si pas un flag, indique qu'il faut un paramètre
if not self.options[o]['flag']:
fs = "\t-%s, --%s\t=VAL\t%s"
print fs % ( self.options[o]['short'], self.options[o]['long'], self.options[o]['description'] )
def print_state(self): def print_state(self):
print "Options settings:" print "Options settings:"
for o in self.options: for o in self.options:
print "\t%s=%s (%s)" % ( self.options[o]['long'], self.options[o]['value'], self.options[o]['default'] ) print "\t%s='%s' (%s)" % ( self.options[o]['long'], self.options[o]['value'], self.options[o]['origin'] )
def get( self, long ): def get( self, long ):
return self.options[long]['value'] return self.options[long]['value']
@ -144,7 +212,7 @@ class Stripit:
im.save(file, "PNG", pnginfo=meta) im.save(file, "PNG", pnginfo=meta)
def export( self, file_we, max_size=None, options='' ): def export( self, file_we, options='', max_size=None ):
"""file name only, without extension""" """file name only, without extension"""
if self.verbose: if self.verbose:
@ -196,6 +264,29 @@ class Stripit:
return unicodedata.normalize('NFKD', res ).encode('ASCII', 'ignore') return unicodedata.normalize('NFKD', res ).encode('ASCII', 'ignore')
def xfind_attribute( self, tree, ns ):
# pour une raison qui m'échappe, ElementTree ne considère pas les attributs comme des sous-éléments de chaque noeud
# cette fonction est donc un hack pour pallier le problème
# les premiers éléments sont considérés comme des noeuds de la requête xpath
q = '//' + '/'.join( ns[0:-1] )
# le dernier est l'attribut
attribute = ns[-1]
# on récupère l'objet élément
el = tree.find( q)
# les attributs sont récupérables dans une liste de tuples (!)
# on convertit donc en dictionnaire, plus logique
# TODO vérifier (quand même) s'il ne peut pas y avoir plusieurs attributs identiques
attr = dict( el.items() )
# ce qui permet de récupérer le contenu directement avec l'identifiant
res = unicode( attr[attribute] )
return unicodedata.normalize('NFKD', res ).encode('ASCII', 'ignore')
def get_svg_metadata( self, file_we ): def get_svg_metadata( self, file_we ):
if self.verbose: if self.verbose:
@ -228,7 +319,9 @@ class Stripit:
metadata = {} metadata = {}
metadata['Author'] = self.xfind( tree, [ CC('Agent'), DC('title') ] ) metadata['Author'] = self.xfind( tree, [ CC('Agent'), DC('title') ] )
metadata['Description'] = self.xfind( tree, [ CC('Work'), DC('description') ]) metadata['Description'] = self.xfind( tree, [ CC('Work'), DC('description') ])
metadata['Copyright'] = self.xfind( tree, [ CC('Work'), CC('license') ] ) # FIXME ne marche pas
metadata['Copyright'] = self.xfind_attribute( tree, [ CC('Work'),CC('license'),RDF('resource') ] )
metadata['Creation Time'] = self.xfind( tree, [ CC('Work'), DC('date') ] ) metadata['Creation Time'] = self.xfind( tree, [ CC('Work'), DC('date') ] )
metadata['Software'] = 'www.inkscape.org / stripit.sourceforge.net' # FIXME pas très élégant metadata['Software'] = 'www.inkscape.org / stripit.sourceforge.net' # FIXME pas très élégant
metadata['Disclaimer'] ='' metadata['Disclaimer'] =''
@ -288,9 +381,9 @@ class Stripit:
if __name__=="__main__": if __name__=="__main__":
usage = """Script d'aide à l'export et au téléchargement pour StripIt. usage = """Aide à l'export et au téléchargement pour StripIt.
\tCe script va exporter un fichier SVG au format PNG, puis télécharger le tout sur un serveur FTP. \tCe script va exporter un ou plusieurs fichiers SVG au format PNG, en préservant les métadonnées ;
Usage: stripit.py [OPTIONS] fichier""" \tpuis télécharger le tout sur un serveur FTP."""
oo = Options( sys.argv, usage ) oo = Options( sys.argv, usage )
@ -304,10 +397,13 @@ Usage: stripit.py [OPTIONS] fichier"""
oo.add( 'v', 'verbose', "Afficher plus d'informations", False ) oo.add( 'v', 'verbose', "Afficher plus d'informations", False )
oo.add( 's', 'supp', 'Options supplémentaires pour inkscape', '' ) oo.add( 's', 'supp', 'Options supplémentaires pour inkscape', '' )
oo.add( 'h', 'help', "Ce message d'aide", False ) oo.add( 'h', 'help', "Ce message d'aide", False )
oo.add( 'm', 'max-size', 'Taille maximale en hauteur ou en largeur, en pixels', '800' ) oo.add( 'z', 'size', "Limiter la taille du PNG", False )
oo.add( 'm', 'max-size', 'Taille maximale en hauteur ou en largeur, en pixels', '800')
args = oo.parse() args = oo.parse()
#oo.print_state()
if oo.get('verbose'):
oo.print_state()
if oo.get('help'): if oo.get('help'):
oo.print_usage() oo.print_usage()
@ -326,7 +422,10 @@ Usage: stripit.py [OPTIONS] fichier"""
si = Stripit( oo.get('verbose') ) si = Stripit( oo.get('verbose') )
if not oo.get('no-export'): if not oo.get('no-export'):
si.export( f, oo.get('max-size'), oo.get('supp') ) if oo.get('size'):
si.export( f, oo.get('supp'), oo.get('max-size') )
else:
si.export( f, options=oo.get('supp') )
md = si.get_svg_metadata( f ) md = si.get_svg_metadata( f )
@ -339,5 +438,5 @@ Usage: stripit.py [OPTIONS] fichier"""
oo.get('user'), oo.get('user'),
oo.get('dir'), oo.get('dir'),
oo.get('pass') oo.get('pass')
) # FIXME options ou .conf ? )