• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import sys
2
3
4OS = sys.platform
5
6
7def _as_tuple(items):
8    if isinstance(items, str):
9        return tuple(items.strip().replace(',', ' ').split())
10    elif items:
11        return tuple(items)
12    else:
13        return ()
14
15
16class PreprocessorError(Exception):
17    """Something preprocessor-related went wrong."""
18
19    @classmethod
20    def _msg(cls, filename, reason, **ignored):
21        msg = 'failure while preprocessing'
22        if reason:
23            msg = f'{msg} ({reason})'
24        return msg
25
26    def __init__(self, filename, preprocessor=None, reason=None):
27        if isinstance(reason, str):
28            reason = reason.strip()
29
30        self.filename = filename
31        self.preprocessor = preprocessor or None
32        self.reason = str(reason) if reason else None
33
34        msg = self._msg(**vars(self))
35        msg = f'({filename}) {msg}'
36        if preprocessor:
37            msg = f'[{preprocessor}] {msg}'
38        super().__init__(msg)
39
40
41class PreprocessorFailure(PreprocessorError):
42    """The preprocessor command failed."""
43
44    @classmethod
45    def _msg(cls, error, **ignored):
46        msg = 'preprocessor command failed'
47        if error:
48            msg = f'{msg} {error}'
49        return msg
50
51    def __init__(self, filename, argv, error=None, preprocessor=None):
52        exitcode = -1
53        if isinstance(error, tuple):
54            if len(error) == 2:
55                error, exitcode = error
56            else:
57                error = str(error)
58        if isinstance(error, str):
59            error = error.strip()
60
61        self.argv = _as_tuple(argv) or None
62        self.error = error if error else None
63        self.exitcode = exitcode
64
65        reason = str(self.error)
66        super().__init__(filename, preprocessor, reason)
67
68
69class ErrorDirectiveError(PreprocessorFailure):
70    """The file hit a #error directive."""
71
72    @classmethod
73    def _msg(cls, error, **ignored):
74        return f'#error directive hit ({error})'
75
76    def __init__(self, filename, argv, error, *args, **kwargs):
77        super().__init__(filename, argv, error, *args, **kwargs)
78
79
80class MissingDependenciesError(PreprocessorFailure):
81    """The preprocessor did not have access to all the target's dependencies."""
82
83    @classmethod
84    def _msg(cls, missing, **ignored):
85        msg = 'preprocessing failed due to missing dependencies'
86        if missing:
87            msg = f'{msg} ({", ".join(missing)})'
88        return msg
89
90    def __init__(self, filename, missing=None, *args, **kwargs):
91        self.missing = _as_tuple(missing) or None
92
93        super().__init__(filename, *args, **kwargs)
94
95
96class OSMismatchError(MissingDependenciesError):
97    """The target is not compatible with the host OS."""
98
99    @classmethod
100    def _msg(cls, expected, **ignored):
101        return f'OS is {OS} but expected {expected or "???"}'
102
103    def __init__(self, filename, expected=None, *args, **kwargs):
104        if isinstance(expected, str):
105            expected = expected.strip()
106
107        self.actual = OS
108        self.expected = expected if expected else None
109
110        super().__init__(filename, None, *args, **kwargs)
111