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.

171 lines
6.7 KiB

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