summary refs log tree commit diff stats
path: root/compiler/nimblecmd.nim
Commit message (Expand)AuthorAgeFilesLines
* fixes #19863; move sha1, md5 to nimble packages for 2.0 (#21702)ringabout2023-05-021-1/+3
* move assertions out of system (#19599)flywind2022-03-231-0/+3
* Add changes required by Nimble lock file support (#12104)Ivan Bobev2021-07-151-30/+52
* move tests under the compiler directory to testament (#16096)flywind2020-11-251-27/+0
* make case-object transitions explicit, make unknownLineInfo a const, replace ...Jasper Jenkins2020-01-171-10/+10
* fixes disruptek/nimph#102 multi-level nim.cfg use (#13001) [backport]Andy Davidoff2019-12-311-2/+3
* Cosmetic compiler cleanup (#12718)Clyybber2019-11-281-2/+2
* Substitute $nimbleDir in --path flags (#12750)genotrance2019-11-281-0/+4
* compiler refactoring; use typesafe path handing; docgen: render symbols betwe...Andreas Rumpf2018-09-071-7/+7
* fixes #8776Araq2018-08-271-10/+11
* remove more global variables in the Nim compilerAndreas Rumpf2018-05-271-1/+1
* move more global variables into ConfigRefAndreas Rumpf2018-05-111-4/+4
* big refactoring: parser compiles againAndreas Rumpf2018-05-101-12/+13
* fixes #6949Araq2017-12-211-6/+18
* implemented new experimental scriptable import mechanismAndreas Rumpf2017-10-011-4/+4
* Fixed handling of versions with dashes in nimble pkgs (#6335)Yuriy Glukhov2017-09-061-9/+20
* Implement .nimble-link files in the compiler and add tests for them.Dominik Picheta2017-09-021-3/+14
* Add readme to tests. Add fileDir option to testament & create nimble test.Dominik Picheta2017-09-021-35/+60
* fixes #5752Araq2017-05-021-11/+30
* removed compiler internal list implementation (#5371)Arne Döring2017-02-221-4/+4
* remove unused stuffJacek Sieka2016-08-091-12/+0
* added getOrDefault; bootstrapping works againAraq2015-10-131-1/+1
* compiler: Trim .nim files trailing whitespaceAdam Strzelecki2015-09-041-3/+3
* Introduce NotesVerbosity defining verbosity levelsAdam Strzelecki2015-07-031-1/+1
* Fix typosFederico Ceratto2015-02-151-1/+1
* VM supports math and a few os procsAraq2014-08-301-1/+1
* renamed babelcmd to nimblecmd; config files are now nim.cfg; other renamingsAraq2014-08-291-0/+90
itle='author toonn <toonn@toonn.io> 2021-08-08 19:38:44 +0200 committer toonn <toonn@toonn.io> 2021-08-08 19:38:44 +0200 py2_compat: Added check for with Popen' href='/akspecs/ranger/commit/tests/pylint/py2_compat.py?id=fc4430de36d033563d21413ae009409fd7cb3a59'>fc4430de ^
1f5a23a8 ^
fc4430de ^
1f5a23a8 ^

fc4430de ^

6a871101 ^







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152


























                                                                            


                                                                        










                                                                                


                                                                         
                                                       

                                                                              





                                                                               


                                                                     














                                                                               
                                               













                                                                                
                                                              



                                                                   
                                                 

                                                                   
                                                 


















                                                                               
                                             








                                                                       
                                                     
 




                                                                             






                                                                               
                                                   
                                                                    

                                                          

                                                                                







                                                            
from __future__ import absolute_import

import astroid

from pylint.checkers import BaseChecker
from pylint.interfaces import IAstroidChecker, HIGH

from pylint.checkers import utils


class Py2CompatibilityChecker(BaseChecker):
    """Verify some simple properties of code compatible with both 2 and 3"""

    __implements__ = IAstroidChecker

    # The name defines a custom section of the config for this checker.
    name = "py2-compat"
    # The priority indicates the order that pylint will run the checkers.
    priority = -1
    # This class variable declares the messages (ie the warnings and errors)
    # that the checker can emit.
    msgs = {
        # Each message has a code, a message that the user will see,
        # a unique symbol that identifies the message,
        # and a detailed help message
        # that will be included in the documentation.
        "E4200": ('Use explicit inheritance from "object"',
                  "old-style-class",
                  'Python 2 requires explicit inheritance from "object"'
                  ' for new-style classes.'),
        # old-division
        # "E4210": ('Use "//" for integer division or import from "__future__"',
        #     "division-without-import",
        #     'Python 2 might perform integer division unless you import'
        #     ' "division" from "__future__".'),
        # no-absolute-import
        # "E4211": ('Always import "absolute_import" from "__future__"',
        #     "old-no-absolute-import",
        #     'Python 2 allows relative imports unless you import'
        #     ' "absolute_import" from "__future__".'),
        "E4212": ('Import "print_function" from "__future__"',
                  "print-without-import",
                  'Python 2 requires importing "print_function" from'
                  ' "__future__" to use the "print()" function syntax.'),
        "E4220": ('Use explicit format spec numbering',
                  "implicit-format-spec",
                  'Python 2.6 does not support implicit format spec numbering'
                  ' "{}", use explicit numbering "{0}" or keywords "{key}".'),
        "E4230": ("Use popen23.Popen with with-statements",
                  "with-popen23",
                  "Python 2 subprocess.Popen objects were not contextmanagers,"
                  "popen23.Popen wraps them to enable use with"
                  "with-statements."),
        "E4240": ("Use format method",
                  "use-format-method",
                  "Python 2 (and <3.6) does not support f-strings."),
    }
    # This class variable declares the options
    # that are configurable by the user.
    options = ()

    def visit_classdef(self, node):
        """Make sure classes explicitly inherit from object"""
        if not node.bases and node.type == 'class' and not node.metaclass():
            # We use confidence HIGH here because this message should only ever
            # be emitted for classes at the root of the inheritance hierarchy
            self.add_message('old-style-class', node=node, confidence=HIGH)

    def visit_call(self, node):
        """Make sure "print_function" is imported if necessary"""
        if (isinstance(node.func, astroid.nodes.Name)
                and node.func.name == "print"):
            if "print_function" in node.root().future_imports:
                def previous(node):
                    if node is not None:
                        parent = node.parent
                    previous = node.previous_sibling()
                    if previous is None:
                        return parent
                    return previous

                prev = previous(node)
                while prev is not None:
                    if (isinstance(prev, astroid.nodes.ImportFrom)
                        and prev.modname == "__future__"
                        and "print_function" in (name_alias[0] for name_alias in
                                                 prev.names)):
                        return
                    prev = previous(prev)

                self.add_message("print-without-import", node=node,
                                 confidence=HIGH)
            else:
                self.add_message("print-without-import", node=node,
                                 confidence=HIGH)

        func = utils.safe_infer(node.func)
        if (
            isinstance(func, astroid.BoundMethod)
            and isinstance(func.bound, astroid.Instance)
            and func.bound.name in ("str", "unicode", "bytes")
        ):
            if func.name == "format":
                if isinstance(node.func, astroid.Attribute) and not isinstance(
                    node.func.expr, astroid.Const
                ):
                    return
                if node.starargs or node.kwargs:
                    return
                try:
                    strnode = next(func.bound.infer())
                except astroid.InferenceError:
                    return
                if not (isinstance(strnode, astroid.Const) and isinstance(
                        strnode.value, str)):
                    return
                try:
                    fields, num_args, manual_pos = (
                        utils.parse_format_method_string(strnode.value)
                    )
                except utils.IncompleteFormatString:
                    self.add_message("bad-format-string", node=node)
                if num_args != 0:
                    self.add_message("implicit-format-spec", node=node,
                                     confidence=HIGH)

    def visit_joinedstr(self, node):
        """Make sure we don't use f-strings"""
        if isinstance(node, astroid.nodes.JoinedStr):
            self.add_message("use-format-method", node=node, confidence=HIGH)

    def visit_with(self, node):
        """Make sure subprocess.Popen objects aren't used in with-statements"""
        for (cm, _) in node.items:
            if isinstance(cm, astroid.nodes.Call):
                if ((isinstance(cm.func, astroid.nodes.Name)
                    and cm.func.name.endswith("Popen")
                    and (node.root().scope_lookup(node.root(), "Popen")[1][0]
                         ).modname == "subprocess")
                    or (isinstance(cm.func, astroid.nodes.Attribute)
                        and cm.func.expr == "subprocess"
                        and cm.func.attrname == "Popen")):
                    self.add_message("with-popen23", node=node, confidence=HIGH)


def register(linter):
    """This required method auto registers the checker.

    :param linter: The linter to register the checker to.
    :type linter: pylint.lint.PyLinter
    """
    linter.register_checker(Py2CompatibilityChecker(linter))