Closed
Description
Describe the bug
FalwtyDeps fails when run on s3transfer package.
The problem is with the way dependencies are declared in setup.py.
Minimal not-working example of setup.py:
from setuptools import setup
setup(
extras_require={
'crt1': 'botocore>=1.33.2,<2.0a.0', # FawltyDeps fails
'crt2': 'botocore[crt]', # FawltyDeps fails
'crt3': ['botocore'], # FawltyDeps works
},
)
To Reproduce
Download s3transfer package and run:
fawltydeps
from arbitrary environment.
Expected behavior
Minimal expectation: FawltyDeps informs of the problem and does not crash.
Ideal outcome: FalwtyDeps handles setup.py
cases like the above.
Environment
- OS name + version: Ubuntu 22.04 LTS
- Version of the code: 0.15.0
Additional context
(fawltydeps-py3.10) ➜ s3transfer git:(master) fawltydeps
WARNING:fawltydeps.limited_eval:Unable to resolve Call(func=Attribute(value=Attribute(value=Name(id='os', ctx=Load()), attr='path', ctx=Load()), attr='dirname', ctx=Load()), args=[Name(id='__file__', ctx=Load())], keywords=[]) from os.path.dirname(__file__) @ setup.py:7
WARNING:fawltydeps.limited_eval:Failed to parse assignment of 'ROOT': Call(func=Attribute(value=Attribute(value=Name(id='os', ctx=Load()), attr='path', ctx=Load()), attr='dirname', ctx=Load()), args=[Name(id='__file__', ctx=Load())], keywords=[]) from os.path.dirname(__file__) @ setup.py:7
WARNING:fawltydeps.limited_eval:Unable to resolve Call(func=Attribute(value=Name(id='re', ctx=Load()), attr='compile', ctx=Load()), args=[Constant(value='__version__ = [\'"]([0-9.]+)[\'"]')], keywords=[]) from re.compile('__version__ = [\'"]([0-9.]+)[\'"]') @ setup.py:8
WARNING:fawltydeps.limited_eval:Failed to parse assignment of 'VERSION_RE': Call(func=Attribute(value=Name(id='re', ctx=Load()), attr='compile', ctx=Load()), args=[Constant(value='__version__ = [\'"]([0-9.]+)[\'"]')], keywords=[]) from re.compile('__version__ = [\'"]([0-9.]+)[\'"]') @ setup.py:8
Traceback (most recent call last):
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/requirements.py", line 35, in __init__
parsed = _parse_requirement(requirement_string)
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_parser.py", line 64, in parse_requirement
return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES))
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_parser.py", line 73, in _parse_requirement
name_token = tokenizer.expect(
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_tokenizer.py", line 140, in expect
raise self.raise_syntax_error(f"Expected {expected}")
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/_tokenizer.py", line 165, in raise_syntax_error
raise ParserSyntaxError(
pkg_resources.extern.packaging._tokenizer.ParserSyntaxError: Expected package name at the start of dependency specifier
[
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/bin/fawltydeps", line 6, in <module>
sys.exit(main())
File "/tmp/FawltyDeps/fawltydeps/main.py", line 368, in main
analysis = Analysis.create(settings, stdin)
File "/tmp/FawltyDeps/fawltydeps/main.py", line 194, in create
ret.undeclared_deps # pylint: disable=pointless-statement
File "/tmp/FawltyDeps/fawltydeps/utils.py", line 72, in wrapper
calculated: T = method(self)
File "/tmp/FawltyDeps/fawltydeps/main.py", line 162, in undeclared_deps
return calculate_undeclared(self.imports, self.resolved_deps, self.settings)
File "/tmp/FawltyDeps/fawltydeps/utils.py", line 72, in wrapper
calculated: T = method(self)
File "/tmp/FawltyDeps/fawltydeps/main.py", line 148, in resolved_deps
(dep.name for dep in self.declared_deps),
File "/tmp/FawltyDeps/fawltydeps/utils.py", line 72, in wrapper
calculated: T = method(self)
File "/tmp/FawltyDeps/fawltydeps/main.py", line 136, in declared_deps
return list(
File "/tmp/FawltyDeps/fawltydeps/extract_declared_dependencies.py", line 423, in parse_sources
yield from parse_source(source)
File "/tmp/FawltyDeps/fawltydeps/extract_declared_dependencies.py", line 414, in parse_source
yield from parser.execute(src.path)
File "/tmp/FawltyDeps/fawltydeps/extract_declared_dependencies.py", line 123, in parse_setup_py
yield from _extract_deps_from_setup_call(node.value) # type: ignore
File "/tmp/FawltyDeps/fawltydeps/extract_declared_dependencies.py", line 98, in _extract_deps_from_setup_call
yield parse_one_req(item, source)
File "/tmp/FawltyDeps/fawltydeps/extract_declared_dependencies.py", line 50, in parse_one_req
req = Requirement.parse(req_text)
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/__init__.py", line 3212, in parse
(req,) = parse_requirements(s)
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/__init__.py", line 3171, in __init__
super(Requirement, self).__init__(requirement_string)
File "/home/mknorps/.cache/pypoetry/virtualenvs/fawltydeps-88kNcXzg-py3.10/lib/python3.10/site-packages/pkg_resources/_vendor/packaging/requirements.py", line 37, in __init__
raise InvalidRequirement(str(e)) from e
pkg_resources.extern.packaging.requirements.InvalidRequirement: Expected package name at the start of dependency specifier
[
^