Skip to content

Commit 62d90dc

Browse files
committed
Update specification for directives for sys.implementation and sys.platform checks.
Signed-off-by: Jos Verlinde <Jos.Verlinde@Microsoft.com>
1 parent f98d75e commit 62d90dc

File tree

1 file changed

+129
-13
lines changed

1 file changed

+129
-13
lines changed

docs/spec/directives.rst

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -145,23 +145,139 @@ left undefined by the typing spec at this time.
145145
Version and platform checking
146146
-----------------------------
147147

148-
Type checkers are expected to understand simple version and platform
149-
checks, e.g.::
148+
Type checkers should support narrowing based on:
149+
* ``sys.version_info``
150+
* ``sys.platform``
151+
* ``sys.implementation.version``
152+
* ``sys.implementation.name``
150153

151-
import sys
154+
Type checkers should support combining these checks with:
155+
* A ``not`` unary operator
156+
* An ``and`` or ``or`` binary operator
152157

153-
if sys.version_info >= (3, 12):
154-
# Python 3.12+
155-
else:
156-
# Python 3.11 and lower
158+
Type checkers are only required to support the fully-qualified form (e.g., ``sys.platform``).
159+
Support for aliases or import variants (e.g., ``from sys import platform``) is not required, though type checkers may choose to support them.
157160

158-
if sys.platform == 'win32':
159-
# Windows specific definitions
160-
else:
161-
# Posix specific definitions
161+
The comparison patterns for these variables are described in more detail in the following paragraphs.
162162

163-
Don't expect a checker to understand obfuscations like
164-
``"".join(reversed(sys.platform)) == "xunil"``.
163+
sys.version_info checks
164+
^^^^^^^^^^^^^^^^^^^^^^^^
165+
166+
Type checkers should support the following comparison patterns:
167+
* ``sys.version_info >= <2-tuple>``
168+
* ``sys.version_info < <2-tuple>``
169+
170+
Comparisons checks are only supported against the first two elements of the version tuple.
171+
172+
.. code-block:: python
173+
:caption: Example `sys.version_info`
174+
:emphasize-lines: 2
175+
176+
import sys
177+
if sys.version_info >= (3, 12):
178+
# Python 3.12+
179+
else:
180+
# Python 3.11 and lower
181+
182+
sys.platform checks
183+
^^^^^^^^^^^^^^^^^^^
184+
185+
Type checkers should support the following comparison patterns:
186+
* ``sys.platform == <string literal>``
187+
* ``sys.platform != <string literal>``
188+
* ``sys.platform in <tuple of string literals>``
189+
* ``sys.platform not in <tuple of string literals>``
190+
191+
Common values: ``"linux"``, ``"darwin"``, ``"win32"``, ``"emscripten"``, ``"wasi"``
192+
193+
The membership checks ``in`` and ``not in``, only support simple containment testing to a tuple of literal strings.
194+
195+
.. code-block:: python
196+
:caption: Example `sys.platform`
197+
:emphasize-lines: 2,4
198+
199+
import sys
200+
if sys.platform == 'win32':
201+
# Windows specific definitions
202+
if sys.platform in ("linux", "darwin"):
203+
# Platform-specific stubs for Linux and macOS
204+
...
205+
206+
207+
sys.implementation.name checks
208+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
209+
210+
Type checkers should support comparison patterns:
211+
* ``sys.implementation.name == <string literal>``
212+
* ``sys.implementation.name != <string literal>``
213+
* ``sys.implementation.name in <tuple of string literals>``
214+
* ``sys.implementation.name not in <tuple of string literals>``
215+
216+
Common values: ``"cpython"``, ``"pypy"``, ``"micropython"``, ``"graalpy"``, ``"jython"``, ``"ironpython"``
217+
218+
.. code-block:: python
219+
:caption: Example `sys.implementation.name`
220+
:emphasize-lines: 2,4
221+
222+
import sys
223+
if sys.implementation.name == "cpython":
224+
# CPython-specific stub
225+
if sys.implementation.name == "micropython":
226+
# MicroPython-specific stub
227+
228+
229+
sys.implementation.version checks
230+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
231+
232+
Type checkers should support the following comparison patterns:
233+
* ``sys.implementation.version >= <2-tuple>``
234+
* ``sys.implementation.version < <2-tuple>``
235+
236+
Comparisons checks are only supported against the first two elements of the implementation version tuple.
237+
238+
.. code-block:: python
239+
:caption: Example `sys.implementation.version`
240+
:emphasize-lines: 2,4
241+
242+
import sys
243+
if sys.implementation.name == "pypy" and sys.implementation.version >= (7, 3):
244+
# PyPy version 7.3 and above
245+
if sys.implementation.name == "micropython" and sys.implementation.version >= (1, 24):
246+
# MicroPython version 1.24 and above
247+
248+
.. note::
249+
250+
``sys.implementation.version`` is a tuple, in the same format as sys.version_info. However it represents the version of the Python implementation rather than the version of the Python language.
251+
This has a distinct meaning from the specific version of the Python language to which the currently running interpreter conforms. For CPython this is the same as `sys.version_info`.
252+
253+
254+
No support for complex expressions
255+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
256+
257+
Type checkers are only required to support the above patterns, and are not required to evaluate complex expressions involving these variables.
258+
For example, the pattern ``sys.platform == "linux"`` is supported but other syntax variants such as ``platform == "linux"`` and ``"win" not in sys.platform`` are not supported.
259+
260+
Therefore checkers are **not required** to understand obfuscations such as:
261+
262+
.. code-block:: python
263+
:caption: Examples of unsupported or overly complex version/platform checks
264+
:emphasize-lines: 3,5,7
265+
266+
import sys
267+
from sys import platform
268+
if "".join(reversed(sys.platform)) == "xunil":
269+
# Linux specific code
270+
if platform == "linux":
271+
# Linux specific code
272+
if "win" not in sys.platform:
273+
# Non-Windows specific code
274+
275+
276+
Configuration
277+
^^^^^^^^^^^^^
278+
279+
Type checkers should provide configuration or CLI options to specify target sys.version, sys.platform, sys.implementation.name and sys.implementation.version.
280+
The exact mechanism for this is implementation-defined by the type checker.
165281

166282
.. _`deprecated`:
167283

0 commit comments

Comments
 (0)