Thanks for the post. I appreciate the clear articulation of the problem and the menu of possible solutions.
I think that both of your proposed solutions are possible, but we should understand the advantages and costs associated with each.
It’s important to understand that these conditional platform expressions need to be evaluated by a static type checker very early in the analysis process. In pyright (and presumably other type checkers), the evaluation of these expressions informs the construction of the code flow graph. The code flow graph is needed to evaluate the type of any expression (including type annotations and type qualifiers), and determine the types of imported symbols. That means these platform expressions need to be evaluated before any type evaluation is possible. It’s a classic chicken-and-egg problem. To make this work, type checkers need to work directly from the AST looking for specific syntactical forms. This is why the typing spec is so specific in prescribing which forms are supported. Even small deviations from the supported forms will prevent it from working. For example, if you change import sys; if sys.platform == "darwin": ... to from sys import platform; if platform == "darwin"; ... it will no longer work. These two variants are semantically equivalent but syntactically different, and the syntax matters here. Likewise, if you swap the operands (if "darwin" == sys.platform) or attempt to use a variable (as suggested above by @JoBe), it will not work. Any solution needs to respect the constraints faced by type checker implementations. For more details, refer to this pyright documentation.
Supporting sys.implementation.name is possible, but it has some (perhaps non-obvious) costs. It would require type checkers to add a new configuration mechanism for setting the desired implementation name. It would also require adding command-line switches, and it would require auto-detection of this value if it’s not specified in the configuration or command line. This wouldn’t be so bad if it were just type checkers, but many CI scripts, test harnesses, typing-related tools (e.g. mypy_primer), etc. also provide ways to configure the pythonVersion and pythonPlatform. This approach would compel all of these tools and scripts to plumb through another configuration setting. That’s doable, but it will take time and impose some not-insignificant cost across the ecosystem.
Supporting alternative syntax forms for sys.platform checks is possible and would be limited to just type checkers, linters, stub generators, stub testers, and similar tools. It wouldn’t require new configuration or auto-discovery mechanisms. Most other tooling and scripts would not need to be modified because they already support a pythonPlatform configuration setting and command-line switches. So this option is less costly than the first. If we were to adopt this option, I would recommend against supporting tuples, lists, and sets. I would pick one of them — preferably tuples — and mandate that everyone use that. This isn’t a situation where supporting lots of freedom, creativity, and redundant approaches is helpful. Picking one supported syntactic form is beneficial. Supporting both in and not in operators is straightforward.
Let me suggest a third option that may partly address the problem without requiring any new functionality. Both mypy and pyright allow developers to define “constants” in the config file. In pyright, this is done with the defineConstant setting, and both boolean and string constants are supported. Mypy supports always_true and always_false, which limits it to booleans. You could standardize a symbol such as MICROPYTHON (all caps to indicate that it’s a constant) that you use within your stubs. Consumers of the stubs could then modify their type checker configuration to indicate that MICROPYTHON should always be evaluated as True. If mypy were extended to support string-based constants (as pyright already does), you could standardize a symbol such as IMPLEMENTATION_NAME that takes on the value of micropython. Some variation of this idea may address part of the problem you’re facing.
I’ll note that none of the above solutions (including the two you proposed) address the “implementation version” requirement. Relative to platform comparisons, how important are version comparisons?