def _GetBaseListerFrontendPrototype(args, message=None):
  """Make Frontend suitable for BaseLister argument namespace.

  Generated client-side filter is stored to args.filter. Generated server-side
  filter is None. Client-side filter should be processed using
  flags.RewriteFilter before use to take advantage of possible server-side
  filtering.

  Args:
    args: The argument namespace of BaseLister.
    message: The resource proto message.

  Returns:
    Frontend initialized with information from BaseLister argument namespace.
    Server-side filter is None.
  """
  frontend = _GetListCommandFrontendPrototype(args, message=message)
  filter_args = []
  default = args.filter  # must preserve '' and None for default processing
  if args.filter:
    filter_args.append('('+args.filter+')')
  if getattr(args, 'regexp', None):
    filter_args.append(
        '(name ~ "^{}$")'.format(resource_expr_rewrite.BackendBase()
                                 .Quote(args.regexp)))
  if getattr(args, 'names', None):
    name_regexp = ' '.join([
        resource_expr_rewrite.BackendBase().Quote(name) for name in args.names
        if not name.startswith('https://')
    ])
    selflink_regexp = ' '.join([
        resource_expr_rewrite.BackendBase().Quote(name) for name in args.names
        if name.startswith('https://')
    ])
    if not selflink_regexp:
      filter_args.append('(name =({}))'.format(name_regexp))
    elif not name_regexp:
      filter_args.append('(selfLink =({}))'.format(selflink_regexp))
    else:
      filter_args.append('((name =({})) OR (selfLink =({})))'.format(
          name_regexp, selflink_regexp))
  # Refine args.filter specification to reuse gcloud filtering logic
  # for filtering based on instance names
  args.filter = ' AND '.join(filter_args) or default

  return _Frontend(None, frontend.max_results, frontend.scope_set)
    def testResourceFilterBackendBaseRewrite(self):
        """Rewrite backend base tests -- all expressions should collapse to None."""
        def T(expected, expression, exception=None):
            self.Run(expected, expression, exception=exception, depth=2)

        self.SetBackend(resource_expr_rewrite.BackendBase())

        T((None, None), None)
        T((None, None), '')
        T(('a:3', None), 'a:3')
        T(('s:xyz', None), 's:xyz')
        T(('-a:3', None), '-a:3')
        T(('NOT a:3', None), 'NOT a:3')
        T(('x<3', None), 'x<3')
        T(('x<=3', None), 'x<=3')
        T(('x>=3', None), 'x>=3')
        T(('x>3', None), 'x>3')
        T(('x!=3', None), 'x!=3')
        T(('-x!=3', None), '-x!=3')
        T(('NOT x!=3', None), 'NOT x!=3')
        T(('s=ing', None), 's=ing')
        T(('s:S*ing', None), 's:S*ing')
        T(('s:str*', None), 's:str*')
        T(('s~[a-z]', None), 's~[a-z]')
        T(('s!~^s.*g$', None), 's!~^s.*g$')
        T(('s:"STRING"', None), 's:"STRING"')

        T(('a.b.c:"c*g"', None), 'a.b.c:"c*g"')
        T(('x:1 AND (y:2 OR z:3)', None), 'x:1 AND (y:2 OR z:3)')
        T(('NOT x:1 AND ( y:2 OR z:3 )', None), 'NOT x:1 AND ( y:2 OR z:3 )')
        T(('(x>0 OR y>0) AND z>0', None), '(x>0 OR y>0) AND z>0')
        T(('( x:1 OR y:2 ) AND ( w:3 OR z:4 )', None),
          '( x:1 OR y:2 ) AND ( w:3 OR z:4 )')
        T(('( x:1 OR y:2 ) AND ( x:3 OR z:4 )', None),
          '( x:1 OR y:2 ) AND ( x:3 OR z:4 )')

        T(('a.b.c.test_transform():1', None), 'a.b.c.test_transform():1')
        T(('a.b.c.test_transform():1 AND z:3', None),
          'a.b.c.test_transform():1 AND z:3')

        T(('a.b.c.unknown():1', None), 'a.b.c.unknown():1')
        T(('a.b.c.unknown():1 AND z:3', None), 'a.b.c.unknown():1 AND z:3')
 def SetUp(self):
     self.backend = resource_expr_rewrite.BackendBase()