option argument length

Discussion in 'Python' started by Ritesh Raj Sarraf, Dec 4, 2005.

  1. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Hi,

    I'm using optparse module to parse all options and arguments.

    My program uses mostly "option arguments" hence my len(args) value is always
    zero. I need to check if the user has passed the correct number of "option
    arguments". Something like:

    (options,args) = parser.parse_args()

    len(options) != 1 or len(options) > 2:
    print "Incorrect number of arguments passed."

    How do I accomplish it ?

    Regards,

    rrs
    - --
    Ritesh Raj Sarraf
    RESEARCHUT -- http://www.researchut.com
    "Stealing logics from one person is plagiarism, stealing from many is
    research."
    "Necessity is the mother of invention."

    Note: Please CC me. I'm not subscribed to the list
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.2 (GNU/Linux)

    iD8DBQFDk1Nh4Rhi6gTxMLwRApx0AJ9XHlWFU1J0NdN02gtvimogUSgDkACgmkOO
    2pX8ocoC7pot1a8R4u2BWrY=
    =piNo
    -----END PGP SIGNATURE-----
     
    Ritesh Raj Sarraf, Dec 4, 2005
    #1
    1. Advertising

  2. In <>, Ritesh Raj
    Sarraf wrote:

    > My program uses mostly "option arguments" hence my len(args) value is always
    > zero. I need to check if the user has passed the correct number of "option
    > arguments". Something like:
    >
    > (options,args) = parser.parse_args()
    >
    > len(options) != 1 or len(options) > 2:
    > print "Incorrect number of arguments passed."
    >
    > How do I accomplish it ?


    Just insert an ``if`` in front of the condition and end the program with
    ``sys.exit()`` after the message.

    Ciao,
    Marc 'BlackJack' Rintsch
     
    Marc 'BlackJack' Rintsch, Dec 4, 2005
    #2
    1. Advertising

  3. Ritesh Raj Sarraf

    Peter Otten Guest

    Ritesh Raj Sarraf wrote:

    > My program uses mostly "option arguments" hence my len(args) value is
    > always zero. I need to check if the user has passed the correct number of
    > "option arguments". Something like:
    >
    > (options,args) = parser.parse_args()
    >
    > len(options) != 1 or len(options) > 2:
    > print "Incorrect number of arguments passed."
    >
    > How do I accomplish it ?


    Judging from your code sample invention is the mother of that necessity.
    You can pass a custom Values object with a __len__() method

    class MyValues:
    def __len__(self):
    return len(self.__dict__)

    # ...

    options, args = parser.parse_args(values=MyValues())

    but you should do your users a favour and give them meaningful error
    messages. I can't conceive how you could achieve this by checking the
    number of options. Explicit constraint checks like

    options, args = parser.parse_args()
    if options.eat_your_cake and options.have_it:
    parser.error("Sorry, you cannot eat your cake and have it")

    will increase your script's usability and make it easier to maintain for
    only a tiny amount of work.

    Peter
     
    Peter Otten, Dec 4, 2005
    #3
  4. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Marc 'BlackJack' Rintsch on Monday December 5 2005 03:24 wrote:

    > In <>, Ritesh Raj
    > Sarraf wrote:
    >
    >> My program uses mostly "option arguments" hence my len(args) value is
    >> always zero. I need to check if the user has passed the correct number of
    >> "option arguments". Something like:
    >>
    >> (options,args) = parser.parse_args()
    >>
    >> len(options) != 1 or len(options) > 2:
    >> print "Incorrect number of arguments passed."
    >>
    >> How do I accomplish it ?

    >
    > Just insert an ``if`` in front of the condition and end the program with
    > ``sys.exit()`` after the message.
    >
    > Ciao,
    > Marc 'BlackJack' Rintsch


    This won't help because "options" is an instance.

    Regards,

    rrs
    - --
    Ritesh Raj Sarraf
    RESEARCHUT -- http://www.researchut.com
    "Stealing logics from one person is plagiarism, stealing from many is
    research."
    "Necessity is the mother of invention."

    Note: Please CC me. I'm not subscribed to the list
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.2 (GNU/Linux)

    iD8DBQFDlIbH4Rhi6gTxMLwRAlgSAJ0Y3TT9eCBgrck5N2Y9YjOTZMxUgwCcDeO5
    qqgzY6rz2E4YKvurnlHL0nQ=
    =hlZO
    -----END PGP SIGNATURE-----
     
    Ritesh Raj Sarraf, Dec 5, 2005
    #4
  5. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Peter Otten on Monday December 5 2005 03:34 wrote:

    > options, args = parser.parse_args(values=MyValues())
    >
    > but you should do your users a favour and give them meaningful error
    > messages. I can't conceive how you could achieve this by checking the
    > number of options. Explicit constraint checks like
    >
    > options, args = parser.parse_args()
    > if options.eat_your_cake and options.have_it:
    > parser.error("Sorry, you cannot eat your cake and have it")
    >
    > will increase your script's usability and make it easier to maintain for
    > only a tiny amount of work.


    I'm using this for "option arguments" which are mutually inclusive.
    But I want the user to pass atleast one "option argument" for the program to
    function properly.

    For example, I have an option "--fetch-update" which requires a file "foo"
    to check what it has to fetch. If the file is provided as an argument, it
    uses it, else I add a parser.set_defaults("foo") which makes the program to
    look for it in the current working directory.

    WHen the program see the "--fetch-update" option, it should execute the
    required code. Now how do I check if at least one option has been passed at
    the command-line ?
    I have multiple options but I have parser.set_defaults() for each of them.

    Regards,

    rrs
    - --
    Ritesh Raj Sarraf
    RESEARCHUT -- http://www.researchut.com
    "Stealing logics from one person is plagiarism, stealing from many is
    research."
    "Necessity is the mother of invention."

    Note: Please CC me. I'm not subscribed to the list
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.2 (GNU/Linux)

    iD8DBQFDlIhF4Rhi6gTxMLwRAsLTAJ9ydjppGrFVbH2kL00vL00HgtrxqQCghZBq
    pC0/1HftWE+9Eipx6vF+3Bo=
    =Ay8m
    -----END PGP SIGNATURE-----
     
    Ritesh Raj Sarraf, Dec 5, 2005
    #5
  6. Ritesh Raj Sarraf

    Peter Otten Guest

    Ritesh Raj Sarraf wrote:

    > I'm using this for "option arguments" which are mutually inclusive.
    > But I want the user to pass atleast one "option argument" for the program
    > to function properly.
    >
    > For example, I have an option "--fetch-update" which requires a file "foo"
    > to check what it has to fetch. If the file is provided as an argument, it
    > uses it, else I add a parser.set_defaults("foo") which makes the program
    > to look for it in the current working directory.
    >
    > WHen the program see the "--fetch-update" option, it should execute the
    > required code. Now how do I check if at least one option has been passed
    > at the command-line ?
    > I have multiple options but I have parser.set_defaults() for each of them.


    I'm sorry I don't understand your example. Wouldn't you need at least two
    options to demonstrate "mutually inclusive" options? The set_default()
    method seems to accept only keyword arguments -- but even it were used
    correctly I'm still unclear why you would need it at all.

    Perhaps you can post a few sample invocations (both correct and illegal) of
    your script together with a description (in English, not code) of how the
    script should react?

    Peter, puzzled
     
    Peter Otten, Dec 6, 2005
    #6
  7. On Tue, 6 Dec 2005, Peter Otten wrote:

    > Ritesh Raj Sarraf wrote:
    >
    >> I'm using this for "option arguments" which are mutually inclusive.
    >> But I want the user to pass atleast one "option argument" for the program
    >> to function properly.
    >>
    >> For example, I have an option "--fetch-update" which requires a file "foo"
    >> to check what it has to fetch. If the file is provided as an argument, it
    >> uses it, else I add a parser.set_defaults("foo") which makes the program
    >> to look for it in the current working directory.
    >>
    >> WHen the program see the "--fetch-update" option, it should execute the
    >> required code. Now how do I check if at least one option has been passed
    >> at the command-line ?
    >> I have multiple options but I have parser.set_defaults() for each of them.

    >
    > I'm sorry I don't understand your example. Wouldn't you need at least two
    > options to demonstrate "mutually inclusive" options? The set_default()
    > method seems to accept only keyword arguments -- but even it were used
    > correctly I'm still unclear why you would need it at all.
    >
    > Perhaps you can post a few sample invocations (both correct and illegal) of
    > your script together with a description (in English, not code) of how the
    > script should react?
    >
    > Peter, puzzled
    >
    >



    try:
    version = "0.6b"
    reldate = "03/10/2005"
    copyright = "(C) 2005 Ritesh Raj Sarraf - RESEARCHUT (http://www.researchut.com/)"

    #FIXME: Option Parsing
    # There's a flaw with either optparse or I'm not well understood with it
    # Presently you need to provide all the arguments to it to work.
    # No less, no more. This needs to be converted to getopt sometime.

    #parser = OptionParser()
    #parser = optparse.OptionParser()
    parser = optparse.OptionParser(usage="%prog [OPTION1, OPTION2, ...]", version="%prog " + version)
    parser.add_option("-d","--download-dir", dest="download_dir", help="Root directory path to save the downloaded files", action="store", type="string")
    parser.set_defaults(download_dir="foo")
    parser.add_option("-s","--cache-dir", dest="cache_dir", help="Root directory path where the pre-downloaded files will be searched. If not, give a period '.'",action="store", type="string", metavar=".")
    parser.set_defaults(cache_dir=".")
    #parser.set_defaults(cache_dir=".")
    #parser.add_option("-u","--uris", dest="uris_file", help="Full path of the uris file which contains the main database of files to be downloaded",action="store", type="string")

    # We'll have additional options
    # --set-update - This will extract the list of uris which need to be fetched
    # --fetch-update - This will fetch the list of uris which need for update.
    # --install-update - This will install the fetched database files
    # The same will happen for upgradation.
    # --set-upgrade - This will extract the list of uris which need to be fetched
    # --fetch-upgrade - This will fetch the list of uris which need for upgrade
    # --install-upgrade - This will install the fetched database files
    parser.add_option("","--set-update", dest="set_update", help="Extract the list of uris which need to be fetched for _updation_", action="store", type="string", metavar="foo")
    parser.set_defaults(set_update="foo")
    parser.add_option("","--fetch-update", dest="fetch_update", help="Fetch the list of uris which are needed for _updation_.", action="store", type="string", metavar="foo")
    parser.set_defaults(fetch_update="foo")
    parser.add_option("","--install-update", dest="install_update", help="Install the fetched database files ", action="store", type="string", metavar="foo.zip")
    parser.set_defaults(install_update="foo.zip")
    parser.add_option("","--set-upgrade", dest="set_upgrade", help="Extract the list of uris which need to be fetched ", action="store", type="string", metavar="foo.dat")
    parser.set_defaults(set_upgrade="foo.dat")
    parser.add_option("","--fetch-upgrade", dest="fetch_upgrade", help="Fetch the list of uris which are needed ", action="store", type="string", metavar="foo.dat")
    parser.set_defaults(fetch_upgrade="foo.dat")
    parser.add_option("","--install-upgrade", dest="install_upgrade", help="Install the fetched packages ", action="store", type="string", metavar="foo-fetched.zip")
    parser.set_defaults(install_ugprade="foofetched.zip")
    (options, args) = parser.parse_args()
    #parser.check_required("-d", "-s", "-u")
    #if len(arguments) != 2:
    # parser.error("Err! Incorrect number of arguments. Exiting")
    if len(options) != 1 or len(options) > 2:
    print len(args)
    parser.error("No arguments were passed\n")
    sys.exit(1)
    elif not options.set_upgrade and options.upgrade_type:
    parser.error("Only options --set-upgrade and --upgrade-type are mutually inclusive\n")
    sys.exit(1)


    Thanks,

    rrs
    --
    Ritesh Raj Sarraf
    RESEARCHUT -- http://www.researchut.com
    "Stealing logic from one person is plagiarism, stealing from many is research."
    "Necessity is the mother of invention."
     
    Ritesh Raj Sarraf, Dec 7, 2005
    #7
  8. Ritesh Raj Sarraf

    Peter Otten Guest

    Ritesh Raj Sarraf wrote:

    > parser.add_option("-d","--download-dir", dest="download_dir",
    > help="Root directory path to save the downloaded files",
    > action="store", type="string")
    > parser.set_defaults(download_dir="foo")


    This can be simplified to

    parser.add_option("-d", "--download-dir", default="foo",
    help="Root directory path to save the downloaded files")

    which seems to be the reason why I've never seen the set_defaults() call
    before.

    > if len(options) != 1 or len(options) > 2:


    It doesn't matter much as it won't work anyway, but

    len(options) > 2 implies len(options) != 1, so

    if len(options) != 1:
    #...

    would suffice here.

    Now to the actual problem: I think you didn't understand my previous
    question. I cannot infer from your non-working code what it actually should
    do. I asked for examples of how your script would be used. E. g,
    assuming the code above is in a file called sarraf.py, what should the
    following invocations

    ../sarraf.py --fetch-update bar
    ../sarraf.py --fetch-update bar --the-mutually-inclusive-option baz

    do? Would the first terminate with an error message that another option must
    also be given? Would it use the default? Would the second be accepted? Try
    to describe it as simple and clear as possible. Imagine you were talking to
    someone who has never written a line of code.

    Peter
     
    Peter Otten, Dec 7, 2005
    #8
  9. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Hi Peter,


    Peter Otten on Wednesday December 7 2005 21:25 wrote:

    > This can be simplified to
    >
    > parser.add_option("-d", "--download-dir", default="foo",
    > help="Root directory path to save the downloaded files")
    >
    > which seems to be the reason why I've never seen the set_defaults() call
    > before.


    As per python docs, it's mentioned that "default=" has been deprecated.
    That's why I changed to parser.set_defaults()

    >
    >> if len(options) != 1 or len(options) > 2:

    >
    > It doesn't matter much as it won't work anyway, but
    >
    > len(options) > 2 implies len(options) != 1, so
    >
    > if len(options) != 1:
    > #...
    >


    Yes, you're right. Sorry.

    > would suffice here.
    >


    But will len(options) give a meaningful output. "options" is an instance.
    It gives a Value Error.

    > Now to the actual problem: I think you didn't understand my previous
    > question. I cannot infer from your non-working code what it actually
    > should do. I asked for examples of how your script would be used. E. g,
    > assuming the code above is in a file called sarraf.py, what should the
    > following invocations
    >
    > ./sarraf.py --fetch-update bar
    > ./sarraf.py --fetch-update bar --the-mutually-inclusive-option baz
    >
    > do? Would the first terminate with an error message that another option
    > must also be given? Would it use the default? Would the second be
    > accepted? Try to describe it as simple and clear as possible. Imagine you
    > were talking to someone who has never written a line of code.
    >


    ../sarraf.py --fetch-update /bar

    If the user gives the /bar argument, the program should save the downloaded
    files to /bar. But I'm assuming that the user could be dumb or too lazy, in
    which case --fetch-udpate should use the parser.set_defaults value
    i.e. /foo

    ../sarraf.py --set-upgrade foo.dat --upgrade-type minimal

    set-upgrade will again write data to foo.dat. If the user doesn't pass it as
    an arguemnt it should take the defaults (again whatever is there in
    parser.set_defaults). This will be inclusive with the --upgrade-type option
    because the user will have a choice of selecting what kind of upgrade he'd
    like to do, minimal or full or blah.

    For this I think this should be enough:

    if not options.set_upgrade and options.upgrade_type:
    parser.error("They are mutually inclusive options")


    But my main concern is what if the user doesn't pass any arguemtns. Every
    option I have has a default value. So I want to check what the user has
    passed.
    But unfortunately the args variable has "0" as its value always.

    Is my way (up till now) of using optparse logically incorrect or improper ?


    Regards,

    rrs
    - --
    Ritesh Raj Sarraf
    RESEARCHUT -- http://www.researchut.com
    "Stealing logics from one person is plagiarism, stealing from many is
    research."
    "Necessity is the mother of invention."

    Note: Please CC me. I'm not subscribed to the list
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.2 (GNU/Linux)

    iD8DBQFDlzC84Rhi6gTxMLwRAtCBAJ9z5zDQ8oyx8Jy/rLe9JrwLII3xtACfTaEV
    VhMmj8OD+/p+yN/8wF6xe+8=
    =atC6
    -----END PGP SIGNATURE-----
     
    Ritesh Raj Sarraf, Dec 7, 2005
    #9
  10. Ritesh Raj Sarraf

    Peter Otten Guest

    Ritesh Raj Sarraf wrote:

    > ./sarraf.py --fetch-update /bar
    >
    > If the user gives the /bar argument, the program should save the
    > downloaded files to /bar. But I'm assuming that the user could be dumb or
    > too lazy, in which case --fetch-udpate should use the parser.set_defaults
    > value i.e. /foo
    >
    > ./sarraf.py --set-upgrade foo.dat --upgrade-type minimal
    >
    > set-upgrade will again write data to foo.dat. If the user doesn't pass it
    > as an arguemnt it should take the defaults (again whatever is there in
    > parser.set_defaults). This will be inclusive with the --upgrade-type
    > option because the user will have a choice of selecting what kind of
    > upgrade he'd like to do, minimal or full or blah.
    >
    > For this I think this should be enough:
    >
    > if not options.set_upgrade and options.upgrade_type:
    > parser.error("They are mutually inclusive options")
    >
    >
    > But my main concern is what if the user doesn't pass any arguemtns. Every
    > option I have has a default value. So I want to check what the user has
    > passed.
    > But unfortunately the args variable has "0" as its value always.


    args are just the leftover arguments. For

    ../sarraf.py alpha --set-upgrade foo.dat beta

    it would be ["alpha", "beta"].

    ---

    I think your description is starting to make sense to me. Your user can
    either update or upgrade but you cannot just check the value of e. g.
    set_upgrade because you want to treat the default value and that same value
    given on the command line differently.

    If this is a correct assessment I don't think what you want is covered by
    optparse. However, I hacked something together:

    import optparse

    parser = optparse.OptionParser()

    parser.add_option("--alpha")
    parser.add_option("--beta")

    class Values(object):
    def __init__(self):
    self.__defaults = {}
    def set_defaults(self, **kw):
    self.__defaults.update(kw)
    def __len__(self):
    """Number of options set by the user."""
    return len(self.__dict__) -1
    def __getattr__(self, name):
    try:
    return self.__defaults[name]
    except KeyError:
    raise AttributeError
    def is_default(self, name):
    """Return True when the default fro option 'name'
    wasn't overriden by the user"""
    return name not in self.__dict__

    values = Values()
    values.set_defaults(alpha="xxx", beta="yyy")

    options, args = parser.parse_args(values=values)

    print "len(options) =", len(options)
    print "alpha =", options.alpha,
    print "(using default)" * options.is_default("alpha")
    print "beta =", options.beta,
    print "(using default)" * options.is_default("beta")

    Not particularly elegant but I'm not able to come up with something better
    for the moment. Maybe you should just provide fewer defaults to the parser.
    Or you could look into option callbacks for an alternate approach.

    > Is my way (up till now) of using optparse logically incorrect or improper
    > ?


    Well, as the optparse author points out, "required options" are a
    self-contradictory term -- don't use them if you can avoid it. Would your
    problem go away if you used two different scripts, one for updating and the
    other for upgrading?

    Peter
     
    Peter Otten, Dec 7, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Julien ROUZIERES

    g++ -pg option and -shared option

    Julien ROUZIERES, Dec 21, 2004, in forum: C++
    Replies:
    1
    Views:
    737
    GianGuz
    Dec 21, 2004
  2. Cas
    Replies:
    5
    Views:
    807
    Kevin Jones
    Aug 28, 2006
  3. Kevin Blount

    page.aspx?option - how to detect "option"

    Kevin Blount, Nov 28, 2006, in forum: ASP .Net
    Replies:
    6
    Views:
    616
    =?Utf-8?B?RWVyYWo=?=
    Nov 28, 2006
  4. John

    Regex for <option> ... </option>

    John, Jan 23, 2009, in forum: Perl Misc
    Replies:
    10
    Views:
    246
    Eric Pozharski
    Jan 29, 2009
  5. Mark Kolber
    Replies:
    4
    Views:
    351
Loading...

Share This Page