You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
6.6 KiB

  1. from argparse import ArgumentParser, _SubParsersAction
  2. from argparse import _MutuallyExclusiveGroup, _ArgumentGroup
  3. from textwrap import dedent
  4. class GooeySubParser(_SubParsersAction):
  5. def __init__(self, *args, **kwargs):
  6. super(GooeySubParser, self).__init__(*args, **kwargs)
  7. # TODO: figure out how to correctly dispatch all of these
  8. # so that the individual wrappers aren't needed
  9. class GooeyArgumentGroup(_ArgumentGroup):
  10. def __init__(self, parser, widgets, options, *args, **kwargs):
  11. self.parser = parser
  12. self.widgets = widgets
  13. self.options = options
  14. super(GooeyArgumentGroup, self).__init__(self.parser, *args, **kwargs)
  15. def add_argument(self, *args, **kwargs):
  16. widget = kwargs.pop('widget', None)
  17. metavar = kwargs.pop('metavar', None)
  18. options = kwargs.pop('gooey_options', None)
  19. action = super(GooeyArgumentGroup, self).add_argument(*args, **kwargs)
  20. self.parser._actions[-1].metavar = metavar
  21. self.widgets[self.parser._actions[-1].dest] = widget
  22. self.options[self.parser._actions[-1].dest] = options
  23. return action
  24. def add_argument_group(self, *args, **kwargs):
  25. options = kwargs.pop('gooey_options', {})
  26. group = GooeyArgumentGroup(self.parser, self.widgets, self.options, *args, **kwargs)
  27. group.gooey_options = options
  28. self._action_groups.append(group)
  29. return group
  30. def add_mutually_exclusive_group(self, *args, **kwargs):
  31. options = kwargs.pop('gooey_options', {})
  32. container = self
  33. group = GooeyMutuallyExclusiveGroup(container, self.parser, self.widgets, self.options, *args, **kwargs)
  34. group.gooey_options = options
  35. self.parser._mutually_exclusive_groups.append(group)
  36. return group
  37. class GooeyMutuallyExclusiveGroup(_MutuallyExclusiveGroup):
  38. def __init__(self, container, parser, widgets, options, *args, **kwargs):
  39. self.parser = parser
  40. self.widgets = widgets
  41. self.options = options
  42. super(GooeyMutuallyExclusiveGroup, self).__init__(container, *args, **kwargs)
  43. def add_argument(self, *args, **kwargs):
  44. widget = kwargs.pop('widget', None)
  45. metavar = kwargs.pop('metavar', None)
  46. options = kwargs.pop('gooey_options', None)
  47. super(GooeyMutuallyExclusiveGroup, self).add_argument(*args, **kwargs)
  48. self.parser._actions[-1].metavar = metavar
  49. self.widgets[self.parser._actions[-1].dest] = widget
  50. self.options[self.parser._actions[-1].dest] = options
  51. class GooeyParser(object):
  52. def __init__(self, **kwargs):
  53. self.__dict__['parser'] = ArgumentParser(**kwargs)
  54. self.widgets = {}
  55. self.options = {}
  56. if 'parents' in kwargs:
  57. for parent in kwargs['parents']:
  58. if isinstance(parent, self.__class__):
  59. self.widgets.update(parent.widgets)
  60. self.options.update(parent.options)
  61. @property
  62. def _mutually_exclusive_groups(self):
  63. return self.parser._mutually_exclusive_groups
  64. @property
  65. def _actions(self):
  66. return self.parser._actions
  67. @property
  68. def description(self):
  69. return self.parser.description
  70. def add_argument(self, *args, **kwargs):
  71. widget = kwargs.pop('widget', None)
  72. metavar = kwargs.pop('metavar', None)
  73. options = kwargs.pop('gooey_options', None)
  74. action = self.parser.add_argument(*args, **kwargs)
  75. self.parser._actions[-1].metavar = metavar
  76. action_dest = self.parser._actions[-1].dest
  77. if action_dest not in self.widgets or self.widgets[action_dest] is None:
  78. self.widgets[action_dest] = widget
  79. if action_dest not in self.options or self.options[action_dest] is None:
  80. self.options[self.parser._actions[-1].dest] = options
  81. self._validate_constraints(
  82. self.parser._actions[-1],
  83. widget,
  84. options or {},
  85. **kwargs
  86. )
  87. return action
  88. def add_mutually_exclusive_group(self, *args, **kwargs):
  89. options = kwargs.pop('gooey_options', {})
  90. group = GooeyMutuallyExclusiveGroup(self, self.parser, self.widgets, self.options, *args, **kwargs)
  91. group.gooey_options = options
  92. self.parser._mutually_exclusive_groups.append(group)
  93. return group
  94. def add_argument_group(self, *args, **kwargs):
  95. options = kwargs.pop('gooey_options', {})
  96. group = GooeyArgumentGroup(self.parser, self.widgets, self.options, *args, **kwargs)
  97. group.gooey_options = options
  98. self.parser._action_groups.append(group)
  99. return group
  100. def parse_args(self, args=None, namespace=None):
  101. return self.parser.parse_args(args, namespace)
  102. def add_subparsers(self, **kwargs):
  103. if self._subparsers is not None:
  104. self.error(_('cannot have multiple subparser arguments'))
  105. # add the parser class to the arguments if it's not present
  106. kwargs.setdefault('parser_class', type(self))
  107. if 'title' in kwargs or 'description' in kwargs:
  108. title = kwargs.pop('title', 'subcommands')
  109. description = kwargs.pop('description', None)
  110. self._subparsers = self.add_argument_group(title, description)
  111. else:
  112. self._subparsers = self._positionals
  113. # prog defaults to the usage message of this parser, skipping
  114. # optional arguments and with no "usage:" prefix
  115. if kwargs.get('prog') is None:
  116. formatter = self._get_formatter()
  117. positionals = self._get_positional_actions()
  118. groups = self._mutually_exclusive_groups
  119. formatter.add_usage(self.usage, positionals, groups, '')
  120. kwargs['prog'] = formatter.format_help().strip()
  121. # create the parsers action and add it to the positionals list
  122. parsers_class = self._pop_action_class(kwargs, 'parsers')
  123. action = parsers_class(option_strings=[], **kwargs)
  124. self._subparsers._add_action(action)
  125. # return the created parsers action
  126. return action
  127. def _validate_constraints(self, parser_action, widget, options, **kwargs):
  128. from gooey.python_bindings import constraints
  129. constraints.assert_listbox_constraints(widget, **kwargs)
  130. constraints.assert_visibility_requirements(parser_action, options)
  131. def __getattr__(self, item):
  132. return getattr(self.parser, item)
  133. def __setattr__(self, key, value):
  134. return setattr(self.parser, key, value)