| 203 | |
| 204 | |
| 205 | class ParseMachine(StateMachine): |
| 206 | initial_state = "context" |
| 207 | |
| 208 | state("context", enter=["complete_flag", "complete_context"]) |
| 209 | state("unknown", enter=["complete_flag", "complete_context"]) |
| 210 | state("end", enter=["complete_flag", "complete_context"]) |
| 211 | |
| 212 | transition(from_=("context", "unknown"), event="finish", to="end") |
| 213 | transition( |
| 214 | from_="context", |
| 215 | event="see_context", |
| 216 | action="switch_to_context", |
| 217 | to="context", |
| 218 | ) |
| 219 | transition( |
| 220 | from_=("context", "unknown"), |
| 221 | event="see_unknown", |
| 222 | action="store_only", |
| 223 | to="unknown", |
| 224 | ) |
| 225 | |
| 226 | def changing_state(self, from_: str, to: str) -> None: |
| 227 | debug("ParseMachine: {!r} => {!r}".format(from_, to)) |
| 228 | |
| 229 | def __init__( |
| 230 | self, |
| 231 | initial: "ParserContext", |
| 232 | contexts: Lexicon, |
| 233 | ignore_unknown: bool, |
| 234 | ) -> None: |
| 235 | # Initialize |
| 236 | self.ignore_unknown = ignore_unknown |
| 237 | self.initial = self.context = copy.deepcopy(initial) |
| 238 | debug("Initialized with context: {!r}".format(self.context)) |
| 239 | self.flag = None |
| 240 | self.flag_got_value = False |
| 241 | self.result = ParseResult() |
| 242 | self.contexts = copy.deepcopy(contexts) |
| 243 | debug("Available contexts: {!r}".format(self.contexts)) |
| 244 | # In case StateMachine does anything in __init__ |
| 245 | super().__init__() |
| 246 | |
| 247 | @property |
| 248 | def waiting_for_flag_value(self) -> bool: |
| 249 | # Do we have a current flag, and does it expect a value (vs being a |
| 250 | # bool/toggle)? |
| 251 | takes_value = self.flag and self.flag.takes_value |
| 252 | if not takes_value: |
| 253 | return False |
| 254 | # OK, this flag is one that takes values. |
| 255 | # Is it a list type (which has only just been switched to)? Then it'll |
| 256 | # always accept more values. |
| 257 | # TODO: how to handle somebody wanting it to be some other iterable |
| 258 | # like tuple or custom class? Or do we just say unsupported? |
| 259 | if self.flag.kind is list and not self.flag_got_value: |
| 260 | return True |
| 261 | # Not a list, okay. Does it already have a value? |
| 262 | has_value = self.flag.raw_value is not None |
no outgoing calls
no test coverage detected
searching dependent graphs…