Example #1
0
 def test_no_python_file(self):
     quality = PylintQualityReporter('pylint', [])
     file_paths = ['file1.coffee', 'subdir/file2.js']
     # Expect that we get no results because no Python files
     for path in file_paths:
         result = quality.violations(path)
         self.assertEqual(result, [])
 def test_no_python_file(self):
     quality = PylintQualityReporter('pylint', [])
     file_paths = ['file1.coffee', 'subdir/file2.js']
     # Expect that we get no results because no Python files
     for path in file_paths:
         result = quality.violations(path)
         self.assertEqual(result, [])
Example #3
0
    def test_quality(self):
        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()

        _mock_communicate.return_value = (dedent("""
            file1.py:1: [C0111] Missing docstring
            file1.py:1: [C0111, func_1] Missing docstring
            file1.py:2: [W0612, cls_name.func] Unused variable 'd'
            file1.py:2: [W0511] TODO: Not the real way we'll store usages!
            file1.py:579: [F0401] Unable to import 'rooted_paths'
            file1.py:113: [W0613, cache_relation.clear_pk] Unused argument 'cls'
            file1.py:150: [F0010] error while code parsing ([Errno 2] No such file or directory)
            file1.py:149: [C0324, Foo.__dict__] Comma not followed by a space
                self.peer_grading._find_corresponding_module_for_location(Location('i4x','a','b','c','d'))
            file1.py:162: [R0801] Similar lines in 2 files
            ==external_auth.views:1
            ==student.views:4
            import json
            import logging
            import random
            path/to/file2.py:100: [W0212, openid_login_complete] Access to a protected member
            """).strip().encode('ascii'), '')

        expected_violations = [
            Violation(1, 'C0111: Missing docstring'),
            Violation(1, 'C0111: func_1: Missing docstring'),
            Violation(2, "W0612: cls_name.func: Unused variable 'd'"),
            Violation(2, "W0511: TODO: Not the real way we'll store usages!"),
            Violation(579, "F0401: Unable to import 'rooted_paths'"),
            Violation(
                150,
                "F0010: error while code parsing ([Errno 2] No such file or directory)"
            ),
            Violation(149,
                      "C0324: Foo.__dict__: Comma not followed by a space"),
            Violation(162, "R0801: Similar lines in 2 files"),
            Violation(113,
                      "W0613: cache_relation.clear_pk: Unused argument 'cls'")
        ]

        # Parse the report
        quality = PylintQualityReporter('pylint', [])

        # Expect that the name is set
        self.assertEqual(quality.name(), 'pylint')

        # Measured_lines is undefined for a
        # quality reporter since all lines are measured
        self.assertEqual(quality.measured_lines('file1.py'), None)

        # Expect that we get violations for file1.py only
        # We're not guaranteed that the violations are returned
        # in any particular order.
        actual_violations = quality.violations('file1.py')
        self.assertEqual(len(actual_violations), len(expected_violations))
        for expected in expected_violations:
            self.assertIn(expected, actual_violations)
    def test_no_quality_issues_emptystring(self):

        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = ('', '')

        # Parse the report
        quality = PylintQualityReporter('pylint', [])
        self.assertEqual([], quality.violations('file1.py'))
Example #5
0
    def test_no_quality_issues_emptystring(self):

        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = (b'', b'')

        # Parse the report
        quality = PylintQualityReporter('pylint', [])
        self.assertEqual([], quality.violations('file1.py'))
    def test_quality_pregenerated_report_continuation_char(self):

        # The report contains a non-ASCII continuation char
        pylint_reports = [BytesIO(b"file.py:2: [W1401] Invalid char '\xc3'")]

        # Generate the violation report
        quality = PylintQualityReporter('pylint', pylint_reports)
        violations = quality.violations('file.py')

        # Expect that the char is replaced
        self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
    def test_unicode_continuation_char(self):
        _mock_communicate = patch.object(Popen, 'communicate').start()

        # Test a unicode continuation char, which pylint can produce (probably an encoding bug in pylint)
        _mock_communicate.return_value = ("file.py:2: [W1401] Invalid char '\xc3'", '')

        # Since we are replacing characters we can't interpet, this should
        # return a valid string with the char replaced with '?'
        quality = PylintQualityReporter('pylint', [])
        violations = quality.violations(u'file.py')
        self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
    def test_no_quality_issues_newline(self):

        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = ('\n', '')
        violations = []
        name = "pylint"

        # Parse the report
        quality = PylintQualityReporter(name)
        self.assertEqual(violations, quality.violations('file1.py'))
