diff --git a/bear-requirements.txt b/bear-requirements.txt index 0d1605367d..51e610bf0a 100644 --- a/bear-requirements.txt +++ b/bear-requirements.txt @@ -29,3 +29,4 @@ vim-vint~=0.3.10 vulture~=0.10.0 yamllint~=1.5 yapf~=0.14.0 +check-manifest~=0.34 diff --git a/bears/general/CheckmanifestBear.py b/bears/general/CheckmanifestBear.py new file mode 100644 index 0000000000..5f50c4517a --- /dev/null +++ b/bears/general/CheckmanifestBear.py @@ -0,0 +1,63 @@ +import os + +from coalib.bearlib.abstractions.Linter import linter +from dependency_management.requirements.PipRequirement import PipRequirement +from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY +from coalib.bears.GlobalBear import GlobalBear +from coalib.results.Result import Result +from coalib.misc.Shell import run_shell_command +from coalib.results.Diff import Diff + + +class CheckmanifestBear(GlobalBear): + """ + Check MANIFEST.in in a Python source package for completeness + + Check https://pypi.python.org/pypi/rstcheck for more information. + """ + + LANGUAGES = {'Python MANIFEST.in'} + REQUIREMENTS = {PipRequirement('check-manifest', '0.34')} + AUTHORS = {'The coala developers'} + AUTHORS_EMAILS = {'coala-devel@googlegroups.com'} + LICENSE = 'AGPL-3.0' + CAN_DETECT = {'Redundancy'} + EXECUTABLE = 'check-manifest' + + def run(self, ignore: list=[]): + """ + Check MANIFEST.in in a Python source package for completeness + + Check https://pypi.python.org/pypi/rstcheck for more information. + + :param ignore: + ignore files/directories matching these comma- + separated patterns + """ + args = '' + if ignore: + args = ('--ignore=' + + ','.join(ignore),) + + output_message = 'suggested MANIFEST.in rules:' + output, _ = run_shell_command( + (self.EXECUTABLE,) + tuple(args) + + tuple(os.path.dirname(filename) + for filename in self.file_dict.keys())) + to_search = output_message+'\n' + + temp_output = output.splitlines(1) + if to_search in temp_output: + index = temp_output.index(to_search) + new_output = temp_output[index+1:] + final_output = [x.strip(' ') for x in new_output] + else: + final_output = '' + # Ignore LineLengthBear + output_message = 'lists of files in version control and sdist match!' + + a = Diff(list(self.file_dict.values())[0]) + a.add_lines(len(list(self.file_dict.values())[0]), final_output) + + yield Result(self, output_message, + diffs={list(self.file_dict.keys())[0]: a}) diff --git a/tests/general/CheckmanifestBearTest.py b/tests/general/CheckmanifestBearTest.py new file mode 100644 index 0000000000..d08688eca3 --- /dev/null +++ b/tests/general/CheckmanifestBearTest.py @@ -0,0 +1,72 @@ +import shutil +import tempfile +import platform +import stat +import os +from os import path + +import unittest +from queue import Queue +from coalib.settings.Section import Section +from coalib.misc.Shell import run_shell_command +from bears.general.CheckmanifestBear import CheckmanifestBear + + +class CheckmanifestBearTest(unittest.TestCase): + + @staticmethod + def run_git_command(*args, stdin=None): + run_shell_command(' '.join(('git',) + args), stdin) + + @staticmethod + def _windows_rmtree_remove_readonly(func, path, excinfo): + os.chmod(path, stat.S_IWRITE) + func(path) + + def setUp(self): + self.queue = Queue() + self.file_dict = {} + self.section = Section('Checkmanifest') + self.uut = CheckmanifestBear(self.file_dict, self.section, + self.queue) + self._old_cwd = os.getcwd() + self.test_dir = tempfile.mkdtemp() + with open(path.join(self.test_dir, 'setup.py'), 'w') as f: + f.write('from setuptools import setup\n') + f.write("setup(name='sample', py_modules=['sample'])\n") + f.close() + with open(path.join(self.test_dir, 'sample.py'), 'w') as f: + f.write('# wow. such code. so amaze\n') + f.close() + + f = open(path.join(self.test_dir, 'MANIFEST.in'), 'w') + f.close() + f = open(path.join(self.test_dir, 'unrelated.txt'), 'w') + f.write('Hello from the other side') + f.close() + f = open(path.join(self.test_dir, 'rishu.cpp'), 'w') + f.write('int main') + f.close() + os.chdir(self.test_dir) + self.run_git_command('init') + self.run_git_command('config', 'user.email coala@coala.io') + self.run_git_command('config', 'user.name coala') + self.run_git_command('add', '--all') + + def tearDown(self): + os.chdir(self._old_cwd) + if platform.system() == 'Windows': + onerror = self._windows_rmtree_remove_readonly + else: + onerror = None + shutil.rmtree(self.test_dir, onerror=onerror) + + def run_uut(self, *args, **kwargs): + return list(result.message for result in self.uut.run(*args, **kwargs)) + + def test_something(self): + self.uut.file_dict = {path.join(self.test_dir, 'MANIFEST.in'): + ''} + self.assertEqual(self.run_uut(ignore=['unrelated.txt', 'rishu.cpp']), + ['lists of files in version control and sdist match!']) # Ignore LineLengthBear + self.assertNotEqual(self.run_uut(), [])