class Command: ...
class CreateCommand(Command): ...
class ExerciseCommand(Command): ...
class CreateAndExerciseCommand(Command): ...
class ExerciseByKeyCommand(Command): ...
The advantage of using union types is mypy and other Python typecheckers can do a much better job of exhaustiveness checks. The disadvantage is that under Python 3.8 and Python 3.9, using union types breaks isinstance checks. This PR hacks around it by using defining alternate implementations for those two versions of Python, but keeping the typing definition union-based. (Side note: unfortunately Python 3.9 is scheduled for EOL in October 2025 so we'll be stuck with this awkwardness for a while.)
PEP 622, the original proposal for structural pattern matching included sealed types, but PEP 634, which succeeded it, dropped them. That would allowed us to use the best of both options, but sadly it isn't an option.
This is a bit of an experiment on the ergonomics of defining:
instead of the more traditional:
The advantage of using union types is mypy and other Python typecheckers can do a much better job of exhaustiveness checks. The disadvantage is that under Python 3.8 and Python 3.9, using union types breaks
isinstance
checks. This PR hacks around it by using defining alternate implementations for those two versions of Python, but keeping the typing definition union-based. (Side note: unfortunately Python 3.9 is scheduled for EOL in October 2025 so we'll be stuck with this awkwardness for a while.)PEP 622, the original proposal for structural pattern matching included sealed types, but PEP 634, which succeeded it, dropped them. That would allowed us to use the best of both options, but sadly it isn't an option.