Example #9
0
    def test_quality_pregenerated_report_continuation_char(self):

        # The report contains a non-ASCII continuation char
        pylint_reports = [BytesIO(b"file.py:2: [W1401] Invalid char '\xc3'")]

        # Generate the violation report
        quality = PylintQualityReporter('pylint', pylint_reports)
        violations = quality.violations('file.py')

        # Expect that the char is replaced
        self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
    def test_quality(self):
        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()

        _mock_communicate.return_value = (
            dedent("""
            file1.py:1: [C0111] Missing docstring
            file1.py:1: [C0111, func_1] Missing docstring
            file1.py:2: [W0612, cls_name.func] Unused variable 'd'
            file1.py:2: [W0511] TODO: Not the real way we'll store usages!
            file1.py:579: [F0401] Unable to import 'rooted_paths'
            file1.py:113: [W0613, cache_relation.clear_pk] Unused argument 'cls'
            file1.py:150: [F0010] error while code parsing ([Errno 2] No such file or directory)
            file1.py:149: [C0324, Foo.__dict__] Comma not followed by a space
                self.peer_grading._find_corresponding_module_for_location(Location('i4x','a','b','c','d'))
            file1.py:162: [R0801] Similar lines in 2 files
            ==external_auth.views:1
            ==student.views:4
            import json
            import logging
            import random
            path/to/file2.py:100: [W0212, openid_login_complete] Access to a protected member
            """).strip(), ''
        )

        expected_violations = [
            Violation(1, 'C0111: Missing docstring'),
            Violation(1, 'C0111: func_1: Missing docstring'),
            Violation(2, "W0612: cls_name.func: Unused variable 'd'"),
            Violation(2, "W0511: TODO: Not the real way we'll store usages!"),
            Violation(579, "F0401: Unable to import 'rooted_paths'"),
            Violation(150, "F0010: error while code parsing ([Errno 2] No such file or directory)"),
            Violation(149, "C0324: Foo.__dict__: Comma not followed by a space"),
            Violation(162, "R0801: Similar lines in 2 files"),
            Violation(113, "W0613: cache_relation.clear_pk: Unused argument 'cls'")
        ]

        # Parse the report
        quality = PylintQualityReporter('pylint', [])

        # Expect that the name is set
        self.assertEqual(quality.name(), 'pylint')

        # Measured_lines is undefined for a
        # quality reporter since all lines are measured
        self.assertEqual(quality.measured_lines('file1.py'), None)

        # Expect that we get violations for file1.py only
        # We're not guaranteed that the violations are returned
        # in any particular order.
        actual_violations = quality.violations('file1.py')
        self.assertEqual(len(actual_violations), len(expected_violations))
        for expected in expected_violations:
            self.assertIn(expected, actual_violations)
