Skip to content

Commit a7e55b4

Browse files
Add new If guard helper methods (#1099)
* Add new if guard helper methods Co-authored-by: Pierre Sassoulas <[email protected]>
1 parent 071d36a commit a7e55b4

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

ChangeLog

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ What's New in astroid 2.7.0?
77
Release date: TBA
88

99

10-
1110
What's New in astroid 2.6.3?
1211
============================
1312
Release date: TBA
1413

14+
* Added ``If.is_sys_guard`` and ``If.is_typing_guard`` helper methods
1515

1616
* Fix a bad inferenece type for yield values inside of a derived class.
1717

astroid/node_classes.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3480,6 +3480,43 @@ def _get_yield_nodes_skip_lambdas(self):
34803480
yield from self.test._get_yield_nodes_skip_lambdas()
34813481
yield from super()._get_yield_nodes_skip_lambdas()
34823482

3483+
def is_sys_guard(self) -> bool:
3484+
"""Return True if IF stmt is a sys.version_info guard.
3485+
3486+
>>> node = astroid.extract_node('''
3487+
import sys
3488+
if sys.version_info > (3, 8):
3489+
from typing import Literal
3490+
else:
3491+
from typing_extensions import Literal
3492+
''')
3493+
>>> node.is_sys_guard()
3494+
True
3495+
"""
3496+
if isinstance(self.test, Compare):
3497+
value = self.test.left
3498+
if isinstance(value, Subscript):
3499+
value = value.value
3500+
if isinstance(value, Attribute) and value.as_string() == "sys.version_info":
3501+
return True
3502+
3503+
return False
3504+
3505+
def is_typing_guard(self) -> bool:
3506+
"""Return True if IF stmt is a typing guard.
3507+
3508+
>>> node = astroid.extract_node('''
3509+
from typing import TYPE_CHECKING
3510+
if TYPE_CHECKING:
3511+
from xyz import a
3512+
''')
3513+
>>> node.is_typing_guard()
3514+
True
3515+
"""
3516+
return isinstance(
3517+
self.test, (Name, Attribute)
3518+
) and self.test.as_string().endswith("TYPE_CHECKING")
3519+
34833520

34843521
class IfExp(NodeNG):
34853522
"""Class representing an :class:`ast.IfExp` node.

tests/unittest_nodes.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,64 @@ def test_block_range(self):
342342
self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8))
343343
self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8))
344344

345+
@staticmethod
346+
def test_if_sys_guard():
347+
code = builder.extract_node(
348+
"""
349+
import sys
350+
if sys.version_info > (3, 8): #@
351+
pass
352+
353+
if sys.version_info[:2] > (3, 8): #@
354+
pass
355+
356+
if sys.some_other_function > (3, 8): #@
357+
pass
358+
"""
359+
)
360+
assert isinstance(code, list) and len(code) == 3
361+
362+
assert isinstance(code[0], nodes.If)
363+
assert code[0].is_sys_guard() is True
364+
assert isinstance(code[1], nodes.If)
365+
assert code[1].is_sys_guard() is True
366+
367+
assert isinstance(code[2], nodes.If)
368+
assert code[2].is_sys_guard() is False
369+
370+
@staticmethod
371+
def test_if_typing_guard():
372+
code = builder.extract_node(
373+
"""
374+
import typing
375+
import typing as t
376+
from typing import TYPE_CHECKING
377+
378+
if typing.TYPE_CHECKING: #@
379+
pass
380+
381+
if t.TYPE_CHECKING: #@
382+
pass
383+
384+
if TYPE_CHECKING: #@
385+
pass
386+
387+
if typing.SOME_OTHER_CONST: #@
388+
pass
389+
"""
390+
)
391+
assert isinstance(code, list) and len(code) == 4
392+
393+
assert isinstance(code[0], nodes.If)
394+
assert code[0].is_typing_guard() is True
395+
assert isinstance(code[1], nodes.If)
396+
assert code[1].is_typing_guard() is True
397+
assert isinstance(code[2], nodes.If)
398+
assert code[2].is_typing_guard() is True
399+
400+
assert isinstance(code[3], nodes.If)
401+
assert code[3].is_typing_guard() is False
402+
345403

346404
class TryExceptNodeTest(_NodeTest):
347405
CODE = """

0 commit comments

Comments
 (0)