diff options
Diffstat (limited to 'morphlib/cmdline_parse_utils.py')
-rw-r--r-- | morphlib/cmdline_parse_utils.py | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/morphlib/cmdline_parse_utils.py b/morphlib/cmdline_parse_utils.py new file mode 100644 index 00000000..c5e08ec1 --- /dev/null +++ b/morphlib/cmdline_parse_utils.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright © 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + + +from itertools import groupby as _groupby +from itertools import takewhile as _takewhile + +from cliapp import AppException as _AppException + + +from .utils import word_join_list as _word_join_list + + +def _split(iterable, split_token): + sequence = [] + for token in iterable: + if token == split_token: + yield tuple(sequence) + sequence = [] + else: + sequence.append(token) + if sequence: + yield tuple(sequence) + + +class SystemsSpecsParseWrongNumber(_AppException): + def __init__(self, specs, definitions_names): + self.specs = specs + self.definitions_names = definitions_names + msg = 'From expected definition specs {expected};'.format( + expected=_word_join_list(map(repr, definitions_names))) + if len(specs) < len(definitions_names): + missing_spec_names = definitions_names[len(specs):] + super(SystemsSpecsParseWrongNumber, self).__init__( + '{msg} missing {missing}'.format( + msg=msg, + missing=_word_join_list(map(repr, missing_spec_names)))) + else: + super(SystemsSpecsParseWrongNumber, self).__init__( + '{msg} {extra} extra specs given'.format( + msg=msg, + extra=len(specs) - len(definitions_names))) + + +class SystemsSpecsParseWrongFormat(_AppException): + def __init__(self, definition_list_name_list, malformed_definition_lists): + self.definition_list_name_list = definition_list_name_list + self.malformed_definition_lists = malformed_definition_lists + errors = [] + for spec, name, i in malformed_definition_lists: + pre = 'Spec {i} named {name!r}'.format(i=i, name=name) + if not spec: + errors.append(pre + ' is empty, want REPO REF SYSTEM...') + elif len(spec) == 1: + errors.append(pre + ' missing REF, want REPO REF SYSTEM...') + super(SystemsSpecsParseWrongFormat, self).__init__( + 'From expected definition specs {expected}:\n\t{errors}'.format( + expected=_word_join_list(map(repr, definition_list_name_list)), + errors='\n\t'.join(errors))) + + +def parse_definition_lists(definition_list_name_list, args): + specs = tuple(_split(args, '-')) + if len(specs) != len(definition_list_name_list): + raise SystemsSpecsParseWrongNumber(specs, definition_list_name_list) + + malformed_definition_lists = [] + specinfo = enumerate(zip(definition_list_name_list, specs), start=1) + for i, (definition_list_name, definitions_spec) in specinfo: + if len(definitions_spec) < 2: + malformed_definition_lists.append( + (definitions_spec, definition_list_name, i)) + if malformed_definition_lists: + raise SystemsSpecsParseWrongFormat(definition_list_name_list, + malformed_definition_lists) + + return ((spec[0], spec[1], spec[2:]) for spec in specs) |