Example #11
0
    def test_unicode_continuation_char(self):
        _mock_communicate = patch.object(Popen, 'communicate').start()

        # Test a unicode continuation char, which pylint can produce (probably an encoding bug in pylint)
        _mock_communicate.return_value = (b"file.py:2: [W1401]"
                                          b" Invalid char '\xc3'", '')

        # Since we are replacing characters we can't interpet, this should
        # return a valid string with the char replaced with '?'
        quality = PylintQualityReporter('pylint', [])
        violations = quality.violations(u'file.py')
        self.assertEqual(violations, [Violation(2, u"W1401: Invalid char '\ufffd'")])
    def test_quality_pregenerated_report(self):

        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = ('\n', '')

        # When the user provides us with a pre-generated pylint report
        # then use that instead of calling pylint directly.
        pylint_reports = [
            StringIO(
                dedent(u"""
                path/to/file.py:1: [C0111] Missing docstring
                path/to/file.py:57: [W0511] TODO the name of this method is a little bit confusing
                another/file.py:41: [W1201, assign_default_role] Specify string format arguments as logging function parameters
                another/file.py:175: [C0322, Foo.bar] Operator not preceded by a space
                        x=2+3
                          ^
                        Unicode: \u9404 \u1239
                another/file.py:259: [C0103, bar] Invalid name "\u4920" for type variable (should match [a-z_][a-z0-9_]{2,30}$)
            """).strip()),
            StringIO(
                dedent(u"""
            path/to/file.py:183: [C0103, Foo.bar.gettag] Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$)
            another/file.py:183: [C0111, Foo.bar.gettag] Missing docstring
            """).strip())
        ]

        # Generate the violation report
        quality = PylintQualityReporter('pylint', pylint_reports)

        # Expect that we get the right violations
        expected_violations = [
            Violation(1, u'C0111: Missing docstring'),
            Violation(
                57,
                u'W0511: TODO the name of this method is a little bit confusing'
            ),
            Violation(
                183,
                u'C0103: Foo.bar.gettag: Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$)'
            )
        ]

        # We're not guaranteed that the violations are returned
        # in any particular order.
        actual_violations = quality.violations('path/to/file.py')
        self.assertEqual(len(actual_violations), len(expected_violations))
        for expected in expected_violations:
            self.assertIn(expected, actual_violations)
    def test_quality_error(self):

        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = ("", 'whoops')

        name = "pylint"

        # Parse the report
        quality = PylintQualityReporter(name)

        # Expect that the name is set
        self.assertEqual(quality.name(), name)

        self.assertRaises(QualityReporterError, quality.violations, 'file1.py')
    def test_unicode(self):
        _mock_communicate = patch.object(Popen, 'communicate').start()

        # Test non-ascii unicode characters in the filename, function name and message
        _mock_communicate.return_value = (dedent(u"""
            file_\u6729.py:616: [W1401] Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix.
            file.py:2: [W0612, cls_name.func_\u9492] Unused variable '\u2920'
        """).encode('utf-8'), b'')

        quality = PylintQualityReporter('pylint', [])
        violations = quality.violations(u'file_\u6729.py')
        self.assertEqual(violations, [
            Violation(616, u"W1401: Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix."),
        ])

        violations = quality.violations(u'file.py')
        self.assertEqual(violations, [Violation(2, u"W0612: cls_name.func_\u9492: Unused variable '\u2920'")])
Example #15
0
    def test_unicode(self):
        _mock_communicate = patch.object(Popen, 'communicate').start()

        # Test non-ascii unicode characters in the filename, function name and message
        _mock_communicate.return_value = (dedent(u"""
            file_\u6729.py:616: [W1401] Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix.
            file.py:2: [W0612, cls_name.func_\u9492] Unused variable '\u2920'
        """).encode('utf-8'), b'')

        quality = PylintQualityReporter('pylint', [])
        violations = quality.violations(u'file_\u6729.py')
        self.assertEqual(violations, [
            Violation(616, u"W1401: Anomalous backslash in string: '\u5922'. String constant might be missing an r prefix."),
        ])

        violations = quality.violations(u'file.py')
        self.assertEqual(violations, [Violation(2, u"W0612: cls_name.func_\u9492: Unused variable '\u2920'")])
    def test_quality(self):
        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = ("************* Module new_file\nC0111:  1,0: Missing docstring\ndef func_1(apple,my_list):\n                ^^\nC0111:  1,0:func_1: Missing docstring\n\nW0612:  2,4:func_1: Unused variable 'd'", '')
        violations = [Violation(1, 'C0111: Missing docstring'), Violation(1, 'C0111: Missing docstring'), Violation(2, "W0612: Unused variable 'd'")]
        name = "pylint"

        # Parse the report
        quality = PylintQualityReporter(name)

        # Expect that the name is set
        self.assertEqual(quality.name(), name)
        # measured_lines is undefined for a quality reporter since all lines are measured
        self.assertEqual(quality.measured_lines('file1.py'), None)

        # By construction, each file has the same set
        # of covered/uncovered lines
        self.assertEqual(violations, quality.violations('file1.py'))
