def testCompleterForAttribute(self): collections = [ ('example.projects.shelves.books', True), ('example.projects.shelves', True), ('cloudresourcemanager.projects', True)] self.MockCRUDMethods(*collections) expected_completer = completers.ResourceArgumentCompleter( self.resource_spec, self.book_collection, registry.GetMethod('example.projects.shelves.books', 'list'), param='booksId', static_params={}) completer = completers.CompleterForAttribute(self.resource_spec, 'book')() self.assertEqual(expected_completer, completer) expected_completer = completers.ResourceArgumentCompleter( self.resource_spec, self.shelf_collection, registry.GetMethod('example.projects.shelves', 'list'), param='shelvesId', static_params={}) completer = completers.CompleterForAttribute(self.resource_spec, 'shelf')() self.assertEqual(expected_completer, completer) expected_completer = completers.ResourceArgumentCompleter( self.resource_spec, self.project_collection, registry.GetMethod('cloudresourcemanager.projects', 'list'), param='projectsId', static_params={}) completer = completers.CompleterForAttribute( self.resource_spec, 'project')() self.assertEqual(expected_completer, completer)
def testCompleterIsNoneIfNoMethod(self): collections = [ ('cloudresourcemanager.projects', True), ('example.projects.shelves.books', True)] self.MockCRUDMethods(*collections) self._PatchProjectReturnType() self._PatchBookReturnType() self.assertIsNone(completers.CompleterForAttribute( self.resource_spec_auto_completers, 'shelf'))
def RunResourceCompleter(self, resource_spec, attribute_name, prefix='', expected_completions=None, args=None, presentation_name=None, dest=None, flag_name_overrides=None, projects=None): """Run a test of a resource completer. Args: resource_spec: googlecloudsdk.calliope.concepts.concepts.ResourceSpec, the resource spec. attribute_name: str, the name of the attribute. prefix: str, the value to be completed if any. Defaults to ''. expected_completions: [str], the list of expected results if any. args: {str: str}, a dict of args to be parsed into the mock namespace. presentation_name: str, the name of the presentation spec. Defaults to the resource name (i.e. a positional arg). dest: str, the name of the argument for which completion is running. Defaults to the name of the attribute. flag_name_overrides: {str: str} | None, the flag name overrides for the presentation spec, if any. projects: [str], a list of project IDs to be returned by a list projects call if the project argument needs to be completed. If None, no list projects call is expected. """ args = args or {} flag_name_overrides = flag_name_overrides or {} presentation_name = presentation_name or resource_spec.name dest = dest or attribute_name expected_completions = expected_completions or [] presentation_spec = presentation_specs.ResourcePresentationSpec( presentation_name, resource_spec, 'Help text', prefixes=False, flag_name_overrides=flag_name_overrides) resource_info = concept_parsers.ConceptParser( [presentation_spec]).GetInfo(presentation_spec.name) if projects is not None: self._ExpectListProjects(projects) completer = self.Completer(completers.CompleterForAttribute( resource_spec, attribute_name), args=args, handler_info=resource_info, cli=self.cli) argument = mock.MagicMock(dest=dest) parameter_info = completer.ParameterInfo(self.parsed_args, argument) completions = completer.Complete(prefix, parameter_info) self.assertEqual(expected_completions, completions)
def testCompleterForAttribute_DifferentVersions(self): collections = [ ('example.projects.shelves.books', True), ('example.projects.shelves', True), ('example.projects', True), ('example.projects.shelves.books', True, 'v1beta1'), ('example.projects.shelves', True, 'v1beta1'), ('example.projects', True, 'v1beta1')] self.MockCRUDMethods(*collections) book_collection = registry.GetAPICollection( 'example.projects.shelves.books', 'v1beta1') resource_spec = util.GetBookResource(api_version='v1beta1') expected_completer = completers.ResourceArgumentCompleter( resource_spec, book_collection, registry.GetMethod('example.projects.shelves.books', 'list', api_version='v1beta1'), param='booksId', static_params={}) completer = completers.CompleterForAttribute(self.resource_spec, 'book')() self.assertEqual(expected_completer, completer) expected_completer = completers.ResourceArgumentCompleter( resource_spec, registry.GetAPICollection('example.projects.shelves', 'v1beta1'), registry.GetMethod('example.projects.shelves', 'list', api_version='v1beta1'), param='shelvesId', static_params={}) completer = completers.CompleterForAttribute(self.resource_spec, 'shelf')() self.assertEqual(expected_completer, completer) expected_completer = completers.ResourceArgumentCompleter( self.resource_spec, registry.GetAPICollection('example.projects', 'v1beta1'), registry.GetMethod('example.projects', 'list', api_version='v1beta1'), param='projectsId', static_params={}) completer = completers.CompleterForAttribute( self.resource_spec, 'project')() self.assertEqual(expected_completer, completer)
def testAddCompleter(self): collections = [ ('example.projects.shelves.books', True), ('example.projects.shelves', True), ('cloudresourcemanager.projects', True)] self.MockCRUDMethods(*collections) info = concept_parsers.ConceptParser([self.presentation_spec]).GetInfo( self.presentation_spec.name) attribute_args = info.GetAttributeArgs() for arg, attribute_name in zip(attribute_args, ['project', 'shelf', 'book']): expected_completer = completers.CompleterForAttribute( self.resource_spec_auto_completers, attribute_name) actual_completer = arg.kwargs['completer'] self.assertEqual(expected_completer(), actual_completer())
def _KwargsForAttribute(self, name, attribute, is_anchor=False): """Constructs the kwargs for adding an attribute to argparse.""" # Argument is modal if it's the anchor, unless there are fallthroughs. # If fallthroughs can ever be configured in the ResourceInfo object, # a more robust solution will be needed, e.g. a GetFallthroughsForAttribute # method. required = is_anchor and not attribute.fallthroughs # If this is the only argument in the group, the help text should be the # "group" help. if len(list(filter(bool, self.attribute_to_args_map.values()))) == 1: help_text = self.group_help else: # Expand the help text. help_text = attribute.help_text.format( resource=self.resource_spec.name) plural = attribute == self.resource_spec.anchor and self.plural if attribute.completer: completer = attribute.completer elif not self.resource_spec.disable_auto_completers: completer = completers.CompleterForAttribute( self.resource_spec, attribute.name) else: completer = None kwargs_dict = { 'help': help_text, 'type': attribute.value_type, 'completer': completer } if util.IsPositional(name): if plural and required: kwargs_dict.update({'nargs': '+'}) # The following should not usually happen because anchor args are # required. elif plural and not required: kwargs_dict.update({'nargs': '*'}) elif not required: kwargs_dict.update({'nargs': '?'}) else: kwargs_dict.update({'metavar': util.MetavarFormat(name)}) if required: kwargs_dict.update({'required': True}) if plural: kwargs_dict.update({'type': arg_parsers.ArgList()}) return kwargs_dict
def _KwargsForAttribute(self, name, attribute, is_anchor=False): """Constructs the kwargs for adding an attribute to argparse.""" # Argument is modal if it's the anchor, unless there are fallthroughs. # If fallthroughs can ever be configured in the ResourceInfo object, # a more robust solution will be needed, e.g. a GetFallthroughsForAttribute # method. required = is_anchor and not self.fallthroughs_map.get( attribute.name, []) final_help_text = self._GetHelpTextForAttribute(attribute, is_anchor=is_anchor) plural = attribute == self.resource_spec.anchor and self.plural if attribute.completer: completer = attribute.completer elif not self.resource_spec.disable_auto_completers: completer = completers.CompleterForAttribute( self.resource_spec, attribute.name) else: completer = None kwargs_dict = { 'help': final_help_text, 'type': attribute.value_type, 'completer': completer } if util.IsPositional(name): if plural and required: kwargs_dict.update({'nargs': '+'}) # The following should not usually happen because anchor args are # required. elif plural and not required: kwargs_dict.update({'nargs': '*'}) elif not required: kwargs_dict.update({'nargs': '?'}) else: kwargs_dict.update({'metavar': util.MetavarFormat(name)}) if required: kwargs_dict.update({'required': True}) if plural: kwargs_dict.update({'type': arg_parsers.ArgList()}) return kwargs_dict