def _from_json(self, d: list, exact=True): if not isinstance(d, list): raise PlaintextParseError from TypeError('expected list, got ' + type(d).__name__) if exact and len(d) != len(self.inners): raise PlaintextParseError( f'value number mismatch (expected {len(self.inners)}, got {len(d)})' ) ret = [] for s, v in zip(self.inners, d): if not isinstance(v, str): raise PlaintextParseError( f'in {s.title}:, value must be str, got {type(v).__name__}' ) try: parsed = s.joined_plaintext_parser(v) except PlaintextParseError as e: raise PlaintextParseError(f'error parsing {s.title}') from e ret.append(parsed) return tuple(ret)
def parse_point(x, y): try: x = float(x) except ValueError as e: raise PlaintextParseError('could not parse x') from e try: y = float(y) except ValueError as e: raise PlaintextParseError('could not parse y') from e return x, y
def glob_search(pattern): i = iglob(pattern) try: ret = next(i) except StopIteration as e: raise PlaintextParseError('no paths match pattern') from e try: next(i) except StopIteration: pass else: raise PlaintextParseError('multiple paths match pattern') return Path(ret)
def from_csv(self, v): source = StringIO(v, newline='') v = list(csv.reader(source)) ret = [] row_count = len(v) if not row_count: raise PlaintextParseError('list must have at least one row') if not self.row_bounds.in_bounds(row_count): raise PlaintextParseError( f'row number {row_count} is out of bounds') col_count = len(v[0]) if col_count != self.column_count: raise PlaintextParseError( f'column number mismatch {col_count} (expected {self.column_count})' ) for row_num, (row, inners_row) in enumerate(zip(v, repeat_last(self.inners))): ret_row = [] if len(row) != col_count: raise PlaintextParseError( f'{col_count} column in row, 0 but {len(row)} in row {row_num}' ) for col_num, (e, inner) in enumerate(zip(row, repeat_last(inners_row))): try: s = inner.joined_plaintext_parser(e) except PlaintextParseError as exc: raise PlaintextParseError( f'error parsing {row_num, col_num}') from exc ret_row.append(s) ret.append(ret_row) return ret
def from_json_reshape(self, v): def rec_iter(iterable): for i in iterable: if isinstance(i, Iterable) and not isinstance(i, str): yield from rec_iter(i) else: yield i size = self.row_count * self.column_count i = rec_iter(v) ret = [] for row_num, inners_row in enumerate(self.inners): ret_row = [] for col_num, inner in enumerate(inners_row): try: e = next(i) except StopIteration as exc: raise PlaintextParseError( f'too few elements, expected {size}') from exc try: s = inner.joined_plaintext_parser(e) except PlaintextParseError as exc: raise PlaintextParseError( f'error parsing {row_num, col_num}') from exc ret_row.append(s) ret.append(ret_row) try: next(i) except StopIteration: pass else: raise PlaintextParseError(f'too many elements, expected {size}') return ret
def from_json(self, v): ret = [] row_count = len(v) if not row_count: raise PlaintextParseError('list must have at least one row') if not self.row_bounds.in_bounds(row_count): raise PlaintextParseError( f'row number {row_count} is out of bounds') col_count = len(v[0]) if col_count != self.column_count: raise PlaintextParseError( f'column number mismatch {col_count} (expected {self.column_count})' ) for row_num, (row, inners_row) in enumerate(zip(v, repeat_last(self.inners))): ret_row = [] if not isinstance(row, list): raise PlaintextParseError( f'element in index {row_num} is not a list') if len(row) != col_count: raise PlaintextParseError( f'{col_count} column in row 0, but {len(row)} in row {row_num}' ) for col_num, (e, inner) in enumerate(zip(row, repeat_last(inners_row))): try: s = inner.joined_plaintext_parser(e) except PlaintextParseError as exc: raise PlaintextParseError( f'error parsing {row_num, col_num}') from exc ret_row.append(s) ret.append(ret_row) return ret
def singleton(self, v): if v not in self.names: raise PlaintextParseError(f'can only parse {self.names}') return self.__value
def shorthand(s: str): split = s.rsplit("u", 2) if len(split) == 1: raise PlaintextParseError( 'string must contain a "u" separator') return s
def from_values(self, text): try: return self.name_lookup[text][1] except KeyError as e: raise PlaintextParseError(e)
def by_name(self, name): if name in self._opt_lookup_name: return name raise PlaintextParseError() from KeyError(name)
def NoneParser(s: str): if s.lower() in none_names: return self.none_value raise PlaintextParseError( f'this parser only accepts {next(iter(none_names))}')