OLD | NEW |
---|---|
1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 30 matching lines...) Expand all Loading... | |
41 # with which to validate arguments against known names. | 41 # with which to validate arguments against known names. |
42 # Sequence types as default values will produce sequences | 42 # Sequence types as default values will produce sequences |
43 # as parse results. | 43 # as parse results. |
44 # Bare arguments (no '=') are treated as names with value True. | 44 # Bare arguments (no '=') are treated as names with value True. |
45 # The first field will always be labeled 'name'. | 45 # The first field will always be labeled 'name'. |
46 # | 46 # |
47 # InFile.load_from_path('file.in', {'arg': None, 'arg2': []}) | 47 # InFile.load_from_path('file.in', {'arg': None, 'arg2': []}) |
48 # | 48 # |
49 # Parsing produces an array of dictionaries: | 49 # Parsing produces an array of dictionaries: |
50 # [ { 'name' : 'name1', 'arg' :' value', arg2=['value2', 'value3'] } | 50 # [ { 'name' : 'name1', 'arg' :' value', arg2=['value2', 'value3'] } |
51 | |
52 def _is_comment(line): | |
53 return line.startswith("//") or line.startswith("#") | |
54 | |
51 class InFile(object): | 55 class InFile(object): |
52 def __init__(self, lines, defaults): | 56 def __init__(self, lines, defaults, default_parameters): |
53 lines = map(str.strip, lines) | 57 self.name_dictionaries = [] |
54 lines = filter(lambda line: line and not line.startswith("//"), lines) | 58 self.parameters = copy.deepcopy(default_parameters if default_parameters else {}) |
55 self.name_dictionaries = [self._parse_line(line, defaults) for line in l ines] | 59 self._defaults = defaults |
60 self._parse(map(str.strip, lines)) | |
56 | 61 |
57 @classmethod | 62 @classmethod |
58 def load_from_path(self, path, defaults): | 63 def load_from_path(self, path, defaults, default_parameters): |
59 with open(os.path.abspath(path)) as in_file: | 64 with open(os.path.abspath(path)) as in_file: |
60 return InFile(in_file.readlines(), defaults) | 65 return InFile(in_file.readlines(), defaults, default_parameters) |
61 | 66 |
62 def _is_sequence(self, arg): | 67 def _is_sequence(self, arg): |
63 return (not hasattr(arg, "strip") | 68 return (not hasattr(arg, "strip") |
64 and hasattr(arg, "__getitem__") | 69 and hasattr(arg, "__getitem__") |
65 or hasattr(arg, "__iter__")) | 70 or hasattr(arg, "__iter__")) |
66 | 71 |
67 def _parse_line(self, line, defaults): | 72 def _parse(self, lines): |
68 args = copy.deepcopy(defaults) | 73 parsing_parameters = True |
74 for line in lines: | |
75 if _is_comment(line): | |
76 continue | |
77 if not line: | |
eseidel
2013/04/30 21:46:16
So a leading newline (between the comments and the
abarth-chromium
2013/04/30 21:50:44
I'm just matching the behavior of the Perl "in" fi
| |
78 parsing_parameters = False | |
79 continue | |
80 if parsing_parameters: | |
81 self._parse_parameter(line) | |
82 else: | |
83 self.name_dictionaries.append(self._parse_line(line)) | |
84 | |
85 def _parse_parameter(self, line): | |
86 if '=' in line: | |
87 name, value = line.split('=') | |
88 else: | |
89 name, value = line, True | |
eseidel
2013/04/30 21:46:16
If we don't support bare parameters, then paramete
abarth-chromium
2013/04/30 21:50:44
The Perl supports parameters that lack a =. I don
| |
90 if not name in self.parameters: | |
91 self._fatal("Unknown parameter: '%s' in line:\n%s\nKnown parameters: %s" % (name, line, self.parameters.keys())) | |
92 self.parameters[name] = value | |
93 | |
94 def _parse_line(self, line): | |
95 args = copy.deepcopy(self._defaults) | |
69 parts = line.split(' ') | 96 parts = line.split(' ') |
70 args['name'] = parts[0] | 97 args['name'] = parts[0] |
71 # re-join the rest of the line and split on ',' | 98 # re-join the rest of the line and split on ',' |
72 args_list = ' '.join(parts[1:]).strip().split(',') | 99 args_list = ' '.join(parts[1:]).strip().split(',') |
73 for arg_string in args_list: | 100 for arg_string in args_list: |
74 arg_string = arg_string.strip() | 101 arg_string = arg_string.strip() |
75 if not arg_string: # Ignore empty args | 102 if not arg_string: # Ignore empty args |
76 continue | 103 continue |
77 if '=' in arg_string: | 104 if '=' in arg_string: |
78 arg_name, arg_value = arg_string.split('=') | 105 arg_name, arg_value = arg_string.split('=') |
79 else: | 106 else: |
80 arg_name, arg_value = arg_string, True | 107 arg_name, arg_value = arg_string, True |
81 if arg_name not in defaults: | 108 if arg_name not in self._defaults: |
82 # FIXME: This should probably raise instead of exit(1) | 109 self._fatal("Unknown argument: '%s' in line:\n%s\nKnown argument s: %s" % (arg_name, line, self._defaults.keys())) |
83 print "Unknown argument: '%s' in line:\n%s\nKnown arguments: %s" % (arg_name, line, defaults.keys()) | |
84 exit(1) | |
85 if self._is_sequence(args[arg_name]): | 110 if self._is_sequence(args[arg_name]): |
86 args[arg_name].append(arg_value) | 111 args[arg_name].append(arg_value) |
87 else: | 112 else: |
88 args[arg_name] = arg_value | 113 args[arg_name] = arg_value |
89 return args | 114 return args |
115 | |
116 def _fatal(self, message): | |
117 # FIXME: This should probably raise instead of exit(1) | |
118 print message | |
119 exit(1) | |
OLD | NEW |