annotate mercurial/fancyopts.py @ 51594:e3a5ec2d236a

outgoing: rework the handling of the `missingroots` case to be faster The previous implementation was slow, to the point it was taking a significant amount of `hg bundle --type none-streamv2` call. We rework the code to compute the same value much faster, making the operation disappear from the `hg bundle --type none-streamv2` profile. Someone would remark that producing a streamclone does not requires an `outgoing` object. However that is a matter for another day. There is other user of `missingroots` (non stream `hg bundle` call for example), and they will also benefit from this rework. We implement an old TODO in the process, directly computing the missing and common attribute as we have most element at hand already. ### benchmark.name = hg.command.bundle # bin-env-vars.hg.flavor = default # bin-env-vars.hg.py-re2-module = default # benchmark.variants.revs = all # benchmark.variants.type = none-streamv2 ## data-env-vars.name = heptapod-public-2024-03-25-zstd-sparse-revlog before: 7.750458 after: 6.665565 (-14.00%, -1.08) ## data-env-vars.name = mercurial-public-2024-03-22-zstd-sparse-revlog before: 0.700229 after: 0.496050 (-29.16%, -0.20) ## data-env-vars.name = mozilla-try-2023-03-22-zstd-sparse-revlog before: 346.508952 after: 316.749699 (-8.59%, -29.76) ## data-env-vars.name = pypy-2024-03-22-zstd-sparse-revlog before: 3.401700 after: 2.915810 (-14.28%, -0.49) ## data-env-vars.name = tryton-public-2024-03-22-zstd-sparse-revlog before: 1.870798 after: 1.461583 (-21.87%, -0.41) note: this whole `missingroots` of outgoing has a limited number of callers and could likely be replace by something simpler (like taking an explicit "missing_revs" set for example). However this is a wider change and we focus on a small impact, quick rework that does not change the API for now.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 09 Apr 2024 22:36:35 +0200
parents 642e31cb55f0
children f4733654f144
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8230
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
1 # fancyopts.py - better command line parsing
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
2 #
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 45837
diff changeset
3 # Copyright 2005-2009 Olivia Mackall <olivia@selenic.com> and others
8230
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
4 #
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8366
diff changeset
6 # GNU General Public License version 2 or any later version.
8230
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
7
25947
6002e2d95e54 fancyopts: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25563
diff changeset
8
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
9 import abc
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
10 import functools
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
11
25947
6002e2d95e54 fancyopts: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25563
diff changeset
12 from .i18n import _
30578
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29947
diff changeset
13 from . import (
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29947
diff changeset
14 error,
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29947
diff changeset
15 pycompat,
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29947
diff changeset
16 )
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
17
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
18 # Set of flags to not apply boolean negation logic on
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 30578
diff changeset
19 nevernegate = {
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
20 # avoid --no-noninteractive
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
21 b'noninteractive',
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
22 # These two flags are special because they cause hg to do one
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
23 # thing and then exit, and so aren't suitable for use in things
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
24 # like aliases anyway.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
25 b'help',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
26 b'version',
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 30578
diff changeset
27 }
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
28
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
29
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
30 def _earlyoptarg(arg, shortlist, namelist):
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
31 """Check if the given arg is a valid unabbreviated option
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
32
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
33 Returns (flag_str, has_embedded_value?, embedded_value, takes_value?)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
34
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
35 >>> def opt(arg):
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
36 ... return _earlyoptarg(arg, b'R:q', [b'cwd=', b'debugger'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
37
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
38 long form:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
39
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
40 >>> opt(b'--cwd')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
41 ('--cwd', False, '', True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
42 >>> opt(b'--cwd=')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
43 ('--cwd', True, '', True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
44 >>> opt(b'--cwd=foo')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
45 ('--cwd', True, 'foo', True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
46 >>> opt(b'--debugger')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
47 ('--debugger', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
48 >>> opt(b'--debugger=') # invalid but parsable
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
49 ('--debugger', True, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
50
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
51 short form:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
52
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
53 >>> opt(b'-R')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
54 ('-R', False, '', True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
55 >>> opt(b'-Rfoo')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
56 ('-R', True, 'foo', True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
57 >>> opt(b'-q')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
58 ('-q', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
59 >>> opt(b'-qfoo') # invalid but parsable
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
60 ('-q', True, 'foo', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
61
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
62 unknown or invalid:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
63
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
64 >>> opt(b'--unknown')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
65 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
66 >>> opt(b'-u')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
67 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
68 >>> opt(b'-ufoo')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
69 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
70 >>> opt(b'--')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
71 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
72 >>> opt(b'-')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
73 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
74 >>> opt(b'-:')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
75 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
76 >>> opt(b'-:foo')
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
77 ('', False, '', False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
78 """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
79 if arg.startswith(b'--'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
80 flag, eq, val = arg.partition(b'=')
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
81 if flag[2:] in namelist:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
82 return flag, bool(eq), val, False
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
83 if flag[2:] + b'=' in namelist:
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
84 return flag, bool(eq), val, True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
85 elif arg.startswith(b'-') and arg != b'-' and not arg.startswith(b'-:'):
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
86 flag, val = arg[:2], arg[2:]
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
87 i = shortlist.find(flag[1:])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
88 if i >= 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
89 return flag, bool(val), val, shortlist.startswith(b':', i + 1)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
90 return b'', False, b'', False
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
91
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
92
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
93 def earlygetopt(args, shortlist, namelist, gnu=False, keepsep=False):
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
94 """Parse options like getopt, but ignores unknown options and abbreviated
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
95 forms
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
96
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
97 If gnu=False, this stops processing options as soon as a non/unknown-option
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
98 argument is encountered. Otherwise, option and non-option arguments may be
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
99 intermixed, and unknown-option arguments are taken as non-option.
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
100
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
101 If keepsep=True, '--' won't be removed from the list of arguments left.
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
102 This is useful for stripping early options from a full command arguments.
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
103
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
104 >>> def get(args, gnu=False, keepsep=False):
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
105 ... return earlygetopt(args, b'R:q', [b'cwd=', b'debugger'],
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
106 ... gnu=gnu, keepsep=keepsep)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
107
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
108 default parsing rules for early options:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
109
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
110 >>> get([b'x', b'--cwd', b'foo', b'-Rbar', b'-q', b'y'], gnu=True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
111 ([('--cwd', 'foo'), ('-R', 'bar'), ('-q', '')], ['x', 'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
112 >>> get([b'x', b'--cwd=foo', b'y', b'-R', b'bar', b'--debugger'], gnu=True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
113 ([('--cwd', 'foo'), ('-R', 'bar'), ('--debugger', '')], ['x', 'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
114 >>> get([b'--unknown', b'--cwd=foo', b'--', '--debugger'], gnu=True)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
115 ([('--cwd', 'foo')], ['--unknown', '--debugger'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
116
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
117 restricted parsing rules (early options must come first):
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
118
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
119 >>> get([b'--cwd', b'foo', b'-Rbar', b'x', b'-q', b'y'], gnu=False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
120 ([('--cwd', 'foo'), ('-R', 'bar')], ['x', '-q', 'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
121 >>> get([b'--cwd=foo', b'x', b'y', b'-R', b'bar', b'--debugger'], gnu=False)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
122 ([('--cwd', 'foo')], ['x', 'y', '-R', 'bar', '--debugger'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
123 >>> get([b'--unknown', b'--cwd=foo', b'--', '--debugger'], gnu=False)
35227
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
124 ([], ['--unknown', '--cwd=foo', '--', '--debugger'])
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
125
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
126 stripping early options (without loosing '--'):
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
127
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
128 >>> get([b'x', b'-Rbar', b'--', '--debugger'], gnu=True, keepsep=True)[1]
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
129 ['x', '--', '--debugger']
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
130
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
131 last argument:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
132
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
133 >>> get([b'--cwd'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
134 ([], ['--cwd'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
135 >>> get([b'--cwd=foo'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
136 ([('--cwd', 'foo')], [])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
137 >>> get([b'-R'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
138 ([], ['-R'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
139 >>> get([b'-Rbar'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
140 ([('-R', 'bar')], [])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
141 >>> get([b'-q'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
142 ([('-q', '')], [])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
143 >>> get([b'-q', b'--'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
144 ([('-q', '')], [])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
145
35227
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
146 '--' may be a value:
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
147
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
148 >>> get([b'-R', b'--', b'x'])
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
149 ([('-R', '--')], ['x'])
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
150 >>> get([b'--cwd', b'--', b'x'])
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
151 ([('--cwd', '--')], ['x'])
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
152
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
153 value passed to bool options:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
154
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
155 >>> get([b'--debugger=foo', b'x'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
156 ([], ['--debugger=foo', 'x'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
157 >>> get([b'-qfoo', b'x'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
158 ([], ['-qfoo', 'x'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
159
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
160 short option isn't separated with '=':
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
161
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
162 >>> get([b'-R=bar'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
163 ([('-R', '=bar')], [])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
164
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
165 ':' may be in shortlist, but shouldn't be taken as an option letter:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
166
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
167 >>> get([b'-:', b'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
168 ([], ['-:', 'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
170 '-' is a valid non-option argument:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
171
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
172 >>> get([b'-', b'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
173 ([], ['-', 'y'])
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
174 """
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
175 parsedopts = []
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
176 parsedargs = []
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
177 pos = 0
35227
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
178 while pos < len(args):
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
179 arg = args[pos]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
180 if arg == b'--':
35227
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
181 pos += not keepsep
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
182 break
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
183 flag, hasval, val, takeval = _earlyoptarg(arg, shortlist, namelist)
35227
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
184 if not hasval and takeval and pos + 1 >= len(args):
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
185 # missing last argument
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
186 break
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
187 if not flag or hasval and not takeval:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
188 # non-option argument or -b/--bool=INVALID_VALUE
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
189 if gnu:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
190 parsedargs.append(arg)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
191 pos += 1
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
192 else:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
193 break
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
194 elif hasval == takeval:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
195 # -b/--bool or -s/--str=VALUE
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
196 parsedopts.append((flag, val))
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
197 pos += 1
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
198 else:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
199 # -s/--str VALUE
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
200 parsedopts.append((flag, args[pos + 1]))
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
201 pos += 2
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
202
35227
98a5aa5575e7 fancyopts: fix handling of "--" value in earlygetopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35226
diff changeset
203 parsedargs.extend(args[pos:])
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
204 return parsedopts, parsedargs
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
205
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
206
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
207 class customopt: # pytype: disable=ignored-metaclass
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
208 """Manage defaults and mutations for any type of opt."""
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
209
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
210 __metaclass__ = abc.ABCMeta
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
211
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
212 def __init__(self, defaultvalue):
37092
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
213 self._defaultvalue = defaultvalue
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
214
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
215 def _isboolopt(self):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
216 return False
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
217
37092
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
218 def getdefaultvalue(self):
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
219 """Returns the default value for this opt.
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
220
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
221 Subclasses should override this to return a new value if the value type
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
222 is mutable."""
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
223 return self._defaultvalue
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
224
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
225 @abc.abstractmethod
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
226 def newstate(self, oldstate, newparam, abort):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
227 """Adds newparam to oldstate and returns the new state.
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
228
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
229 On failure, abort can be called with a string error message."""
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
230
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
231
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
232 class _simpleopt(customopt):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
233 def _isboolopt(self):
37092
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
234 return isinstance(self._defaultvalue, (bool, type(None)))
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
235
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
236 def newstate(self, oldstate, newparam, abort):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
237 return newparam
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
238
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
239
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
240 class _callableopt(customopt):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
241 def __init__(self, callablefn):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
242 self.callablefn = callablefn
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
243 super(_callableopt, self).__init__(None)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
244
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
245 def newstate(self, oldstate, newparam, abort):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
246 return self.callablefn(newparam)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
247
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
248
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
249 class _listopt(customopt):
37092
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
250 def getdefaultvalue(self):
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
251 return self._defaultvalue[:]
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
252
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
253 def newstate(self, oldstate, newparam, abort):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
254 oldstate.append(newparam)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
255 return oldstate
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
256
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
257
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
258 class _intopt(customopt):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
259 def newstate(self, oldstate, newparam, abort):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
260 try:
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
261 return int(newparam)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
262 except ValueError:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
263 abort(_(b'expected int'))
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
264
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
265
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
266 def _defaultopt(default):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
267 """Returns a default opt implementation, given a default value."""
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
268
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
269 if isinstance(default, customopt):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
270 return default
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
271 elif callable(default):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
272 return _callableopt(default)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
273 elif isinstance(default, list):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
274 return _listopt(default[:])
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
275 elif type(default) is type(1):
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
276 return _intopt(default)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
277 else:
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
278 return _simpleopt(default)
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
279
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
280
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
281 def fancyopts(args, options, state, gnu=False, early=False, optaliases=None):
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
282 """
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
283 read args, parse options, and store options in state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
284
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
285 each option is a tuple of:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
286
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
287 short option or ''
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
288 long option
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
289 default value
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
290 description
11321
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
291 option value label(optional)
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
292
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
293 option types include:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
294
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
295 boolean or none - option sets variable in state to true
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
296 string - parameter string is stored in state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
297 list - parameter string is added to a list
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
298 integer - parameter strings is stored as int
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
299 function - call function with parameter
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
300 customopt - subclass of 'customopt'
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
301
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
302 optaliases is a mapping from a canonical option name to a list of
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
303 additional long options. This exists for preserving backward compatibility
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
304 of early options. If we want to use it extensively, please consider moving
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
305 the functionality to the options table (e.g separate long options by '|'.)
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
306
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
307 non-option args are returned
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
308 """
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
309 if optaliases is None:
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
310 optaliases = {}
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
311 namelist = []
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
312 shortlist = b''
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
313 argmap = {}
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
314 defmap = {}
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
315 negations = {}
44452
9d2b2df2c2ba cleanup: run pyupgrade on our source tree to clean up varying things
Augie Fackler <augie@google.com>
parents: 43474
diff changeset
316 alllong = {o[1] for o in options}
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
317
11321
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
318 for option in options:
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
319 if len(option) == 5:
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
320 short, name, default, comment, dummy = option
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
321 else:
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
322 short, name, default, comment = option
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
323 # convert opts to getopt format
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
324 onames = [name]
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
325 onames.extend(optaliases.get(name, []))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
326 name = name.replace(b'-', b'_')
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
327
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
328 argmap[b'-' + short] = name
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
329 for n in onames:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
330 argmap[b'--' + n] = name
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
331 defmap[name] = _defaultopt(default)
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
332
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
333 # copy defaults to state
37092
ef6215df2402 fancyopts: prevent mutation of the default value in customopts
Daniel Ploch <dploch@google.com>
parents: 36383
diff changeset
334 state[name] = defmap[name].getdefaultvalue()
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
335
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
336 # does it take a parameter?
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
337 if not defmap[name]._isboolopt():
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
338 if short:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
339 short += b':'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
340 onames = [n + b'=' for n in onames]
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
341 elif name not in nevernegate:
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
342 for n in onames:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
343 if n.startswith(b'no-'):
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
344 insert = n[3:]
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
345 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
346 insert = b'no-' + n
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
347 # backout (as a practical example) has both --commit and
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
348 # --no-commit options, so we don't want to allow the
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
349 # negations of those flags.
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
350 if insert not in alllong:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
351 assert (b'--' + n) not in negations
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
352 negations[b'--' + insert] = b'--' + n
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
353 namelist.append(insert)
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
354 if short:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
355 shortlist += short
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
356 if name:
35223
4edd2202f7d7 dispatch: alias --repo to --repository while parsing early options
Yuya Nishihara <yuya@tcha.org>
parents: 35169
diff changeset
357 namelist.extend(onames)
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
358
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
359 # parse arguments
35169
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
360 if early:
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
361 parse = functools.partial(earlygetopt, gnu=gnu)
898c6f812a51 fancyopts: add early-options parser compatible with getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 33103
diff changeset
362 elif gnu:
35226
5b569d512fbd fancyopts: use getopt.gnu_getopt()
Yuya Nishihara <yuya@tcha.org>
parents: 35223
diff changeset
363 parse = pycompat.gnugetoptb
7772
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
364 else:
30578
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29947
diff changeset
365 parse = pycompat.getoptb
7772
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
366 opts, args = parse(args, shortlist, namelist)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
367
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
368 # transfer result to state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
369 for opt, val in opts:
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
370 boolval = True
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
371 negation = negations.get(opt, False)
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
372 if negation:
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
373 opt = negation
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
374 boolval = False
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
375 name = argmap[opt]
25563
69e8384a436c fancyopts: allow all callable as default parameter value
introom <i@introo.me>
parents: 21794
diff changeset
376 obj = defmap[name]
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
377 if obj._isboolopt():
29947
e1f0ec0b7d2d flags: allow specifying --no-boolean-flag on the command line (BC)
Augie Fackler <augie@google.com>
parents: 26587
diff changeset
378 state[name] = boolval
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
379 else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
380
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
381 def abort(s):
45837
2eb8ad899fa6 errors: raise InputError in fancyopts
Martin von Zweigbergk <martinvonz@google.com>
parents: 44452
diff changeset
382 raise error.InputError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
383 _(b'invalid value %r for option %s, %s')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
384 % (pycompat.maybebytestr(val), opt, s)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
385 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 37465
diff changeset
386
36353
cc9d0763c8e9 fancyopts: add support for custom multi-arg opts in fancyopts.py
Daniel Ploch <dploch@google.com>
parents: 35227
diff changeset
387 state[name] = defmap[name].newstate(state[name], val, abort)
209
63af1db35611 Beginning of new command parsing interface
mpm@selenic.com
parents: 164
diff changeset
388
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
389 # return unparsed args
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
390 return args