-
Notifications
You must be signed in to change notification settings - Fork 580
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bears/python: Add RequirementsCheckBear
Closes #1113
- Loading branch information
Showing
7 changed files
with
141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import os.path | ||
|
||
from coalib.bears.GlobalBear import GlobalBear | ||
from coalib.results.Result import Result, RESULT_SEVERITY | ||
from sarge import capture_both | ||
|
||
from dependency_management.requirements.PipRequirement import PipRequirement | ||
|
||
|
||
class RequirementsCheckBear(GlobalBear): | ||
""" | ||
The bear to check and find any conflicting pip dependencies. | ||
""" | ||
LANGUAGES = { | ||
'Python Requirements', | ||
'Python 2 Requirements', | ||
'Python 3 Requirements', | ||
} | ||
REQUIREMENTS = {PipRequirement('pip-tools', '3.8.0')} | ||
AUTHORS = {'The coala developers'} | ||
AUTHORS_EMAILS = {'[email protected]'} | ||
LICENSE = 'AGPL-3.0' | ||
|
||
def run(self, require_files: tuple): | ||
""" | ||
:param require_files: | ||
Tuple of requirements files. | ||
""" | ||
data = '' | ||
orig_file = '' | ||
|
||
for require_file in require_files: | ||
if not os.path.isfile(os.path.abspath(require_file)): | ||
raise ValueError('The file \'{}\' doesn\'t exist.' | ||
.format(require_file)) | ||
|
||
with open(require_file) as _file: | ||
content = _file.read() | ||
if not orig_file: | ||
orig_file = content | ||
else: | ||
data += content | ||
|
||
with open(require_files[0], 'a+') as temp_file: | ||
temp_file.write(data) | ||
|
||
out = capture_both('pip-compile {} -r -n --no-annotate --no-header ' | ||
'--no-index --allow-unsafe'.format(require_files[0])) | ||
|
||
if out.stderr.text and not out.stdout.text: | ||
pip_warning = 'Cache entry deserialization failed, entry ignored' | ||
lines = out.stderr.text.splitlines() | ||
lines = [line for line in lines if line not in pip_warning] | ||
yield Result(self, | ||
message=lines[0], | ||
severity=RESULT_SEVERITY.MAJOR, | ||
) | ||
|
||
with open(require_files[0], 'w+') as _file: | ||
_file.write(orig_file) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import os | ||
import unittest | ||
|
||
from queue import Queue | ||
|
||
from bears.python.requirements.RequirementsCheckBear import ( | ||
RequirementsCheckBear) | ||
from coalib.results.Result import Result, RESULT_SEVERITY | ||
from coalib.settings.Section import Section | ||
from coalib.settings.Setting import Setting | ||
|
||
|
||
def get_absolute_test_path(file): | ||
return os.path.join(os.path.dirname(__file__), | ||
'requirements_test_files', file) | ||
|
||
|
||
def read_file(file): | ||
with open(file) as _file: | ||
return _file.read() | ||
|
||
|
||
class RequirementsCheckBearTest(unittest.TestCase): | ||
|
||
def setUp(self): | ||
self.section = Section('') | ||
self.file_dict = {} | ||
self.queue = Queue() | ||
self.test_files = [get_absolute_test_path('conflict.txt'), | ||
get_absolute_test_path('valid.txt')] | ||
self.files = [read_file(_file) for _file in self.test_files] | ||
|
||
def test_conflicted_file(self): | ||
self.section.append(Setting('require_files', self.test_files[0])) | ||
self.uut = RequirementsCheckBear({}, self.section, self.queue) | ||
result = list(self.uut.run_bear_from_section([], {})) | ||
self.assertEqual(result[0], | ||
Result(origin='RequirementsCheckBear', | ||
message=('Could not find a version that ' | ||
'matches six<=1.11.0,==1.12.0'), | ||
severity=RESULT_SEVERITY.MAJOR)) | ||
self.assertEqual(read_file(self.test_files[0]), self.files[0]) | ||
|
||
def test_valid_file(self): | ||
self.section.append(Setting('require_files', self.test_files[1])) | ||
self.uut = RequirementsCheckBear({}, self.section, self.queue) | ||
result = list(self.uut.run_bear_from_section([], {})) | ||
self.assertEqual(result, []) | ||
self.assertEqual(read_file(self.test_files[1]), self.files[1]) | ||
|
||
def test_multiple_require_files(self): | ||
self.section.append(Setting('require_files', | ||
','.join(file for file in self.test_files))) | ||
self.uut = RequirementsCheckBear({}, self.section, self.queue) | ||
result = list(self.uut.run_bear_from_section([], {})) | ||
self.assertEqual(result[0], | ||
Result(origin='RequirementsCheckBear', | ||
message=('Could not find a version that ' | ||
'matches six<=1.11.0,==1.12.0'), | ||
severity=RESULT_SEVERITY.MAJOR)) | ||
self.assertEqual(read_file(self.test_files[0]), self.files[0]) | ||
self.assertEqual(read_file(self.test_files[1]), self.files[1]) | ||
|
||
def test_no_existing_file(self): | ||
invalid_test_file_path = get_absolute_test_path('invalid.txt') | ||
self.section.append(Setting('require_files', invalid_test_file_path)) | ||
self.uut = RequirementsCheckBear({}, self.section, self.queue) | ||
error = ('The file \'{}\' doesn\'t exist.' | ||
.format(invalid_test_file_path)) | ||
with self.assertRaisesRegex(ValueError, error): | ||
list(self.uut.run_bear_from_section([], {})) |
2 changes: 2 additions & 0 deletions
2
tests/python/requirements/requirements_test_files/conflict.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
six==1.12.0 | ||
six<=1.11.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pytest~=3.6.4 |