recherche d'objets
This commit is contained in:
parent
38fdb21f91
commit
c8e13163d3
|
@ -13,6 +13,8 @@ SYSTEM_CONFDIR = '/var/local/deploy'
|
||||||
# Diverses fonctions
|
# Diverses fonctions
|
||||||
|
|
||||||
def isseq(t):
|
def isseq(t):
|
||||||
|
"""Tester si t est une séquence
|
||||||
|
"""
|
||||||
return isinstance(t, list) or isinstance(t, tuple) or isinstance(t, set)
|
return isinstance(t, list) or isinstance(t, tuple) or isinstance(t, set)
|
||||||
|
|
||||||
def flatten(src, unique=True, clean=True, sep=','):
|
def flatten(src, unique=True, clean=True, sep=','):
|
||||||
|
@ -23,7 +25,6 @@ def flatten(src, unique=True, clean=True, sep=','):
|
||||||
Si clean==True, supprimer les valeurs vides et les espaces périphériques
|
Si clean==True, supprimer les valeurs vides et les espaces périphériques
|
||||||
|
|
||||||
e.g flatten(['a , b', 'c,']) --> ['a', 'b', 'c']
|
e.g flatten(['a , b', 'c,']) --> ['a', 'b', 'c']
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not isseq(src): src = [src]
|
if not isseq(src): src = [src]
|
||||||
dest = []
|
dest = []
|
||||||
|
@ -37,6 +38,31 @@ def flatten(src, unique=True, clean=True, sep=','):
|
||||||
dest.extend(items)
|
dest.extend(items)
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
|
def qshell(values):
|
||||||
|
if isseq(values): return map(qshell, values)
|
||||||
|
elif not values: return ''
|
||||||
|
else: return "'%s'" % values.replace("'", "'\\''")
|
||||||
|
|
||||||
|
def strip_domain(a):
|
||||||
|
if a.find('.') == -1: return a
|
||||||
|
else: return a[:a.find('.')]
|
||||||
|
|
||||||
|
def match_host(a, b):
|
||||||
|
"""Les hôtes sont matchés de façon particulière:
|
||||||
|
NAME matche NAME et NAME.DOMAIN
|
||||||
|
NAME. matche NAME
|
||||||
|
NAME.DOMAIN matche NAME.DOMAIN
|
||||||
|
"""
|
||||||
|
a = a.lower()
|
||||||
|
b = b.lower()
|
||||||
|
if a == b: return True
|
||||||
|
if a.find('.') == -1: # NAME
|
||||||
|
return a == strip_domain(b)
|
||||||
|
elif a.endswith('.'): # NAME.
|
||||||
|
return a[:-1] == b
|
||||||
|
else: # NAME.DOMAIN
|
||||||
|
return a == b
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Base de données
|
# Base de données
|
||||||
|
|
||||||
|
@ -47,6 +73,10 @@ class GenericObject(object):
|
||||||
values) et des attributs (propriété attrs)
|
values) et des attributs (propriété attrs)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
OTYPE = 'object'
|
||||||
|
VALUESNAME = 'values'
|
||||||
|
ATTRPREFIX = 'object_'
|
||||||
|
|
||||||
_id = None
|
_id = None
|
||||||
_values = None
|
_values = None
|
||||||
_attrs = None
|
_attrs = None
|
||||||
|
@ -59,7 +89,12 @@ class GenericObject(object):
|
||||||
def get_id(self): return self._id
|
def get_id(self): return self._id
|
||||||
id = property(get_id)
|
id = property(get_id)
|
||||||
|
|
||||||
def get_values(self): return self._values
|
def is_defaults(self):
|
||||||
|
"""Cet objet contient-il les attributs par défaut pour le type?
|
||||||
|
"""
|
||||||
|
return self._id is None
|
||||||
|
|
||||||
|
def get_values(self): return tuple(self._values)
|
||||||
values = property(get_values)
|
values = property(get_values)
|
||||||
def add_value(self, value):
|
def add_value(self, value):
|
||||||
self._values.add(value)
|
self._values.add(value)
|
||||||
|
@ -110,6 +145,46 @@ class GenericObject(object):
|
||||||
for value in values:
|
for value in values:
|
||||||
self.modify_attr(name, value, method)
|
self.modify_attr(name, value, method)
|
||||||
|
|
||||||
|
def invalid_match(self, match):
|
||||||
|
return ValueError("%s: invalid match type")
|
||||||
|
def match_values(self, values, match='any', reverse=False):
|
||||||
|
"""Tester si cet objet a l'une des valeurs spécifiées (avec match=='any' qui est
|
||||||
|
la valeur par défaut)
|
||||||
|
"""
|
||||||
|
if not isseq(values): values = [values]
|
||||||
|
if reverse: Yes, No = False, True
|
||||||
|
else: Yes, No = True, False
|
||||||
|
if match == 'any':
|
||||||
|
for value in values:
|
||||||
|
if value in self._values: return Yes
|
||||||
|
return No
|
||||||
|
elif match == 'all':
|
||||||
|
for value in values:
|
||||||
|
if value not in self._values: return No
|
||||||
|
return Yes
|
||||||
|
else:
|
||||||
|
raise self.invalid_match(match)
|
||||||
|
def match_attrs(self, attrs, match='any', reverse=False):
|
||||||
|
"""Tester si cet objet a un des attributs correspondant aux valeurs spécifiées
|
||||||
|
(avec match=='any' qui est la valeur par défaut)
|
||||||
|
"""
|
||||||
|
if reverse: Yes, No = False, True
|
||||||
|
else: Yes, No = True, False
|
||||||
|
if match == 'any':
|
||||||
|
for name, value in attrs.items():
|
||||||
|
values = self._attrs.get(name, None)
|
||||||
|
if values is None: continue
|
||||||
|
if value in values: return Yes
|
||||||
|
return No
|
||||||
|
elif match == 'all':
|
||||||
|
for name, value in attrs.items():
|
||||||
|
values = self._attrs.get(name, None)
|
||||||
|
if values is None: return No
|
||||||
|
if value not in values: return No
|
||||||
|
return Yes
|
||||||
|
else:
|
||||||
|
raise self.invalid_match(match)
|
||||||
|
|
||||||
def _dump_id(self, indent):
|
def _dump_id(self, indent):
|
||||||
print "%s%s" % (indent, self.id)
|
print "%s%s" % (indent, self.id)
|
||||||
def _dump_values(self, indent, name):
|
def _dump_values(self, indent, name):
|
||||||
|
@ -126,13 +201,17 @@ class GenericObject(object):
|
||||||
"""Afficher l'identifiant, les valeurs et les attributs de cet objet
|
"""Afficher l'identifiant, les valeurs et les attributs de cet objet
|
||||||
"""
|
"""
|
||||||
self._dump_id(indent)
|
self._dump_id(indent)
|
||||||
self._dump_values(indent, 'values')
|
self._dump_values(indent, self.VALUESNAME)
|
||||||
self._dump_attrs(indent)
|
self._dump_attrs(indent)
|
||||||
|
|
||||||
class HostObject(GenericObject):
|
class HostObject(GenericObject):
|
||||||
"""Un hôte
|
"""Un hôte
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
OTYPE = 'host'
|
||||||
|
VALUESNAME = 'hosts'
|
||||||
|
ATTRPREFIX = 'host_'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def genid(host):
|
def genid(host):
|
||||||
"""Générer un identifiant à partir du nom d'hôte
|
"""Générer un identifiant à partir du nom d'hôte
|
||||||
|
@ -151,15 +230,31 @@ class HostObject(GenericObject):
|
||||||
ib = re.sub(r'^(.*?)\d+$', r'\1', id)
|
ib = re.sub(r'^(.*?)\d+$', r'\1', id)
|
||||||
return ib
|
return ib
|
||||||
|
|
||||||
def dump(self, indent=''):
|
def match_values(self, values, match='any', reverse=False):
|
||||||
self._dump_id(indent)
|
if not isseq(values): values = [values]
|
||||||
self._dump_values(indent, 'hosts')
|
if reverse: Yes, No = False, True
|
||||||
self._dump_attrs(indent)
|
else: Yes, No = True, False
|
||||||
|
if match == 'any':
|
||||||
|
for value in values:
|
||||||
|
for host in self._values:
|
||||||
|
if match_host(value, host): return Yes
|
||||||
|
return No
|
||||||
|
elif match == 'all':
|
||||||
|
for value in values:
|
||||||
|
for host in self._values:
|
||||||
|
if not match_host(value, host): return No
|
||||||
|
return Yes
|
||||||
|
else:
|
||||||
|
raise self.invalid_match(match)
|
||||||
|
|
||||||
class ModuleObject(GenericObject):
|
class ModuleObject(GenericObject):
|
||||||
"""Un module, uinst-allable
|
"""Un module, uinst-allable
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
OTYPE = 'module'
|
||||||
|
VALUESNAME = 'modules'
|
||||||
|
ATTRPREFIX = 'module_'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def genid(module):
|
def genid(module):
|
||||||
"""Générér un identifiant à partir du nom du module
|
"""Générér un identifiant à partir du nom du module
|
||||||
|
@ -168,15 +263,14 @@ class ModuleObject(GenericObject):
|
||||||
module = re.sub(r'[^a-zA-Z0-9]', '_', module)
|
module = re.sub(r'[^a-zA-Z0-9]', '_', module)
|
||||||
return module
|
return module
|
||||||
|
|
||||||
def dump(self, indent=''):
|
|
||||||
self._dump_id(indent)
|
|
||||||
self._dump_values(indent, 'modules')
|
|
||||||
self._dump_attrs(indent)
|
|
||||||
|
|
||||||
class WobundleObject(GenericObject):
|
class WobundleObject(GenericObject):
|
||||||
"""Un bundle Webobjects, woinst-allable
|
"""Un bundle Webobjects, woinst-allable
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
OTYPE = 'wobundle'
|
||||||
|
VALUESNAME = 'wobundles'
|
||||||
|
ATTRPREFIX = 'wobundle_'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def genid(wobundle):
|
def genid(wobundle):
|
||||||
"""Générér un identifiant à partir du nom du bundle
|
"""Générér un identifiant à partir du nom du bundle
|
||||||
|
@ -186,15 +280,14 @@ class WobundleObject(GenericObject):
|
||||||
wobundle = re.sub(r'[^a-zA-Z0-9]', '_', wobundle)
|
wobundle = re.sub(r'[^a-zA-Z0-9]', '_', wobundle)
|
||||||
return wobundle
|
return wobundle
|
||||||
|
|
||||||
def dump(self, indent=''):
|
|
||||||
self._dump_id(indent)
|
|
||||||
self._dump_values(indent, 'wobundles')
|
|
||||||
self._dump_attrs(indent)
|
|
||||||
|
|
||||||
class WebappObject(GenericObject):
|
class WebappObject(GenericObject):
|
||||||
"""Une webapp, toinst-allable
|
"""Une webapp, toinst-allable
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
OTYPE = 'webapp'
|
||||||
|
VALUESNAME = 'webapps'
|
||||||
|
ATTRPREFIX = 'webapp_'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def genid(webapp):
|
def genid(webapp):
|
||||||
"""Générér un identifiant à partir du nom de la webapp
|
"""Générér un identifiant à partir du nom de la webapp
|
||||||
|
@ -203,11 +296,6 @@ class WebappObject(GenericObject):
|
||||||
webapp = re.sub(r'[^a-zA-Z0-9]', '_', webapp)
|
webapp = re.sub(r'[^a-zA-Z0-9]', '_', webapp)
|
||||||
return webapp
|
return webapp
|
||||||
|
|
||||||
def dump(self, indent=''):
|
|
||||||
self._dump_id(indent)
|
|
||||||
self._dump_values(indent, 'webapps')
|
|
||||||
self._dump_attrs(indent)
|
|
||||||
|
|
||||||
class GenericLink(object):
|
class GenericLink(object):
|
||||||
"""Un lien générique
|
"""Un lien générique
|
||||||
|
|
||||||
|
@ -552,13 +640,23 @@ class Database(object):
|
||||||
"""
|
"""
|
||||||
return self._objects_ids_otype.keys()
|
return self._objects_ids_otype.keys()
|
||||||
known_otypes = property(get_known_otypes)
|
known_otypes = property(get_known_otypes)
|
||||||
def get_objects(self, otype):
|
def get_objects(self, otype, value=UNDEF, attrs=UNDEF):
|
||||||
"""Obtenir tous les objets définis du type spécifié ou None si le type d'objets
|
"""Obtenir tous les objets définis du type spécifié ou None si le type d'objets
|
||||||
est invalide.
|
est invalide. Si value ou attrs sont définis, filtrer sur ces valeurs.
|
||||||
"""
|
"""
|
||||||
|
if otype is None:
|
||||||
|
objects = []
|
||||||
|
for objects_ids in self._objects_ids_otype.values():
|
||||||
|
objects.extend(objects_ids.values())
|
||||||
|
else:
|
||||||
objects = self._objects_ids_otype.get(otype, None)
|
objects = self._objects_ids_otype.get(otype, None)
|
||||||
if objects is None: return None
|
if objects is None: return None
|
||||||
return [objects[id] for id in objects if id is not None]
|
objects = [objects[id] for id in objects if id is not None]
|
||||||
|
return [
|
||||||
|
object for object in objects if
|
||||||
|
(value is UNDEF or object.match_values(value)) and
|
||||||
|
(attrs is UNDEF or object.match_attrs(attrs))
|
||||||
|
]
|
||||||
def has_object(self, otype, id):
|
def has_object(self, otype, id):
|
||||||
"""Vérifier si l'objet avec l'identifiant spécifié est défini
|
"""Vérifier si l'objet avec l'identifiant spécifié est défini
|
||||||
"""
|
"""
|
||||||
|
@ -1390,6 +1488,69 @@ class Parser(object):
|
||||||
################################################################################
|
################################################################################
|
||||||
# Programme principal
|
# Programme principal
|
||||||
|
|
||||||
|
VALID_QUERY_TYPES = ('object', 'source', 'dest', 'link')
|
||||||
|
def __fix_query_type(query_type):
|
||||||
|
if query_type is None: return None
|
||||||
|
query_type = query_type.lower()
|
||||||
|
if query_type == 'o': query_type = 'object'
|
||||||
|
elif query_type == 's': query_type = 'source'
|
||||||
|
elif query_type == 'd': query_type = 'dest'
|
||||||
|
elif query_type == 'l': query_type = 'link'
|
||||||
|
if query_type not in VALID_QUERY_TYPES:
|
||||||
|
raise ValuerError("%s: invalid query type")
|
||||||
|
return query_type
|
||||||
|
|
||||||
|
def __resolve_format(o, query_type):
|
||||||
|
format = o.format or 'shell'
|
||||||
|
ovars, lvars = o.object_vars, o.link_vars
|
||||||
|
if not ovars and not lvars:
|
||||||
|
if query_type == 'object':
|
||||||
|
ovars = True
|
||||||
|
lvars = False
|
||||||
|
elif query_type in ('source', 'dest'):
|
||||||
|
ovars = True
|
||||||
|
lvars = True
|
||||||
|
elif query_type == 'link':
|
||||||
|
ovars = False
|
||||||
|
lvars = True
|
||||||
|
ofunc, lfunc = o.object_func, o.link_func
|
||||||
|
ivars = flatten(o.vars) or None
|
||||||
|
return format, ovars, lvars, ofunc, lfunc, ivars
|
||||||
|
|
||||||
|
def print_var(name, values, format, ivars, is_values=False):
|
||||||
|
if ivars is not None and name not in ivars: return
|
||||||
|
if not isseq(values): values = [values]
|
||||||
|
if format == 'shell':
|
||||||
|
params = (name, " ".join(qshell(values)))
|
||||||
|
if len(values) <= 1: print "%s=%s" % params
|
||||||
|
else: print "%s=(%s)" % params
|
||||||
|
return
|
||||||
|
if not is_values: return
|
||||||
|
if format == 'lines':
|
||||||
|
for value in values:
|
||||||
|
print value
|
||||||
|
elif format == 'spaces':
|
||||||
|
print " ".join(values)
|
||||||
|
elif format == 'path':
|
||||||
|
print ":".join(values)
|
||||||
|
elif format == 'comma':
|
||||||
|
print ",".join(values)
|
||||||
|
else:
|
||||||
|
raise ValueError("%s: invalid format" % format)
|
||||||
|
|
||||||
|
def print_objects(objects, query_type, o):
|
||||||
|
if objects is None: return
|
||||||
|
format, ovars, lvars, ofunc, lfunc, ivars = __resolve_format(o, query_type)
|
||||||
|
if not ovars: return
|
||||||
|
for o in objects:
|
||||||
|
if o.is_defaults(): continue
|
||||||
|
print_var('otype', o.OTYPE, format, ivars)
|
||||||
|
print_var(o.VALUESNAME, o.values, format, ivars, True)
|
||||||
|
for name, values in o.attrs.items():
|
||||||
|
print_var('%s%s' % (o.ATTRPREFIX, name), values, format, ivars)
|
||||||
|
if ofunc and format == 'shell':
|
||||||
|
print ofunc
|
||||||
|
|
||||||
def run_qdd(o):
|
def run_qdd(o):
|
||||||
# fichier de configuration
|
# fichier de configuration
|
||||||
confname = o.confname or 'deploy'
|
confname = o.confname or 'deploy'
|
||||||
|
@ -1409,7 +1570,7 @@ def run_qdd(o):
|
||||||
|
|
||||||
if o.action == 'nop':
|
if o.action == 'nop':
|
||||||
pass
|
pass
|
||||||
elif o.action == 'dump': #XXX
|
elif o.action == 'dump':
|
||||||
predicates = lexer.get_predicates()
|
predicates = lexer.get_predicates()
|
||||||
parser = Parser(db).parse(predicates)
|
parser = Parser(db).parse(predicates)
|
||||||
print "=== predicates"
|
print "=== predicates"
|
||||||
|
@ -1434,6 +1595,22 @@ def run_qdd(o):
|
||||||
|
|
||||||
elif o.action == 'query':
|
elif o.action == 'query':
|
||||||
parser = Parser(db).parse(lexer.get_predicates())
|
parser = Parser(db).parse(lexer.get_predicates())
|
||||||
|
query_type, object_type, link_type = __fix_query_type(o.query_type), o.object_type, o.link_type
|
||||||
|
if query_type is None and object_type is None and link_type is None:
|
||||||
|
query_type = 'dest'
|
||||||
|
object_type = 'host'
|
||||||
|
if o.profile is not None: profile = o.profile or None
|
||||||
|
else: profile = UNDEF
|
||||||
|
args = o.args or UNDEF
|
||||||
|
if query_type == 'object':
|
||||||
|
objects = db.get_objects(object_type, args)
|
||||||
|
print_objects(objects, query_type, o)
|
||||||
|
elif query_type == 'source':
|
||||||
|
pass
|
||||||
|
elif query_type == 'dest':
|
||||||
|
pass
|
||||||
|
elif query_type == 'link':
|
||||||
|
pass
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from argparse import ArgumentParser, HelpFormatter
|
from argparse import ArgumentParser, HelpFormatter
|
||||||
|
@ -1482,29 +1659,42 @@ if __name__ == '__main__':
|
||||||
AP.add_argument('-c', '--config', dest='confname',
|
AP.add_argument('-c', '--config', dest='confname',
|
||||||
help=u"Spécifier le nom de la configuration à utiliser. Par défaut, utiliser le nom générique deploy.")
|
help=u"Spécifier le nom de la configuration à utiliser. Par défaut, utiliser le nom générique deploy.")
|
||||||
AP.add_argument('-q', '--query-type', dest='query_type',
|
AP.add_argument('-q', '--query-type', dest='query_type',
|
||||||
help=u"")
|
help=u"Spécifier le type d'information à afficher:\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"* object pour des informations sur les objets,\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"* source pour des informations sur les objets sources d'un lien,\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"* dest pour des informations sur les objets destinations d'un lien,\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"* link pour des informations sur un lien.\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"La valeur par défaut est '-q dest -j host'")
|
||||||
AP.add_argument('-j', '--object-type', dest='object_type',
|
AP.add_argument('-j', '--object-type', dest='object_type',
|
||||||
help=u"")
|
help=u"Spécifier le type d'objet à chercher pour -q object|source|dest")
|
||||||
AP.add_argument('-t', '--link-type', dest='link_type',
|
AP.add_argument('-t', '--link-type', dest='link_type',
|
||||||
help=u"")
|
help=u"Spécifier le type de lien à chercher pour -q source|dest|link")
|
||||||
AP.add_argument('-p', '--profile', dest='profile',
|
AP.add_argument('-p', '--profile', dest='profile',
|
||||||
help=u"Spécifier le profil de déploiement")
|
help=u"Spécifier le profil de déploiement pour -q source|dest|link. Utiliser une valeur vide pour ne sélectionner que les liens sans profils. Ne pas spécifier l'option pour afficher tous les profils définis.")
|
||||||
AP.add_argument('-F', '--format', dest='format',
|
AP.add_argument('-F', '--format', dest='format',
|
||||||
help=u"Spécifier le format pour la sortie. La valeur par défaut est shell.")
|
help=u"Spécifier le format pour la sortie. La valeur par défaut est shell.\n"
|
||||||
AP.add_argument('-v', '--include-vars', dest='vars', metavar='VARS...',
|
+ u">>>\n"
|
||||||
|
+ u"* shell affiche les définitions de variables\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"* lines affiches les valeurs à raison d'une par lignes. les attributs ne sont pas affichés.\n"
|
||||||
|
+ u">>>\n"
|
||||||
|
+ u"* spaces, path et comma affichent les valeurs séparées respectivement par un espace ' ', deux point ':' et une virgule ','. les attributs ne sont pas affichés.\n")
|
||||||
|
AP.add_argument('-v', '--include-vars', action='append', dest='vars', metavar='VARS...',
|
||||||
help=u"Spécifier les variables qui doivent être affichées. Par défaut, toutes les variables sont affichées.")
|
help=u"Spécifier les variables qui doivent être affichées. Par défaut, toutes les variables sont affichées.")
|
||||||
AP.add_argument('-o', '--object-vars', action='store_true', dest='object_vars',
|
AP.add_argument('-o', '--object-vars', action='store_true', dest='object_vars',
|
||||||
help=u"Afficher les variables associées aux objets.")
|
help=u"Afficher uniquement les variables associées aux objets.")
|
||||||
AP.add_argument('-d', '--dest-vars', action='store_true', dest='dest_vars',
|
|
||||||
help=u"Afficher les variables associées aux hôtes destination.")
|
|
||||||
AP.add_argument('-l', '--link-vars', action='store_true', dest='link_vars',
|
AP.add_argument('-l', '--link-vars', action='store_true', dest='link_vars',
|
||||||
help=u"Afficher les variables associées aux liens.")
|
help=u"Afficher uniquement les variables associées aux liens.")
|
||||||
AP.add_argument('--of', '--object-func', dest='object_func', metavar='FUNC',
|
AP.add_argument('--of', '--object-func', dest='object_func', metavar='FUNC',
|
||||||
help=u"Avec le format shell, spécifier le nom d'une fonction à afficher après les variables associées aux objets.")
|
help=u"Avec le format shell, spécifier le nom d'une fonction à afficher après les variables associées aux objets.")
|
||||||
AP.add_argument('--df', '--dest-func', dest='dest_func', metavar='FUNC',
|
|
||||||
help=u"Avec le format shell, spécifier le nom d'une fonction à afficher après les variables associées aux hôtes destination.")
|
|
||||||
AP.add_argument('--lf', '--link-func', dest='link_func', metavar='FUNC',
|
AP.add_argument('--lf', '--link-func', dest='link_func', metavar='FUNC',
|
||||||
help=u"Avec le format shell, spécifier le nom d'une fonction à afficher après les variables associées aux liens.")
|
help=u"Avec le format shell, spécifier le nom d'une fonction à afficher après les variables associées aux liens.")
|
||||||
|
AP.add_argument('args', nargs=REMAINDER)
|
||||||
o = AP.parse_args()
|
o = AP.parse_args()
|
||||||
|
|
||||||
run_qdd(o)
|
run_qdd(o)
|
||||||
|
|
Loading…
Reference in New Issue