Skip to content

Commit d5e28e1

Browse files
authored
gh-144812: Make argparse group classes public (#158045)
1 parent 638d638 commit d5e28e1

5 files changed

Lines changed: 68 additions & 8 deletions

File tree

‎Doc/library/argparse.rst‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,19 @@ Argument groups
20722072
is now deprecated.
20732073

20742074

2075+
.. class:: ArgumentGroup
2076+
2077+
The type of objects returned by :meth:`ArgumentParser.add_argument_group`.
2078+
Its :meth:`~ArgumentParser.add_argument` and
2079+
:meth:`~ArgumentParser.add_mutually_exclusive_group` methods work as on
2080+
:class:`ArgumentParser`. Use :meth:`~ArgumentParser.add_argument_group`
2081+
to create instances. Only the methods documented here are part of the
2082+
public API; other attributes and methods are implementation details.
2083+
2084+
.. versionadded:: next
2085+
The private ``_ArgumentGroup`` name remains as an alias.
2086+
2087+
20752088
Mutual exclusion
20762089
^^^^^^^^^^^^^^^^
20772090

@@ -2135,6 +2148,20 @@ Mutual exclusion
21352148
exposed through inheritance.
21362149

21372150

2151+
.. class:: MutuallyExclusiveGroup
2152+
2153+
The type of objects returned by
2154+
:meth:`ArgumentParser.add_mutually_exclusive_group`.
2155+
Its :meth:`~ArgumentParser.add_argument` method works as on
2156+
:class:`ArgumentParser`. Use
2157+
:meth:`~ArgumentParser.add_mutually_exclusive_group` to create instances.
2158+
Only the ``add_argument`` method documented here is part of the public API;
2159+
other attributes and methods are implementation details.
2160+
2161+
.. versionadded:: next
2162+
The private ``_MutuallyExclusiveGroup`` name remains as an alias.
2163+
2164+
21382165
Parser defaults
21392166
^^^^^^^^^^^^^^^
21402167

‎Doc/whatsnew/3.16.rst‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ New modules
126126
Improved modules
127127
================
128128

129+
argparse
130+
--------
131+
132+
* :class:`~argparse.ArgumentGroup` and
133+
:class:`~argparse.MutuallyExclusiveGroup`, the types returned by
134+
:meth:`~argparse.ArgumentParser.add_argument_group` and
135+
:meth:`~argparse.ArgumentParser.add_mutually_exclusive_group`, are now
136+
public. The ``_``-prefixed names remain as aliases.
137+
(Contributed by Bernát Gábor in :gh:`144812`.)
138+
129139
asyncio
130140
-------
131141

‎Lib/argparse.py‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
__all__ = [
6868
'ArgumentParser',
6969
'ArgumentError',
70+
'ArgumentGroup',
7071
'ArgumentTypeError',
7172
'BooleanOptionalAction',
7273
'FileType',
@@ -75,6 +76,7 @@
7576
'RawDescriptionHelpFormatter',
7677
'RawTextHelpFormatter',
7778
'MetavarTypeHelpFormatter',
79+
'MutuallyExclusiveGroup',
7880
'Namespace',
7981
'Action',
8082
'ONE_OR_MORE',
@@ -1699,12 +1701,12 @@ def add_argument(self, *args, **kwargs):
16991701
return self._add_action(action)
17001702

17011703
def add_argument_group(self, *args, **kwargs):
1702-
group = _ArgumentGroup(self, *args, **kwargs)
1704+
group = ArgumentGroup(self, *args, **kwargs)
17031705
self._action_groups.append(group)
17041706
return group
17051707

17061708
def add_mutually_exclusive_group(self, **kwargs):
1707-
group = _MutuallyExclusiveGroup(self, **kwargs)
1709+
group = MutuallyExclusiveGroup(self, **kwargs)
17081710
self._mutually_exclusive_groups.append(group)
17091711
return group
17101712

@@ -1892,7 +1894,7 @@ def _check_help(self, action):
18921894
raise ValueError('badly formed help string') from exc
18931895

18941896

1895-
class _ArgumentGroup(_ActionsContainer):
1897+
class ArgumentGroup(_ActionsContainer):
18961898

18971899
def __init__(self, container, title=None, description=None, **kwargs):
18981900
if 'prefix_chars' in kwargs:
@@ -1907,7 +1909,7 @@ def __init__(self, container, title=None, description=None, **kwargs):
19071909
update('conflict_handler', container.conflict_handler)
19081910
update('prefix_chars', container.prefix_chars)
19091911
update('argument_default', container.argument_default)
1910-
super_init = super(_ArgumentGroup, self).__init__
1912+
super_init = super(ArgumentGroup, self).__init__
19111913
super_init(description=description, **kwargs)
19121914

19131915
# group attributes
@@ -1924,21 +1926,21 @@ def __init__(self, container, title=None, description=None, **kwargs):
19241926
self._mutually_exclusive_groups = container._mutually_exclusive_groups
19251927

19261928
def _add_action(self, action):
1927-
action = super(_ArgumentGroup, self)._add_action(action)
1929+
action = super(ArgumentGroup, self)._add_action(action)
19281930
self._group_actions.append(action)
19291931
return action
19301932

19311933
def _remove_action(self, action):
1932-
super(_ArgumentGroup, self)._remove_action(action)
1934+
super(ArgumentGroup, self)._remove_action(action)
19331935
self._group_actions.remove(action)
19341936

19351937
def add_argument_group(self, *args, **kwargs):
19361938
raise ValueError('argument groups cannot be nested')
19371939

1938-
class _MutuallyExclusiveGroup(_ArgumentGroup):
1940+
class MutuallyExclusiveGroup(ArgumentGroup):
19391941

19401942
def __init__(self, container, required=False):
1941-
super(_MutuallyExclusiveGroup, self).__init__(container)
1943+
super(MutuallyExclusiveGroup, self).__init__(container)
19421944
self.required = required
19431945
self._container = container
19441946

@@ -1957,6 +1959,10 @@ def _remove_action(self, action):
19571959
def add_mutually_exclusive_group(self, **kwargs):
19581960
raise ValueError('mutually exclusive groups cannot be nested')
19591961

1962+
# Kept for code that imports the pre-3.16 private names.
1963+
_ArgumentGroup = ArgumentGroup
1964+
_MutuallyExclusiveGroup = MutuallyExclusiveGroup
1965+
19601966
def _prog_name(prog=None):
19611967
if prog is not None:
19621968
return prog

‎Lib/test/test_argparse.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3246,6 +3246,20 @@ def test_nested_argument_group(self):
32463246
'argument groups cannot be nested',
32473247
g.add_argument_group)
32483248

3249+
def test_group_types(self):
3250+
parser = argparse.ArgumentParser()
3251+
group = parser.add_argument_group()
3252+
self.assertIs(type(group), argparse.ArgumentGroup)
3253+
self.assertIs(type(parser.add_mutually_exclusive_group()),
3254+
argparse.MutuallyExclusiveGroup)
3255+
self.assertIs(type(group.add_mutually_exclusive_group()),
3256+
argparse.MutuallyExclusiveGroup)
3257+
3258+
def test_private_aliases(self):
3259+
self.assertIs(argparse._ArgumentGroup, argparse.ArgumentGroup)
3260+
self.assertIs(argparse._MutuallyExclusiveGroup,
3261+
argparse.MutuallyExclusiveGroup)
3262+
32493263
# ===================
32503264
# Parent parser tests
32513265
# ===================
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Make :class:`argparse.ArgumentGroup` and
2+
:class:`argparse.MutuallyExclusiveGroup` public. The private
3+
``_ArgumentGroup`` and ``_MutuallyExclusiveGroup`` names remain as aliases.

0 commit comments

Comments
 (0)