diff --git a/LICENSE.txt b/LICENSE.txt index 43d79e9..d8a7c3a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2017 Arkadiusz Bokowy +Copyright (c) 2017-2018 Arkadiusz Bokowy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.rst b/README.rst index 370f30d..5e654a9 100644 --- a/README.rst +++ b/README.rst @@ -14,7 +14,8 @@ Important notice In order to collect project's dependencies, this checker evaluates Python code from the ``setup.py`` file stored in the project's root directory. Code evaluation is done with the -`eval() `_ function. +`eval() `_ function. As a fall-back +method, this checker also tries to load dependencies from the ``requirements.txt`` file. At this point it is very important to be aware of the consequences of the above approach. One might inject malicious code into the ``setup.py`` file, which will be executed by this checker. diff --git a/src/flake8_requirements/checker.py b/src/flake8_requirements/checker.py index a54fb26..ba4adc3 100644 --- a/src/flake8_requirements/checker.py +++ b/src/flake8_requirements/checker.py @@ -13,7 +13,7 @@ from .modules import STDLIB_PY3 # NOTE: Changing this number will alter package version as well. -__version__ = "1.0.0" +__version__ = "1.1.0" __license__ = "MIT" LOG = getLogger('flake8.plugin.requires') @@ -256,6 +256,7 @@ def __init__(self, tree, filename, lines=None): self.tree = tree self.filename = filename self.lines = lines + self.requirements = self.get_requirements() self.setup = self.get_setup() @classmethod @@ -284,6 +285,17 @@ def parse_options(cls, options): ] } + @classmethod + @memoize + def get_requirements(cls): + """Get package requirements.""" + try: + with open("requirements.txt") as f: + return tuple(parse_requirements(f.readlines())) + except IOError as e: + LOG.debug("Couldn't open requirements file: %s", e) + return () + @classmethod @memoize def get_setup(cls): @@ -325,10 +337,13 @@ def modcmp(lib=(), test=()): modules = self.known_modules[modules[0]] mods_1st_party.update(split(x) for x in modules) - requirements = self.setup.get_requirements( - setup=self.processing_setup_py, - tests=True, - ) + requirements = self.requirements + if self.setup.redirected: + # Use requirements from setup if available. + requirements = self.setup.get_requirements( + setup=self.processing_setup_py, + tests=True, + ) # Get 3rd party module names based on requirements. for requirement in requirements: diff --git a/test/test_checker.py b/test/test_checker.py index ad81b7e..ac317f5 100644 --- a/test/test_checker.py +++ b/test/test_checker.py @@ -7,6 +7,7 @@ class SetupVisitorMock(checker.SetupVisitor): def __init__(self): + self.redirected = True self.keywords = { 'name': "flake8-requires", 'install_requires': [