Example #17
0
    def test_non_integer_line_num(self):
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = (dedent(u"""
            file.py:not_a_number: C0111: Missing docstring
            file.py:\u8911: C0111: Missing docstring
        """).encode('utf-8'), '')

        # None of the violations have a valid line number, so they should all be skipped
        violations = PylintQualityReporter('pylint', []).violations(u'file.py')
        self.assertEqual(violations, [])
    def test_quality_pregenerated_report(self):

        # Patch the output of `pylint`
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = ('\n', '')

        # When the user provides us with a pre-generated pylint report
        # then use that instead of calling pylint directly.
        pylint_reports = [
            StringIO(dedent(u"""
                path/to/file.py:1: [C0111] Missing docstring
                path/to/file.py:57: [W0511] TODO the name of this method is a little bit confusing
                another/file.py:41: [W1201, assign_default_role] Specify string format arguments as logging function parameters
                another/file.py:175: [C0322, Foo.bar] Operator not preceded by a space
                        x=2+3
                          ^
                        Unicode: \u9404 \u1239
                another/file.py:259: [C0103, bar] Invalid name "\u4920" for type variable (should match [a-z_][a-z0-9_]{2,30}$)
            """).strip()),

            StringIO(dedent(u"""
            path/to/file.py:183: [C0103, Foo.bar.gettag] Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$)
            another/file.py:183: [C0111, Foo.bar.gettag] Missing docstring
            """).strip())
        ]

        # Generate the violation report
        quality = PylintQualityReporter('pylint', pylint_reports)

        # Expect that we get the right violations
        expected_violations = [
            Violation(1, u'C0111: Missing docstring'),
            Violation(57, u'W0511: TODO the name of this method is a little bit confusing'),
            Violation(183, u'C0103: Foo.bar.gettag: Invalid name "\u3240" for type argument (should match [a-z_][a-z0-9_]{2,30}$)')
        ]

        # We're not guaranteed that the violations are returned
        # in any particular order.
        actual_violations = quality.violations('path/to/file.py')
        self.assertEqual(len(actual_violations), len(expected_violations))
        for expected in expected_violations:
            self.assertIn(expected, actual_violations)
Example #19
0
    def test_quality_error(self):

        # Patch the output of `pylint`
        # to output to stderr
        _mock_communicate = patch.object(Popen, 'communicate').start()
        _mock_communicate.return_value = (b"", b'whoops')

        # Parse the report
        quality = PylintQualityReporter('pylint', [])

        # Expect an error
        self.assertRaises(QualityReporterError, quality.violations, 'file1.py')
