def set_kw_arg(kwargs, argname, argval): # set the type correctly, too. argspec = self.optionSpec(argname) if (argspec is not None): if (argspec.argtypename is not None): typ = butils.resolve_type(argspec.argtypename, self._fmodule) else: typ = unicode kwargs[argname] = typ(argval) else: kwargs[argname] = argval # raw type if we can't figure one out (could be
def setData(self, index, value, role=Qt.EditRole): col = index.column() row = index.row() if (col != 1): return False if (self._fopts is None): return False if (role != Qt.EditRole): return False filteroptions = self._fopts.filterOptions() if (row < 0 or row >= len(filteroptions)): return False arg = filteroptions[row] value = value.toPyObject() if (isinstance(value, QString)): value = unicode(value); # make sure we're dealing with Python strings and not Qt strings logger.debug("Got value: %r", value) # validate type typ = None if (arg.argtypename is not None): typ = butils.resolve_type(arg.argtypename, filters_factory.get_module(self._filtername, False)) if (typ == None): typ = unicode value = typ(value) logger.debug("Got final value: %r ; typ=%r", value, typ) self._kwargs[arg.argname] = value self._update_optionstring() self.dataChanged.emit(index, index) self._emitOptionStringChanged() logger.debug("_kwargs is %r", self._kwargs) return True
def setData(self, index, value, role=Qt.EditRole): col = index.column() row = index.row() if (col != 1): return False if (self._fopts is None): return False if (role != Qt.EditRole): return False if self._fopts: filteroptions = self._fopts.filterOptions() else: filteroptions = [] if (row < 0 or row >= len(filteroptions)): return False arg = filteroptions[row] logger.debug("Got value: %r", value) # validate type typ = None if (arg.argtypename is not None): typ = butils.resolve_type(arg.argtypename, self._finfo.fmodule) if (typ == None): typ = str value = typ(value) logger.debug("Got final value: %r ; typ=%r", value, typ) self._kwargs[arg.argname] = value self._update_optionstring() self.dataChanged.emit(index, index) self._emitOptionStringChanged() logger.debug("_kwargs is %r", self._kwargs) return True
def __init__(self, filtername, fclass=None): self._filtername = filtername self._fmodule = get_module(filtername) if fclass is None: fclass = get_filter_class(filtername) self._fclass = fclass # find out what the arguments to the filter constructor are self.fclass_arg_defs = inspect.getargspec(fclass.__init__) (fargs, varargs, keywords, defaults) = self.fclass_arg_defs # get some doc about the parameters doc = fclass.__init__.__doc__; if (doc is None): doc = '' argdocspos = []; for m in re.finditer(_rxargdoc, doc): argdocspos.append(m); argdoclist = []; begindoc = None; for k in range(len(argdocspos)): m = argdocspos[k] if (begindoc is None): begindoc = doc[:m.start()]; thisend = (argdocspos[k+1].start() if k < len(argdocspos)-1 else len(doc)) # adjust whitespace in docstr docstr = doc[m.end():thisend].strip() # just format whitespace, don't fill. This is for the GUI. we'll fill to a # certain width only when specifying this as the argparse help argument. docstr = textwrap.TextWrapper(width=sys.maxint, replace_whitespace=True, drop_whitespace=True).fill(docstr) argdoclist.append(_ArgDoc(argname=m.group('argname'), argtypename=m.group('argtypename'), doc=docstr)) argdocs = dict([(x.argname, x) for x in argdoclist]) self._use_auto_case = True if (re.search(r'[A-Z]', "".join(fargs))): logger.debug("filter "+self._filtername+": will not automatically adjust option letter case."); self._use_auto_case = False if (defaults is None): defaults = []; def fmtarg(k, fargs, defaults): s = fargs[k]; off = len(fargs)-len(defaults); if (k-off >= 0): s += "="+repr(defaults[k-off]); return s fclasssyntaxdesc = fclass.__name__+("(" + " ".join([xpart for xpart in [ (", ".join([fmtarg(k, fargs, defaults) for k in range(len(fargs)) if fargs[k] != "self"])), ("[...]" if varargs else ""), ("[..=...]" if keywords else ""), ] if xpart]) + ")"); p = FilterArgumentParser(filtername=self._filtername, prog=self._filtername, description=fclass.getHelpDescription(), epilog=_add_epilog, add_help=False, formatter_class=argparse.RawDescriptionHelpFormatter, ); group_filter = p.add_argument_group('Filter Arguments'); # add option for all arguments # memo for later, whether to show info about boolean args in help text. Wrap this # in a class so that we can access this from member functions. class Store: pass ns = Store() ns.has_a_boolean_arg = False ns.seen_types = [] self._filteroptions = [] self._filtervaroptions = [] def make_filter_option(farg): fopt = farg.replace('_', '-'); argdoc = argdocs.get(farg, _ArgDoc(farg,None,None)) if argdoc.doc is not None: argdocdoc = argdoc.doc.replace('%', '%%') argdocdoc = textwrap.TextWrapper(width=80, replace_whitespace=True, drop_whitespace=True).fill( argdocdoc ) else: argdocdoc = None optkwargs = { 'action': 'store', 'dest': farg, 'help': argdocdoc, } if argdoc.argtypename == 'bool': # boolean switch optkwargs['metavar'] = '<BOOLEAN ARG>' if not fopt.startswith('no-'): optkwargs['help'] = '' # only provide help for second option group_filter.add_argument('--'+fopt, nargs='?', default=None, const=True, type=butils.getbool, **optkwargs) if not fopt.startswith('no-'): optkwargs['help'] = argdocdoc # only provide help for second option group_filter.add_argument('--no-'+fopt, nargs='?', default=None, const=False, type=lambda val: not butils.getbool(val), **optkwargs) # remember that we've seen a bool arg ns.has_a_boolean_arg = True else: if argdoc.argtypename: if (argdoc.argtypename not in ns.seen_types): ns.seen_types.append(argdoc.argtypename) optkwargs['metavar'] = '<%s>'%(argdoc.argtypename) else: optkwargs['metavar'] = '<ARG>' group_filter.add_argument('--'+fopt, **optkwargs) return argdoc argdocs_left = [ x.argname for x in argdoclist ]; for n in xrange(len(fargs)): if n == 0: # Skip 'self' argument. Don't use "farg == 'self'" because in # theory the argument could have any name. continue farg = fargs[n] # normalize name argdoc = make_filter_option(farg) if farg in argdocs_left: argdocs_left.remove(farg) self._filteroptions.append(argdoc) # in case user specified more docs than declared arguments, they document additional arguments that # can be given as **kwargs if (not keywords and argdocs_left): raise FilterError("Filter's argument documentation provides additional documentation for " "non-arguments %r. (Did you forget a **kwargs?)" %(argdocs_left), name=filtername) for farg in argdocs_left: argdoc = make_filter_option(farg) self._filtervaroptions.append(argdoc) group_general = p.add_argument_group('Alternative Option Syntax') # a la ghostscript: -sOutputFile=blahblah -sKey=Value group_general.add_argument('-s', action=store_key_val, dest='_s_args', metavar='Key=Value', exception=FilterOptionsParseError, help="-sKey=Value sets parameter values"); group_general.add_argument('-d', action=store_key_bool, const=True, dest='_d_args', metavar='Switch[=<value>]', exception=FilterOptionsParseErrorHintSInstead, help="-dSwitch[=<value>] sets flag `Switch' to given boolean value, by default " "True. Valid boolean values are 1/T[rue]/Y[es]/On and 0/F[alse]/N[o]/Off"); # allow also to give arguments without the keywords. if varargs: group_general.add_argument('_args', nargs='*', metavar='<arg>', help="Additional arguments will be passed as is to the filter--see " "documentation below"); #p.add_argument_group(u"Python filter syntax", # textwrap.fill(fclasssyntaxdesc, width=80, subsequent_indent=' ')); filter_options_syntax_help = textwrap.dedent( u"""\ For passing option values, you may use either the `--key value' syntax, or the (ghostscript-like) `-sKey=Value' syntax. For boolean switches, use -dSwitch to set the given option to True. When using the -s or -d syntax, the option names are camel-cased, i.e. an option like `--add-description arxiv' can be specified as `-sAddDescription=arxiv'. Likewise, `--preserve-ids' can provided as `-dPreserveIds' or `-dPreserveIds=yes'.""") if ns.has_a_boolean_arg: filter_options_syntax_help += textwrap.dedent(u""" The argument to options which accept a <BOOLEAN ARG> may be omitted. <BOOL ARG> may be one of ("t", "true", "y", "yes", "1", "on") to activate the switch, or ("f", "false", "n", "no", "0", "off") to disable it (case insensitive). If you specify a false argument to the variant '--no-<SWITCH>' of the option, that argument negates the negative effect of the switch.""") for (typname, typ) in ((y, x) for (y, x) in ((y, butils.resolve_type(y, self._fmodule)) for y in ns.seen_types) if hasattr(x, '__doc__')): if not typ.__doc__: # e.g., is None continue docstr = typ.__doc__.strip() if not len(docstr): continue docstr = textwrap.TextWrapper(width=80, replace_whitespace=True, drop_whitespace=True, subsequent_indent=' ').fill( "TYPE %s: "%(typname) + docstr ) filter_options_syntax_help += "\n\n" + docstr if varargs: filter_options_syntax_help += textwrap.dedent(u""" This filter accepts additional positional arguments. See the documentation below for more information.""") p.add_argument_group(u'Note on Filter Options Syntax', filter_options_syntax_help) p.add_argument_group(u'FILTER DESCRIPTION', "\n" + fclass.getHelpText()) self._parser = p
def data(self, index, role=Qt.DisplayRole): if (self._fopts is None): return None filteroptions = self._fopts.filterOptions() col = index.column() row = index.row() if (row < 0 or row >= len(filteroptions)): return None # the argument specification of the current row (_ArgDoc namedtuple instance) arg = filteroptions[row] if (col == 0): # argument name if (role == Qt.DisplayRole): return str(self._fopts.getSOptNameFromArg(filteroptions[row].argname)) # tool-tip documentation if (role == Qt.ToolTipRole): return textwrap.fill(arg.doc, width=80) return None # the value of the argument of the current row. val = self._kwargs.get(arg.argname) if (col == 1): # argument value if (role == overlistbuttonwidget.ROLE_OVERBUTTON): if (val is not None): return overlistbuttonwidget.OVERBUTTON_REMOVE return overlistbuttonwidget.OVERBUTTON_ADD if (role == overlistbuttonwidget.ROLE_ARGNAME): return str(arg.argname) if (role == Qt.DisplayRole): if (val is None): return None return str(val) # request editing value of argument if (role == Qt.EditRole): if arg.argtypename is not None: typ = butils.resolve_type(arg.argtypename, self._finfo.fmodule) else: typ = str if hasattr(typ, 'type_arg_input'): editval = RegisteredArgInputType(typ, val) elif is_class_and_is_sub_class(typ, str) and val is None: editval = typ('') elif typ in [bool, int, float, str]: try: editval = typ(val) # resort to Qt's editor for these types. except Exception: # in case typ(val) generates an exception because val is invalid ...? editval = typ() else: editval = str(val) # always resort to string so that something can be edited return editval return None return None
def data(self, index, role=Qt.DisplayRole): if (self._fopts is None): return QVariant() filteroptions = self._fopts.filterOptions() col = index.column() row = index.row() if (row < 0 or row >= len(filteroptions)): return QVariant() # the argument specification of the current row (_ArgDoc namedtuple instance) arg = filteroptions[row] if (col == 0): # argument name if (role == Qt.DisplayRole): return QVariant(QString(self._fopts.getSOptNameFromArg(filteroptions[row].argname))) # tool-tip documentation if (role == Qt.ToolTipRole): return QVariant(QString(arg.doc)) return QVariant() # the value of the argument of the current row. val = self._kwargs.get(arg.argname) if (col == 1): # argument value if (role == overlistbuttonwidget.ROLE_OVERBUTTON): if (val is not None): return QVariant(overlistbuttonwidget.OVERBUTTON_REMOVE) return QVariant(overlistbuttonwidget.OVERBUTTON_ADD) if (role == overlistbuttonwidget.ROLE_ARGNAME): return QVariant(QString(arg.argname)) if (role == Qt.DisplayRole): if (val is None): return QVariant() return QVariant(QString(unicode(val))) # request editing value of argument if (role == Qt.EditRole): if (arg.argtypename is not None): fmodule = filters_factory.get_module(self._filtername, False) typ = butils.resolve_type(arg.argtypename, fmodule) else: typ = unicode if (hasattr(typ, 'type_arg_input')): editval = RegisteredArgInputType(typ, val) elif (issubclass(typ, basestring) and val is None): editval = typ('') elif (issubclass(typ, CommaStrList)): editval = unicode(val) else: editval = typ(val) return QVariant(editval) return QVariant() return QVariant()