* Avoid exception if trying to delete missing "removed" key
`.pop(key)` throws an exception if that `key` is missing. Using a default value (in this case None) means we don't throw any errors when deleting a missing key. Which is what we want here, for safety. We just want to delete the key. We don't care if it's existing or not.
There are other places in the codebase that also use `.pop(key)`, but all of those first check the validity of the key before popping, so this was the only one that needed fixing.
* Improve performance by removing keys() calls
Every `.keys()` call create a new `[list...]` of all keys from the given dictionary. It's a total waste of performance, since we can already check if a key exists in a dictionary by just using `if "key" in the_dict`.
* Use more pythonic "not in" syntax
The syntax is supposed to be `if "thing" not in other_thing`. We already use this proper `not in` syntax everywhere else in the codebase. Just fixing this location.
Now uses proper shell escaping and parsing for all executable arguments, for more robust game launching. All existing game JSON files with the old string values will automatically be converted to the new format on app launch. The executable parsing uses the "shlex" library, which guarantees accurate parsing.
We now also use direct process launching (without any intermediary shell) by default, but the old "shell"-based launch method still exists in the code via an alternative flag in `run_command.py` (if we ever need to restore it for some reason).
Furthermore, if the user attempts to manually write an improperly escaped argument into the game's details (such as missing closing quotation marks), the GUI will now alert the user that their executable argument is invalid, along with telling them the exact reason why it's invalid.