Example #20
0
    def test_quality_deprecation_warning(self):

        # Patch the output stderr/stdout and returncode of `pylint`
        _mock_communicate = patch.object(subprocess, 'Popen').start()
        subproc_mock = MagicMock()
        # Pylint may raise deprecation warnings on pylint usage itself (such
        # as pylintrc configuration), but continue evaluating for violations.
        # Diff-quality, likewise, will continue.
        subproc_mock.returncode = 0
        subproc_mock.communicate.return_value = (
            b'file1.py:1: [C0111] Missing docstring\n'
            b'file1.py:1: [C0111, func_1] Missing docstring',
            b'Foobar: pylintrc deprecation warning'
        )
        _mock_communicate.return_value = subproc_mock

        # Parse the report
        quality = PylintQualityReporter('pylint', [])
        actual_violations = quality.violations('file1.py')

        # Assert that pylint successfully runs and finds 2 violations
        self.assertEqual(len(actual_violations), 2)
    def test_quality_deprecation_warning(self):

        # Patch the output stderr/stdout and returncode of `pylint`
        _mock_communicate = patch.object(subprocess, 'Popen').start()
        subproc_mock = MagicMock()
        # Pylint may raise deprecation warnings on pylint usage itself (such
        # as pylintrc configuration), but continue evaluating for violations.
        # Diff-quality, likewise, will continue.
        subproc_mock.returncode = 0
        subproc_mock.communicate.return_value = (
            b'file1.py:1: [C0111] Missing docstring\n'
            b'file1.py:1: [C0111, func_1] Missing docstring',
            b'Foobar: pylintrc deprecation warning'
        )
        _mock_communicate.return_value = subproc_mock

        # Parse the report
        quality = PylintQualityReporter('pylint', [])
        actual_violations = quality.violations('file1.py')

        # Assert that pylint successfully runs and finds 2 violations
        self.assertEqual(len(actual_violations), 2)
    def test_legacy_pylint_compatibility(self):
        quality = PylintQualityReporter('pylint', [])
        _mock_communicate = patch.object(Popen, 'communicate').start()
        expected_options = [quality.MODERN_OPTIONS, quality.LEGACY_OPTIONS]

        def side_effect():
            """
            Assure that the first time we use the modern options, return a failure
            Then assert the legacy options were set, return ok
            """
            index = _mock_communicate.call_count - 1
            self.assertEqual(quality.OPTIONS, expected_options[index])

            return [(b"", dedent("""
            Adding some unicode to ensure we parse this correctly: ȼȼȼȼȼȼȼȼȼȼȼ
            No config file found, using default configuration
            Usage:  pylint [options] module_or_package

              Check that a module satisfies a coding standard (and more !).

                pylint --help

              Display this help message and exit.

                pylint --help-msg <msg-id>[,<msg-id>]

              Display help messages about given message identifiers and exit.


            pylint: error: no such option: --msg-template
        """).encode('utf-8')), (b'\n', b'')][index]

        _mock_communicate.side_effect = side_effect
        quality.violations('file1.py')
        self.assertEqual([], quality.violations('file1.py'))
        self.assertEqual(quality.OPTIONS, quality.LEGACY_OPTIONS)
        self.assertEqual(_mock_communicate.call_count, 2)
Example #23
0
    def test_legacy_pylint_compatibility(self):
        quality = PylintQualityReporter('pylint', [])
        _mock_communicate = patch.object(Popen, 'communicate').start()
        expected_options = [quality.MODERN_OPTIONS, quality.LEGACY_OPTIONS]

        def side_effect():
            """
            Assure that the first time we use the modern options, return a failure
            Then assert the legacy options were set, return ok
            """
            index = _mock_communicate.call_count - 1
            self.assertEqual(quality.OPTIONS, expected_options[index])

            return [(b"",
                     dedent("""
            No config file found, using default configuration
            Usage:  pylint [options] module_or_package

              Check that a module satisfies a coding standard (and more !).

                pylint --help

              Display this help message and exit.

                pylint --help-msg <msg-id>[,<msg-id>]

              Display help messages about given message identifiers and exit.


            pylint: error: no such option: --msg-template
        """).encode('utf-8')), (b'\n', b'')][index]

        _mock_communicate.side_effect = side_effect
        quality.violations('file1.py')
        self.assertEqual([], quality.violations('file1.py'))
        self.assertEqual(quality.OPTIONS, quality.LEGACY_OPTIONS)
        self.assertEqual(_mock_communicate.call_count, 2)
Example #24
0
    def test_quality_error(self):

        # Patch the output stderr/stdout and returncode of `pylint`

        _mock_communicate = patch.object(subprocess, 'Popen').start()
        subproc_mock = MagicMock()
        subproc_mock.returncode = 1
        subproc_mock.communicate.return_value = (b'file1.py:1: [C0111] Missing docstring', b'oops')
        _mock_communicate.return_value = subproc_mock

        # Parse the report
        quality = PylintQualityReporter('pylint', [])

        # Expect an error
        self.assertRaises(QualityReporterError, quality.violations, 'file1.py')
Example #25
0
    def test_no_such_file(self):
        quality = PylintQualityReporter('pylint', [])

        # Expect that we get no results
        result = quality.violations('')
        self.assertEqual(result, [])
    def test_no_such_file(self):
        quality = PylintQualityReporter('pylint', [])

        # Expect that we get no results
        result = quality.violations('')
        self.assertEqual(result, [])