Skip to content

Commit

Permalink
Handle case where setup name is referencing a variable that is a stri…
Browse files Browse the repository at this point in the history
…ng (#5905)

* Handle case where setup name is referencing a variable that is a string
  • Loading branch information
matteius committed Sep 6, 2023
1 parent 9b2e0d4 commit 072352a
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
1 change: 1 addition & 0 deletions news/5905.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Handle case better where setup.py name is referencing a variable that is a string while encouraging folks to migrate their projects to pyproject.toml
26 changes: 23 additions & 3 deletions pipenv/utils/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,23 @@ def parse_pkginfo_file(content: str):


def parse_setup_file(content):
# A dictionary to store variable names and their values
variables = {}
try:
tree = ast.parse(content)
for node in ast.walk(tree):
# Extract variable assignments and store them
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name):
if isinstance(node.value, ast.Str): # for Python versions < 3.8
variables[target.id] = node.value.s
elif isinstance(node.value, ast.Constant) and isinstance(
node.value.value, str
):
variables[target.id] = node.value.value

# Check function calls to extract the 'name' attribute from the setup function
if isinstance(node, ast.Call):
if (
getattr(node.func, "id", "") == "setup"
Expand All @@ -525,12 +539,20 @@ def parse_setup_file(content):
):
for keyword in node.keywords:
if keyword.arg == "name":
if isinstance(keyword.value, ast.Str):
# If it's a variable, retrieve its value
if (
isinstance(keyword.value, ast.Name)
and keyword.value.id in variables
):
return variables[keyword.value.id]
# Otherwise, check if it's directly provided
elif isinstance(keyword.value, ast.Str):
return keyword.value.s
elif isinstance(keyword.value, ast.Constant) and isinstance(
keyword.value.value, str
):
return keyword.value.value
# Additional handling for Python versions and specific ways of defining the name
elif sys.version_info < (3, 9) and isinstance(
keyword.value, ast.Subscript
):
Expand All @@ -546,14 +568,12 @@ def parse_setup_file(content):
elif sys.version_info >= (3, 9) and isinstance(
keyword.value, ast.Subscript
):
# If the name is a lookup in a dictionary, only handle the case where it's a static lookup
if (
isinstance(keyword.value.value, ast.Name)
and isinstance(keyword.value.slice, ast.Str)
and keyword.value.value.id == "about"
):
return keyword.value.slice.s

except ValueError:
pass # We will not exec unsafe code to determine the name pre-resolver

Expand Down

0 comments on commit 072352a

Please sign in to comment.