def parse(clazz, text, filename='<unknown>'): name = None unixpath = None pythonpath = None requires = None variables = [] for line in text_line_parser(text): text = line.text_no_comments.strip() if text: key, sep, value = text.partition(':') if sep != ':': raise ValueError('Invalid config line \"%s\" at %s:%s' % (line.text, filename, line.line_number)) key = key.strip() value = value.strip() if key == 'name': name = value elif key in ['unixpath']: unixpath = [path.expanduser(p) for p in value.split(':')] elif key in ['pythonpath']: pythonpath = [path.expanduser(p) for p in value.split(':')] elif key == 'requires': requires = set(string_util.split_by_white_space(value)) elif key == 'variables': variables = string_util.split_by_white_space(value) else: raise ValueError('Invalid config value \"%s\" at %s:%s' % (line.text, filename, line.line_number)) return clazz(name, unixpath, pythonpath, requires, variables)
def parse(clazz, text): if text[0] == '-': is_current = False text_without_dash = text[1:].strip() else: is_current = True text_without_dash = text.strip() parts = string_util.split_by_white_space(text_without_dash, strip=True) if len(parts) < 2: raise ValueError( 'Invalid git submodule status: "{}"'.format(text_without_dash)) revision_long = parts.pop(0) if revision_long.startswith('+'): revision_long = revision_long[1:] if len(revision_long) != 40: raise ValueError( 'Invalid git submodule revision_long: "{}"'.format( revision_long)) name = parts.pop(0) if len(parts) > 0: tag = clazz._parse_tag(parts.pop(0)) else: tag = None return git_submodule_info(name, None, revision_long, None, is_current, tag)
def _command_parse_add(clazz, section): assert section.header_.name == 'add' parts = string_util.split_by_white_space(section.header_.extra_text, strip=True) if len(parts) != 2: raise git_temp_repo_error( 'Invalid "add" section header: "{}"'.format( str(section.header_))) commit_alias = parts[0] name = parts[1] files = [] for entry in section: message = '' if entry.value.key == 'message': message = entry.value.value else: perm = 0o644 filename = entry.value.key content = entry.value.value or '' for annotation in entry.annotations or []: if annotation.key == 'perm': perm = file_mode.parse_mode(annotation.value) files.append(clazz._file(filename, perm, content)) return clazz._command_add('add', name, files, commit_alias, message)
def _command_parse_tag(clazz, section): assert section.header_.name == 'tag' parts = string_util.split_by_white_space(section.header_.extra_text, strip=True) if len(parts) < 2: raise git_temp_repo_error( 'Invalid "tag" section header: "{}"'.format( str(section.header_))) tag_name = parts.pop(0) name = parts.pop(0) from_commit = None push = True annotation = None if parts: from_commit = parts.pop(0) if parts: annotation = ''.join(parts) if section.has_key('from_commit'): from_commit = section.get_value('from_commit') if section.has_key('annotation'): annotation = section.get_value('annotation') if section.has_key('push'): push = section.get_bool('push') if not from_commit: raise git_temp_repo_error('"tag" missing "from_commit"') return clazz._command_tag('tag', name, tag_name, from_commit, annotation, push)
def _parse_line(clazz, line): parts = string_util.split_by_white_space(line, strip=True) if len(parts) != 2: raise git_error('Invalid show-ref line: "{}"'.format(line)) commit_long = parts[0] fullname = parts[1] return clazz._show_ref_item(commit_long, fullname)
def _parse_value(clazz, key, value): if key == 'flags': value = set(string_util.split_by_white_space(value, strip = True)) else: try: value = int(value) except ValueError as ex: pass return value
def _command_loop(self): try: cmd = string_util.split_by_white_space(input('CMD> '), strip=True) if cmd: return self._handle_command(cmd) except KeyboardInterrupt as ex: return False except EOFError as ex: return False return True
def parse_text(clazz, text): parts = string_util.split_by_white_space(text, strip=True) if len(parts) < 3: raise ssh_config_error( 'Invalid authorized_key entry (should have at least 3 parts): "{}"' .format(text)) key_type = parts.pop(0) key = parts.pop(0) i = text.find(key) + len(key) annotation = text[i:].strip() return ssh_authorized_key(key_type, key, annotation)
def _parse_active_branch_entry(clazz, entry): parts = string_util.split_by_white_space(entry, strip=True) if len(parts) < 4: raise git_error('Invalid active branch entry: "{}"'.format(entry)) if parts[0] != '*': raise git_error('Invalid active branch entry: "{}"'.format(entry)) branch = parts[1] commit_hash = parts[2] commit_message = entry[entry.find(commit_hash) + len(commit_hash) + 1:] return (branch, commit_hash, commit_message)
def _parse_clause(clazz, clause): check.check_string(clause) parts = string_util.split_by_white_space(clause, strip=True) if len(parts) != 2: raise ValueError(f'Invalid clause: "{clause}"') operator = parts[0] if operator not in ('<', '>', '==', '<=', '>=', '!='): raise ValueError(f'Invalid operator: "{operator}"') version = semantic_version(parts[1]) if not version.has_only_semantic_tokens: raise ValueError(f'Invalid version: "{version}"') return clazz._clause(operator, version)
def parse_branch(clazz, s, where): parts = string_util.split_by_white_space(s, strip = True) active = False if parts[0] == '*': active = True parts.pop(0) assert len(parts) >= 2 name = parts[0] commit = parts[1] comment = ' '.join(parts[2:]) ahead, behind = clazz.parse_branch_status(comment) comment = clazz.strip_branch_status(comment).strip() return git_branch(name, where, active, ahead, behind, commit, None, comment)
def parse_entry(clazz, text): check.check_string(text) parts = string_util.split_by_white_space(text, strip=True) if len(parts) < 3: raise git_error( 'Invalid git lfs entry. Should have 3 parts: "{}"'.format( text)) oid = parts.pop(0) is_pointer_flag = parts.pop(0) is_pointer = is_pointer_flag == '-' head = oid + ' ' + is_pointer_flag + ' ' filename = string_util.remove_head(text, head) return git_lfs_entry(filename, oid, is_pointer)
def parse_line(clazz, s): check.check_string(s) v = string_util.split_by_white_space(s) #print(f'v={v}') action = git_status_action.parse(v.pop(0)) filename = v.pop(0) renamed_filename = None if v: arrow = v.pop(0) if arrow == '->': assert len(v) > 0 renamed_filename = v.pop(0) return git_status(action, filename, renamed_filename)
def _command_parse_push(clazz, section): assert section.header_.name == 'push' parts = string_util.split_by_white_space(section.header_.extra_text, strip=True) if len(parts) != 2: raise git_temp_repo_error( 'Invalid "push" section header: "{}"'.format( str(section.header_))) repository = parts.pop(0) ref = parts.pop(0) upstream = None if section.has_key('upstream'): upstream = section.get_value('upstream') return clazz._command_push('push', repository, ref, upstream)
def full_version(clazz, exe): 'Return the full version of a python executable' cmd = [exe, '--version'] rv = execute.execute(cmd) stdout = rv.stdout.strip() stderr = rv.stderr.strip() output = stdout or stderr parts = string_util.split_by_white_space(output, strip=True) if len(parts) != 2: raise python_error( f'not a valid python version for {exe}: "{output}"') if parts[0] != 'Python': raise python_error( f'not a valid python name for {exe}: "{output}"') return python_version(parts[1])
def parse_city_and_state(clazz, s): ''' Parse text in the form off "City, ST" "City ST" "ST, City" "ST City" for city and state or None if the state or format cannot be determined. ''' if ',' in s: parts = s.split(',') else: parts = string_util.split_by_white_space(s) state_index = clazz._find_state_index(parts) if state_index < 0: return None state = parts[state_index].strip() parts[state_index] = '' city = ' '.join(parts).strip() return clazz._city_state(city, state)
def test_split_by_white_space(self): self.assertEqual(['a', 'b', 'c'], string_util.split_by_white_space('a b c')) self.assertEqual(['a', 'b', 'c'], string_util.split_by_white_space(' a b c')) self.assertEqual(['a', 'b', 'c'], string_util.split_by_white_space(' a b c ')) self.assertEqual(['a', 'b', 'c'], string_util.split_by_white_space(' a b c ')) self.assertEqual([], string_util.split_by_white_space('')) self.assertEqual(['a'], string_util.split_by_white_space('a'))
def _command_parse_file(clazz, section): assert section.header_.name == 'file' parts = string_util.split_by_white_space(section.header_.extra_text, strip=True) if len(parts) != 1: raise git_temp_repo_error( 'Invalid file section header: "{}"'.format(str( section.header_))) filename = parts[0] content = '' if section.has_key('content'): content = section.get_value('content') perm = 0o644 if section.has_key('perm'): perm = file_mode.parse_mode(section.get_value('perm')) f = clazz._file(filename, perm, content) return clazz._command_file('file', f)
def parse_text(clazz, text): parts = string_util.split_by_white_space(text, strip=True) if len(parts) < 3: raise ssh_config_error( 'Invalid known_hosts entry (should have at least 3 parts): "{}"' .format(text)) hostnames = parts.pop(0).split(',') key_type = parts.pop(0) key = parts.pop(0) i = text.find(key) + len(key) comment = text[i:].strip() or None if comment: if not comment.startswith('#'): raise ssh_config_error( 'Invalid known_hosts entry (extraneous text instead of comment): "{}"' .format(text)) comment = comment[1:].strip() return ssh_known_host(hostnames, key_type, key, comment=comment)
def _parse_ssh_keyscan_output(clazz, s, include_comment=True): 'Parse the output of ssh-keyscan' lines = text_line_parser.parse_lines(s, strip_comments=False, strip_text=True, remove_empties=True) if len(lines) != 2: raise ssh_config_error( 'Invalid ssh-keyscan output. Should be 2 lines:\n{}'.format( s)) comment = lines[0] if include_comment else None parts = string_util.split_by_white_space(lines[1], strip=True) if len(parts) != 3: raise ssh_config_error( 'Invalid ssh-keyscan parts. Should be 3 parts: "{}"'.format( lines[1])) hostname, key_type, key = parts return ssh_known_host([hostname], key_type, key, comment)
def _command_parse_remove(clazz, section): assert section.header_.name == 'remove' parts = string_util.split_by_white_space(section.header_.extra_text, strip=True) if len(parts) != 1: raise git_temp_repo_error( 'Invalid "remove" section header: "{}"'.format( str(section.header_))) name = parts[0] filename = None if section.has_key('filename'): filename = section.get_value('filename') if not filename: raise git_temp_repo_error('"remove" missing one of "filename"') return clazz._command_remove('remove', name, filename)
def _parse_ssh_config_entry(clazz, text, origin, validate_key_characters=True): check.check_string(text) check.check_simple_config_origin(origin) hints = {} if '=' in text: kv = key_value.parse(text) hints['delimiter'] = '=' else: parts = string_util.split_by_white_space(text, strip=True) if len(parts) < 2: raise simple_config_error( 'invalid sss config entry (not enough parts): "{}"'.format( text), origin) kv = key_value(parts.pop(0), ' '.join(parts)) hints['delimiter'] = ' ' return simple_config_entry(kv, origin=origin, hints=hints)
def _command_parse_branch(clazz, section): assert section.header_.name == 'branch' parts = string_util.split_by_white_space(section.header_.extra_text, strip=True) if len(parts) != 2: raise git_temp_repo_error( 'Invalid "branch" section header: "{}"'.format( str(section.header_))) branch_name = parts[0] name = parts[1] start_point = None push = False if section.has_key('start_point'): start_point = section.get_value('start_point') if section.has_key('push'): push = section.get_bool('push') return clazz._command_branch('branch', name, branch_name, start_point, push)
def _parse_ssh_config_entry(clazz, text, origin, options): from bes.system.check import check from bes.common.string_util import string_util from bes.key_value.key_value import key_value from bes.config.simple_config_entry import simple_config_entry check.check_string(text) check.check_simple_config_origin(origin) check.check_simple_config_options(options) hints = {} if '=' in text: kv = key_value.parse(text) hints['delimiter'] = '=' else: parts = string_util.split_by_white_space(text, strip = True) if len(parts) < 2: raise simple_config_error('invalid sss config entry (not enough parts): "{}"'.format(text), origin) kv = key_value(parts.pop(0), ' '.join(parts)) hints['delimiter'] = ' ' return simple_config_entry(kv, origin = origin, hints = hints)
def _tokenize(clazz, text): num_colon = text.count(':') if num_colon > 1: raise ValueError('Invalid text - only one colon is allowed: %s' % (text)) elif num_colon == 0: global_mask = None req_text = text else: assert num_colon == 1 left, _, right = text.partition(':') global_mask = left.strip() req_text = right.strip() last_token = None for word in string_util.split_by_white_space(req_text): if last_token: if clazz._word_is_operator(word): token = clazz._token(clazz._TOKEN_OPERATOR, word, global_mask) elif clazz._word_is_hardness(word): token = clazz._token(clazz._TOKEN_HARDNESS, word, global_mask) elif last_token.type == clazz._TOKEN_OPERATOR: token = clazz._token(clazz._TOKEN_VERSION, word, global_mask) else: token = clazz._make_name_token(word, global_mask) else: if clazz._word_is_hardness(word): token = clazz._token(clazz._TOKEN_HARDNESS, word, global_mask) else: token = clazz._make_name_token(word, global_mask) yield token last_token = token yield clazz._token(clazz._TOKEN_END, None, None)
def parse_text(clazz, text, origin): parts = string_util.split_by_white_space(text, strip=True) if len(parts) == 0: raise simple_config_error( 'Invalid config section header: "{}"'.format(text), origin) name = parts.pop(0) extends = None extra_text = None if len(parts) > 0: if parts[0] == 'extends': if len(parts) < 2: numbered_text = line_numbers.add_line_numbers(text) msg = 'extends directive missing parent: "{}"'.format( numbered_text) raise simple_config_error(msg, origin) parts.pop(0) extends = parts.pop(0) if len(parts) > 0: extra_text = ' '.join(parts) return simple_config_section_header(name, extends=extends, origin=origin, extra_text=extra_text)
def parse_list(clazz, s): 'Parse a space separated list of strings into a list of enumerations.' check.check_string(s) strings = string_util.split_by_white_space(s, strip=True) return [clazz.parse(x) for x in strings]
def get_string_list(self, key): return string_util.split_by_white_space(self.get_value(key), strip = True)
def _make_arg_pair_list(clazz, flag, items): pairs = [ '{} {}'.format(flag, item) for item in items ] flat = ' '.join(pairs) return string_util.split_by_white_space(flat)