def Modify(self, args, existing): """Returns a modified URL map message.""" replacement = self._ModifyBase(args, existing) # Creates PathRule objects from --path-rules, --backend-service-path-rules, # and --backend-bucket-path-rules. service_map = collections.defaultdict(set) bucket_map = collections.defaultdict(set) for path, service in args.path_rules.iteritems(): service_map[service].add(path) for path, service in args.backend_service_path_rules.iteritems(): service_map[service].add(path) for path, bucket in args.backend_bucket_path_rules.iteritems(): bucket_map[bucket].add(path) path_rules = [] for service, paths in sorted(service_map.iteritems()): path_rules.append( self.messages.PathRule( paths=sorted(paths), service=self.CreateGlobalReference(service, resource_type="backendServices").SelfLink(), ) ) for bucket, paths in sorted(bucket_map.iteritems()): path_rules.append( self.messages.PathRule( paths=sorted(paths), service=self.CreateGlobalReference(bucket, resource_type="backendBuckets").SelfLink(), ) ) if args.default_service: default_backend_uri = self.CreateGlobalReference( args.default_service, resource_type="backendServices" ).SelfLink() else: default_backend_uri = self.CreateGlobalReference( args.default_backend_bucket, resource_type="backendBuckets" ).SelfLink() new_path_matcher = self.messages.PathMatcher( defaultService=default_backend_uri, description=args.description, name=args.path_matcher_name, pathRules=path_rules, ) replacement.pathMatchers.append(new_path_matcher) return replacement
def Modify(self, args, existing): """Returns a modified URL map message.""" replacement = self._ModifyBase(args, existing) # Creates PathRule objects from --path-rules. service_map = collections.defaultdict(set) for path, service in args.path_rules.iteritems(): service_map[service].add(path) path_rules = [] for service, paths in sorted(service_map.iteritems()): path_rules.append( self.messages.PathRule( paths=sorted(paths), service=self.CreateGlobalReference( service, resource_type='backendServices').SelfLink())) new_path_matcher = self.messages.PathMatcher( defaultService=self.CreateGlobalReference( args.default_service, resource_type='backendServices').SelfLink(), description=args.description, name=args.path_matcher_name, pathRules=path_rules) replacement.pathMatchers.append(new_path_matcher) return replacement
def CreateServiceAccountMessages(messages, scopes): """Returns a list of ServiceAccount messages corresponding to scopes.""" if scopes is None: scopes = constants.DEFAULT_SCOPES accounts_to_scopes = collections.defaultdict(list) for scope in scopes: parts = scope.split('=') if len(parts) == 1: account = 'default' scope_uri = scope elif len(parts) == 2: account, scope_uri = parts else: raise exceptions.ToolException( '[{0}] is an illegal value for [--scopes]. Values must be of the ' 'form [SCOPE] or [ACCOUNT=SCOPE].'.format(scope)) # Expands the scope if the user provided an alias like # "compute-rw". scope_uri = constants.SCOPES.get(scope_uri, scope_uri) accounts_to_scopes[account].append(scope_uri) res = [] for account, scopes in sorted(accounts_to_scopes.iteritems()): res.append(messages.ServiceAccount(email=account, scopes=sorted(scopes))) return res
def CreateServiceAccountMessages(self, args): """Returns a list of ServiceAccount messages corresponding to --scopes.""" if args.no_scopes: scopes = [] else: scopes = args.scopes or constants.DEFAULT_SCOPES accounts_to_scopes = collections.defaultdict(list) for scope in scopes: parts = scope.split('=') if len(parts) == 1: account = 'default' scope_uri = scope elif len(parts) == 2: account, scope_uri = parts else: raise exceptions.ToolException( '[{0}] is an illegal value for [--scopes]. Values must be of the ' 'form [SCOPE] or [ACCOUNT=SCOPE].'.format(scope)) # Expands the scope if the user provided an alias like # "compute-rw". scope_uri = constants.SCOPES.get(scope_uri, scope_uri) accounts_to_scopes[account].append(scope_uri) res = [] for account, scopes in sorted(accounts_to_scopes.iteritems()): res.append( self.messages.ServiceAccount(email=account, scopes=sorted(scopes))) return res
def Modify(self, args, existing): """Returns a modified URL map message.""" replacement = self._ModifyBase(args, existing) # Creates PathRule objects from --path-rules, --backend-service-path-rules, # and --backend-bucket-path-rules. service_map = collections.defaultdict(set) bucket_map = collections.defaultdict(set) for path, service in args.path_rules.iteritems(): service_map[service].add(path) for path, service in args.backend_service_path_rules.iteritems(): service_map[service].add(path) for path, bucket in args.backend_bucket_path_rules.iteritems(): bucket_map[bucket].add(path) path_rules = [] for service, paths in sorted(service_map.iteritems()): path_rules.append( self.messages.PathRule( paths=sorted(paths), service=self.resources.Parse( service, collection='compute.backendServices').SelfLink())) for bucket, paths in sorted(bucket_map.iteritems()): path_rules.append( self.messages.PathRule( paths=sorted(paths), service=self.resources.Parse( bucket, collection='compute.backendBuckets').SelfLink())) if args.default_service: default_backend_uri = self.BACKEND_SERVICE_ARG.ResolveAsResource( args, self.resources).SelfLink() else: default_backend_uri = self.BACKEND_BUCKET_ARG.ResolveAsResource( args, self.resources).SelfLink() new_path_matcher = self.messages.PathMatcher( defaultService=default_backend_uri, description=args.description, name=args.path_matcher_name, pathRules=path_rules) replacement.pathMatchers.append(new_path_matcher) return replacement
def __init__(self, parsers_by_collection=None, parsers_by_url=None, default_param_funcs=None, registered_apis=None): self.parsers_by_collection = parsers_by_collection or {} self.parsers_by_url = parsers_by_url or {} self.default_param_funcs = default_param_funcs or {} self.registered_apis = registered_apis or collections.defaultdict(set)
def MonitorTestMatrixProgress(self): """Monitor and report the progress of multiple running tests in a matrix.""" while True: matrix = self.GetTestMatrixStatus() state_counts = collections.defaultdict(int) for test in matrix.testExecutions: state_counts[test.state] += 1 self._UpdateMatrixStatus(state_counts) if matrix.state in self.completed_matrix_states: self._LogTestComplete(matrix.state) break self._SleepForStatusInterval()
def MonitorTestMatrixProgress(self): """Monitor and report the progress of multiple running tests in a matrix.""" while True: matrix = self.GetTestMatrixStatus() state_counts = collections.defaultdict(int) for test in matrix.testExecutions: state_counts[test.state] += 1 self._UpdateMatrixStatus(state_counts) if matrix.state in self.completed_matrix_states: self._LogTestComplete(matrix.state) break self._SleepForStatusInterval()
def CreateServiceAccountMessages(self, args): """Returns a list of ServiceAccount messages corresponding to --scopes. Args: args: the argparse arguments that this command was invoked with. Returns: res: a list of ServiceAccount message objects Raises: ToolException: if the scopes are provided in an invalid format. """ if args.no_scopes: scopes = [] else: scopes = args.scopes or constants.DEFAULT_SCOPES accounts_to_scopes = collections.defaultdict(list) for scope in scopes: parts = scope.split('=') if len(parts) == 1: account = 'default' scope_uri = scope elif len(parts) == 2: account, scope_uri = parts else: raise exceptions.ToolException( '[{0}] is an illegal value for [--scopes]. Values must be of the ' 'form [SCOPE] or [ACCOUNT=SCOPE].'.format(scope)) # Expands the scope if the user provided an alias like # "compute-rw". scope_uri = constants.SCOPES.get(scope_uri, scope_uri) accounts_to_scopes[account].append(scope_uri) res = [] for account, scopes in sorted(accounts_to_scopes.iteritems()): res.append(self.messages.ServiceAccount( email=account, scopes=sorted(scopes))) return res
def Modify(self, args, existing): """Returns a modified URL map message.""" replacement = self._ModifyBase(args, existing) # Creates PathRule objects from --path-rules. service_map = collections.defaultdict(set) for path, service in args.path_rules.iteritems(): service_map[service].add(path) path_rules = [] for service, paths in sorted(service_map.iteritems()): path_rules.append(self.messages.PathRule( paths=sorted(paths), service=self.CreateGlobalReference( service, resource_type='backendServices').SelfLink())) new_path_matcher = self.messages.PathMatcher( defaultService=self.CreateGlobalReference( args.default_service, resource_type='backendServices').SelfLink(), description=args.description, name=args.path_matcher_name, pathRules=path_rules) replacement.pathMatchers.append(new_path_matcher) return replacement
def _PrintSynopsisSection(self): """Prints the command line synopsis section.""" # MARKDOWN_CODE is the default SYNOPSIS font style. code = usage_text.MARKDOWN_CODE em = usage_text.MARKDOWN_ITALIC self._Section('SYNOPSIS') self._out('{code}{command}{code}'.format(code=code, command=self._command_name)) # Output the positional args up to the first REMAINDER or '-- *' args. The # rest will be picked up after the flag args are output. argparse does not # have an explicit '--' arg intercept, so we use the metavar value as a '--' # sentinel. # Any SUPPRESSed args are ingnored by a pre-pass. positional_args = FilterOutSuppressed(self._command.ai.positional_args[:]) while positional_args: arg = positional_args[0] if arg.nargs == argparse.REMAINDER or arg.metavar.startswith('-- '): break positional_args.pop(0) self._out(usage_text.PositionalDisplayString(arg, markdown=True)) if self._subcommands and self._subgroups: self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em) elif self._subcommands: self._out(' ' + em + 'COMMAND' + em) elif self._subgroups: self._out(' ' + em + 'GROUP' + em) # Place all flags into a dict. Flags that are in a mutually # exclusive group are mapped group_id -> [flags]. All other flags # are mapped dest -> [flag]. global_flags = False groups = collections.defaultdict(list) for flag in (self._command.ai.flag_args + self._command.ai.ancestor_flag_args): if flag.is_global and not self._is_top_element: global_flags = True else: group_id = self._command.ai.mutex_groups.get(flag.dest, flag.dest) groups[group_id].append(flag) # Split the groups dict into required, common, and then the rest of the # flags. A group is required if any flag in it is required and common if # any flag in it is common. Required takes precedence over common. required_groups = {} common_groups = {} for group_id, flags in groups.iteritems(): for f in flags: if f.required: required_groups[group_id] = flags break elif f.is_common: common_groups[group_id] = flags break for g in required_groups: del groups[g] for g in common_groups: del groups[g] # Generate the flag usage string with required flags first, then common # flags, then the rest of the flags. for section in [required_groups, common_groups, groups]: for group in sorted(section.values(), key=lambda g: g[0].option_strings): if len(group) == 1: arg = group[0] if self._IsSuppressed(arg): continue msg = usage_text.FlagDisplayString(arg, markdown=True) if not msg: continue if arg.required: self._out(' {msg}'.format(msg=msg)) else: self._out(' [{msg}]'.format(msg=msg)) else: group.sort(key=lambda f: f.option_strings) group = [flag for flag in group if not self._IsSuppressed(flag)] msg = ' | '.join(usage_text.FlagDisplayString(arg, markdown=True) for arg in group) if not msg: continue self._out(' [{msg}]'.format(msg=msg)) if global_flags: self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']') # positional_args will only be non-empty if we had -- ... or REMAINDER left. for arg in FilterOutSuppressed(positional_args): self._out(usage_text.PositionalDisplayString(arg, markdown=True))
def _PrintSynopsisSection(self): """Prints the command line synopsis section.""" # MARKDOWN_CODE is the default SYNOPSIS font style. code = base.MARKDOWN_CODE em = base.MARKDOWN_ITALIC self._Section('SYNOPSIS') self._out('{code}{command}{code}'.format(code=code, command=self._command_name)) # Output the positional args up to the first REMAINDER or '-- *' args. The # rest will be picked up after the flag args are output. argparse does not # have an explicit '--' arg intercept, so we use the metavar value as a '--' # sentinel. Any suppressed args are ingnored by a pre-pass. positional_args = usage_text.FilterOutSuppressed( self._command.ai.positional_args) while positional_args: arg = positional_args[0] if arg.nargs == argparse.REMAINDER or arg.metavar.startswith('-- '): break positional_args.pop(0) self._out(usage_text.PositionalDisplayString(arg, markdown=True)) if self._subcommands and self._subgroups: self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em) elif self._subcommands: self._out(' ' + em + 'COMMAND' + em) elif self._subgroups: self._out(' ' + em + 'GROUP' + em) # Place all flags into a dict. Flags that are in a mutually # exclusive group are mapped group_id -> [flags]. All other flags # are mapped dest -> [flag]. global_flags = False groups = collections.defaultdict(list) for flag in (self._command.ai.flag_args + self._command.ai.ancestor_flag_args): if flag.is_global and not self._is_top_element: global_flags = True else: group_id = self._command.ai.mutex_groups.get(flag.dest, flag.dest) groups[group_id].append(flag) # Partition the non-GLOBAL flag groups dict into categorized sections. A # group is REQUIRED if any flag in it is required, categorized if any flag # in it is categorized, otherwise its OTHER. REQUIRED takes precedence # over categorized. categorized_groups = {} for group_id, flags in groups.iteritems(): for f in flags: if f.required: category = 'REQUIRED' elif f.category: category = f.category else: continue if category not in categorized_groups: categorized_groups[category] = {} categorized_groups[category][group_id] = flags break # Delete the categorized groups to get OTHER. for v in categorized_groups.values(): for g in v: del groups[g] category = 'OTHER' if category not in categorized_groups: categorized_groups[category] = {} for group_id, flags in groups.iteritems(): categorized_groups[category][group_id] = flags # Collect the sections in order: REQUIRED, COMMON, OTHER, and categorized. sections = [] for category in ('REQUIRED', base.COMMONLY_USED_FLAGS, 'OTHER'): if category in categorized_groups: sections.append(categorized_groups[category]) del categorized_groups[category] for _, v in sorted(categorized_groups.iteritems()): sections.append(v) # Generate the flag usage string with flags in section order. for section in sections: for group in sorted(section.values(), key=lambda g: g[0].option_strings): if len(group) == 1: arg = group[0] if usage_text.IsSuppressed(arg): continue msg = usage_text.FlagDisplayString(arg, markdown=True) if not msg: continue if arg.required: self._out(' {msg}'.format(msg=msg)) else: self._out(' [{msg}]'.format(msg=msg)) else: # Check if the inverted boolean name should be displayed. inverted = None if len(group) == 2: for arg in group: if getattr(arg, 'show_inverted', False): inverted = arg break if inverted: # The inverted arg replaces the boolean group which only contains # the arg and inverted arg. msg = usage_text.FlagDisplayString(inverted, markdown=True) else: group = usage_text.FilterOutSuppressed(group) group.sort(key=lambda f: f.option_strings) msg = ' | '.join(usage_text.FlagDisplayString(arg, markdown=True) for arg in group) if not msg: continue self._out(' [{msg}]'.format(msg=msg)) if global_flags: self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']') # positional_args will only be non-empty if we had -- ... or REMAINDER left. for arg in usage_text.FilterOutSuppressed(positional_args): self._out(usage_text.PositionalDisplayString(arg, markdown=True))
def Clear(self): self.parsers_by_collection = {} self.parsers_by_url = {} self.default_param_funcs = {} self.registered_apis = collections.defaultdict(list)
def Modify(self, args, existing): """Returns a modified URL map message.""" replacement = copy.deepcopy(existing) if not args.new_hosts and not args.existing_host: new_hosts = ['*'] else: new_hosts = args.new_hosts # If --new-hosts is given, we check to make sure none of those # hosts already exist and once the check succeeds, we create the # new host rule. if new_hosts: new_hosts = set(new_hosts) for host_rule in existing.hostRules: for host in host_rule.hosts: if host in new_hosts: raise exceptions.ToolException( 'Cannot create a new host rule with host [{0}] because the ' 'host is already part of a host rule that references the path ' 'matcher [{1}].'.format(host, host_rule.pathMatcher)) replacement.hostRules.append( self.messages.HostRule(hosts=sorted(new_hosts), pathMatcher=args.path_matcher_name)) # If --existing-host is given, we check to make sure that the # corresponding host rule will not render a patch matcher # orphan. If the check succeeds, we change the path matcher of the # host rule. If the check fails, we remove the path matcher if # --delete-orphaned-path-matcher is given otherwise we fail. else: target_host_rule = None for host_rule in existing.hostRules: for host in host_rule.hosts: if host == args.existing_host: target_host_rule = host_rule break if target_host_rule: break if not target_host_rule: raise exceptions.ToolException( 'No host rule with host [{0}] exists. Check your spelling or ' 'use [--new-hosts] to create a new host rule.'.format( args.existing_host)) path_matcher_orphaned = True for host_rule in replacement.hostRules: if host_rule == target_host_rule: host_rule.pathMatcher = args.path_matcher_name continue if host_rule.pathMatcher == target_host_rule.pathMatcher: path_matcher_orphaned = False break if path_matcher_orphaned: # A path matcher will be orphaned, so now we determine whether # we should delete the path matcher or report an error. if args.delete_orphaned_path_matcher: replacement.pathMatchers = [ path_matcher for path_matcher in existing.pathMatchers if path_matcher.name != target_host_rule.pathMatcher ] else: raise exceptions.ToolException( 'This operation will orphan the path matcher [{0}]. To ' 'delete the orphan path matcher, rerun this command with ' '[--delete-orphaned-path-matcher] or use [gcloud compute ' 'url-maps edit] to modify the URL map by hand.'.format( host_rule.pathMatcher)) # Creates PathRule objects from --path-rules. service_map = collections.defaultdict(set) for path, service in args.path_rules.iteritems(): service_map[service].add(path) path_rules = [] for service, paths in sorted(service_map.iteritems()): path_rules.append( self.messages.PathRule( paths=sorted(paths), service=self.CreateGlobalReference( service, resource_type='backendServices').SelfLink())) new_path_matcher = self.messages.PathMatcher( defaultService=self.CreateGlobalReference( args.default_service, resource_type='backendServices').SelfLink(), description=args.description, name=args.path_matcher_name, pathRules=path_rules) replacement.pathMatchers.append(new_path_matcher) return replacement
def _PrintSynopsisSection(self): """Prints the command line synopsis section.""" # MARKDOWN_CODE is the default SYNOPSIS font style. code = base.MARKDOWN_CODE em = base.MARKDOWN_ITALIC self._Section('SYNOPSIS') self._out('{code}{command}{code}'.format(code=code, command=self._command_name)) # Output the positional args up to the first REMAINDER or '-- *' args. The # rest will be picked up after the flag args are output. argparse does not # have an explicit '--' arg intercept, so we use the metavar value as a '--' # sentinel. Any suppressed args are ingnored by a pre-pass. positional_args = usage_text.FilterOutSuppressed( self._command.ai.positional_args) while positional_args: arg = positional_args[0] if arg.nargs == argparse.REMAINDER or arg.metavar.startswith( '-- '): break positional_args.pop(0) self._out(usage_text.PositionalDisplayString(arg, markdown=True)) if self._subcommands and self._subgroups: self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em) elif self._subcommands: self._out(' ' + em + 'COMMAND' + em) elif self._subgroups: self._out(' ' + em + 'GROUP' + em) # Place all flags into a dict. Flags that are in a mutually # exclusive group are mapped group_id -> [flags]. All other flags # are mapped dest -> [flag]. global_flags = False groups = collections.defaultdict(list) for flag in (self._command.ai.flag_args + self._command.ai.ancestor_flag_args): if flag.is_global and not self._is_top_element: global_flags = True else: group_id = self._command.ai.mutex_groups.get( flag.dest, flag.dest) groups[group_id].append(flag) # Partition the non-GLOBAL flag groups dict into categorized sections. A # group is REQUIRED if any flag in it is required, categorized if any flag # in it is categorized, otherwise its OTHER. REQUIRED takes precedence # over categorized. categorized_groups = {} for group_id, flags in groups.iteritems(): for f in flags: if f.required: category = 'REQUIRED' elif f.category: category = f.category else: continue if category not in categorized_groups: categorized_groups[category] = {} categorized_groups[category][group_id] = flags break # Delete the categorized groups to get OTHER. for v in categorized_groups.values(): for g in v: del groups[g] category = 'OTHER' if category not in categorized_groups: categorized_groups[category] = {} for group_id, flags in groups.iteritems(): categorized_groups[category][group_id] = flags # Collect the sections in order: REQUIRED, COMMON, OTHER, and categorized. sections = [] for category in ('REQUIRED', base.COMMONLY_USED_FLAGS, 'OTHER'): if category in categorized_groups: sections.append(categorized_groups[category]) del categorized_groups[category] for _, v in sorted(categorized_groups.iteritems()): sections.append(v) # Generate the flag usage string with flags in section order. for section in sections: for group in sorted(section.values(), key=lambda g: g[0].option_strings): if len(group) == 1: arg = group[0] if usage_text.IsSuppressed(arg): continue msg = usage_text.FlagDisplayString(arg, markdown=True) if not msg: continue if arg.required: self._out(' {msg}'.format(msg=msg)) else: self._out(' [{msg}]'.format(msg=msg)) else: # Check if the inverted boolean name should be displayed. inverted = None if len(group) == 2: for arg in group: if getattr(arg, 'show_inverted', False): inverted = arg break if inverted: # The inverted arg replaces the boolean group which only contains # the arg and inverted arg. msg = usage_text.FlagDisplayString(inverted, markdown=True) else: group = usage_text.FilterOutSuppressed(group) group.sort(key=lambda f: f.option_strings) msg = ' | '.join( usage_text.FlagDisplayString(arg, markdown=True) for arg in group) if not msg: continue self._out(' [{msg}]'.format(msg=msg)) if global_flags: self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']') # positional_args will only be non-empty if we had -- ... or REMAINDER left. for arg in usage_text.FilterOutSuppressed(positional_args): self._out(usage_text.PositionalDisplayString(arg, markdown=True)) self._out('\n')
def __init__(self, parsers_by_collection=None, parsers_by_url=None, default_param_funcs=None, registered_apis=None): self.parsers_by_collection = parsers_by_collection or {} self.parsers_by_url = parsers_by_url or {} self.default_param_funcs = default_param_funcs or {} self.registered_apis = registered_apis or collections.defaultdict(set)
def Modify(self, args, existing): """Returns a modified URL map message.""" replacement = copy.deepcopy(existing) if not args.new_hosts and not args.existing_host: new_hosts = ['*'] else: new_hosts = args.new_hosts # If --new-hosts is given, we check to make sure none of those # hosts already exist and once the check succeeds, we create the # new host rule. if new_hosts: new_hosts = set(new_hosts) for host_rule in existing.hostRules: for host in host_rule.hosts: if host in new_hosts: raise exceptions.ToolException( 'Cannot create a new host rule with host [{0}] because the ' 'host is already part of a host rule that references the path ' 'matcher [{1}].'.format(host, host_rule.pathMatcher)) replacement.hostRules.append(self.messages.HostRule( hosts=sorted(new_hosts), pathMatcher=args.path_matcher_name)) # If --existing-host is given, we check to make sure that the # corresponding host rule will not render a patch matcher # orphan. If the check succeeds, we change the path matcher of the # host rule. If the check fails, we remove the path matcher if # --delete-orphaned-path-matcher is given otherwise we fail. else: target_host_rule = None for host_rule in existing.hostRules: for host in host_rule.hosts: if host == args.existing_host: target_host_rule = host_rule break if target_host_rule: break if not target_host_rule: raise exceptions.ToolException( 'No host rule with host [{0}] exists. Check your spelling or ' 'use [--new-hosts] to create a new host rule.' .format(args.existing_host)) path_matcher_orphaned = True for host_rule in replacement.hostRules: if host_rule == target_host_rule: host_rule.pathMatcher = args.path_matcher_name continue if host_rule.pathMatcher == target_host_rule.pathMatcher: path_matcher_orphaned = False break if path_matcher_orphaned: # A path matcher will be orphaned, so now we determine whether # we should delete the path matcher or report an error. if args.delete_orphaned_path_matcher: replacement.pathMatchers = [ path_matcher for path_matcher in existing.pathMatchers if path_matcher.name != target_host_rule.pathMatcher] else: raise exceptions.ToolException( 'This operation will orphan the path matcher [{0}]. To ' 'delete the orphan path matcher, rerun this command with ' '[--delete-orphaned-path-matcher] or use [gcloud compute ' 'url-maps edit] to modify the URL map by hand.'.format( host_rule.pathMatcher)) # Creates PathRule objects from --path-rules. service_map = collections.defaultdict(set) for path, service in args.path_rules.iteritems(): service_map[service].add(path) path_rules = [] for service, paths in sorted(service_map.iteritems()): path_rules.append(self.messages.PathRule( paths=sorted(paths), service=self.CreateGlobalReference( service, resource_type='backendServices').SelfLink())) new_path_matcher = self.messages.PathMatcher( defaultService=self.CreateGlobalReference( args.default_service, resource_type='backendServices').SelfLink(), description=args.description, name=args.path_matcher_name, pathRules=path_rules) replacement.pathMatchers.append(new_path_matcher) return replacement
def Clear(self): self.parsers_by_collection = {} self.parsers_by_url = {} self.default_param_funcs = {} self.registered_apis = collections.defaultdict(list)
def _PrintSynopsisSection(self): """Prints the command line synopsis section.""" # MARKDOWN_CODE is the default SYNOPSIS font style. code = usage_text.MARKDOWN_CODE em = usage_text.MARKDOWN_ITALIC self._Section('SYNOPSIS') self._out('{code}{command}{code}'.format(code=code, command=self._command_name)) # Output the positional args up to the first REMAINDER or '-- *' args. The # rest will be picked up after the flag args are output. argparse does not # have an explicit '--' arg intercept, so we use the metavar value as a '--' # sentinel. # Any SUPPRESSed args are ingnored by a pre-pass. positional_args = FilterOutSuppressed( self._command.ai.positional_args[:]) while positional_args: arg = positional_args[0] if arg.nargs == argparse.REMAINDER or arg.metavar.startswith( '-- '): break positional_args.pop(0) self._out(usage_text.PositionalDisplayString(arg, markdown=True)) if self._subcommands and self._subgroups: self._out(' ' + em + 'GROUP' + em + ' | ' + em + 'COMMAND' + em) elif self._subcommands: self._out(' ' + em + 'COMMAND' + em) elif self._subgroups: self._out(' ' + em + 'GROUP' + em) # Place all flags into a dict. Flags that are in a mutually # exclusive group are mapped group_id -> [flags]. All other flags # are mapped dest -> [flag]. global_flags = False groups = collections.defaultdict(list) for flag in (self._command.ai.flag_args + self._command.ai.ancestor_flag_args): if flag.is_global and not self._is_top_element: global_flags = True else: group_id = self._command.ai.mutex_groups.get( flag.dest, flag.dest) groups[group_id].append(flag) # Split the groups dict into required, common, and then the rest of the # flags. A group is required if any flag in it is required and common if # any flag in it is common. Required takes precedence over common. required_groups = {} common_groups = {} for group_id, flags in groups.iteritems(): for f in flags: if f.required: required_groups[group_id] = flags break elif f.is_common: common_groups[group_id] = flags break for g in required_groups: del groups[g] for g in common_groups: del groups[g] # Generate the flag usage string with required flags first, then common # flags, then the rest of the flags. for section in [required_groups, common_groups, groups]: for group in sorted(section.values(), key=lambda g: g[0].option_strings): if len(group) == 1: arg = group[0] if self._IsSuppressed(arg): continue msg = usage_text.FlagDisplayString(arg, markdown=True) if not msg: continue if arg.required: self._out(' {msg}'.format(msg=msg)) else: self._out(' [{msg}]'.format(msg=msg)) else: group.sort(key=lambda f: f.option_strings) group = [ flag for flag in group if not self._IsSuppressed(flag) ] msg = ' | '.join( usage_text.FlagDisplayString(arg, markdown=True) for arg in group) if not msg: continue self._out(' [{msg}]'.format(msg=msg)) if global_flags: self._out(' [' + em + 'GLOBAL-FLAG ...' + em + ']') # positional_args will only be non-empty if we had -- ... or REMAINDER left. for arg in FilterOutSuppressed(positional_args): self._out(usage_text.PositionalDisplayString(arg, markdown=True))