|
| 1 | +import sys |
| 2 | +import re |
| 3 | +from argparse import ArgumentParser, Namespace |
1 | 4 | from collections import namedtuple |
2 | 5 | from glob import iglob |
3 | 6 | from logging import getLogger |
4 | 7 | from math import ceil, floor |
5 | 8 | from os import environ |
6 | | -from typing import Generator, Sequence, Tuple, Union |
| 9 | +from typing import Generator, Sequence, Tuple, Union, Optional |
7 | 10 |
|
8 | 11 | import numpy as np |
9 | 12 | import wkw |
@@ -65,6 +68,34 @@ def parse_padding(padding_str: str) -> Tuple[int, ...]: |
65 | 68 | raise argparse.ArgumentTypeError("The padding could not be parsed") from e |
66 | 69 |
|
67 | 70 |
|
| 71 | +class AsciiArgumentParser(ArgumentParser): |
| 72 | + """ |
| 73 | + This class is a lightweight wrapper around ArgumentParser and checks |
| 74 | + that the shell command doesn't contain non-ascii characters since these |
| 75 | + can easily disturb the argument parsing. |
| 76 | +
|
| 77 | + If non-ascii characters are found, an error is raised. This behavior |
| 78 | + can be disabled by passing --allow-non-ascii on the command line. |
| 79 | + """ |
| 80 | + |
| 81 | + IGNORE_FLAG = "--allow-non-ascii" |
| 82 | + |
| 83 | + def parse_args(self, args: Optional[Sequence[str]] = None, namespace: Optional[Namespace] = None) -> Any: # type: ignore |
| 84 | + if args is None: |
| 85 | + args = sys.argv[1:] |
| 86 | + |
| 87 | + # Search for non-ascii codes (ASCII itself spans 0-127 or 0x00 to 0x7F). |
| 88 | + results = re.findall(r"[^\x00-\x7F]", " ".join(args)) |
| 89 | + if len(results) > 0: |
| 90 | + if not self.IGNORE_FLAG in args: |
| 91 | + raise ValueError( |
| 92 | + f"The shell command contains non-ascii characters. Please remove them to avoid unintended effects. If you need them, pass {self.IGNORE_FLAG} to suppress this error. The special characters are: {results}" |
| 93 | + ) |
| 94 | + |
| 95 | + args = [el for el in args if el != self.IGNORE_FLAG] |
| 96 | + return super().parse_args(args, namespace) |
| 97 | + |
| 98 | + |
68 | 99 | def open_knossos(info: KnossosDatasetInfo) -> KnossosDataset: |
69 | 100 | return KnossosDataset.open(info.dataset_path, np.dtype(info.dtype)) |
70 | 101 |
|
|
0 commit comments