[BUG] When source tree contains a directory symlink, the directory is randomly packaged either as the original or symlink path
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- python
- Domain
- build-system
Research direction
Start with the pyproject.toml and MANIFEST.in reproduction, then run python -m build -s and inspect the generated archive and SOURCES.txt. Trace how the sdist handles the foo/a directory and foo/b symlink, including both creation orders. Done means the original directory remains at its original path consistently, with regression coverage for the reported case.
Written by the indexing model from the issue text.
Description
setuptools version
78.1.0
Python version
3.13.2
OS
Gentoo Linux amd64
Additional environment information
No response
Description
When the source tree contains a directory symlink such as b -> a, then setuptools randomly includes the directory as either a or b (and no symlink). The actual result seems to depend on the filesystem order: if the symlink is created first, then the original directory (i.e. a) is included in the sdist. However, if the symlink is created after the directory, the directory is included as b instead of a.
Expected behavior
I expected the original directory to be preserved in the source distribution at its original location. I don't have a hard opinion whether the symlink should be replaced by a copy of the directory, or be ignored — but it definitely shouldn't cause the original directory to disappear.
How to Reproduce
cat > pyproject.toml <<EOF
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "test"
version = "0"
EOF
echo "graft foo" > MANIFEST.in
mkdir -p foo/a
touch foo/a/{a,b,c}
ln -s a foo/b
python -m build -s
tar -tf dist/test-0.tar.gz
Output
$ python -m build -s
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
- setuptools
* Getting build dependencies for sdist...
running egg_info
writing test.egg-info/PKG-INFO
writing dependency_links to test.egg-info/dependency_links.txt
writing top-level names to test.egg-info/top_level.txt
reading manifest file 'test.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'test.egg-info/SOURCES.txt'
* Building sdist...
running sdist
running egg_info
writing test.egg-info/PKG-INFO
writing dependency_links to test.egg-info/dependency_links.txt
writing top-level names to test.egg-info/top_level.txt
reading manifest file 'test.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'test.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md
running check
creating test-0
creating test-0/foo/b
creating test-0/test.egg-info
copying files to test-0...
copying MANIFEST.in -> test-0
copying pyproject.toml -> test-0
copying foo/b/a -> test-0/foo/b
copying foo/b/b -> test-0/foo/b
copying foo/b/c -> test-0/foo/b
copying test.egg-info/PKG-INFO -> test-0/test.egg-info
copying test.egg-info/SOURCES.txt -> test-0/test.egg-info
copying test.egg-info/dependency_links.txt -> test-0/test.egg-info
copying test.egg-info/top_level.txt -> test-0/test.egg-info
copying test.egg-info/SOURCES.txt -> test-0/test.egg-info
Writing test-0/setup.cfg
Creating tar archive
removing 'test-0' (and everything under it)
Successfully built test-0.tar.gz
$ tar -tf dist/test-0.tar.gz
test-0/
test-0/MANIFEST.in
test-0/PKG-INFO
test-0/foo/
test-0/foo/b/
test-0/foo/b/a
test-0/foo/b/b
test-0/foo/b/c
test-0/pyproject.toml
test-0/setup.cfg
test-0/test.egg-info/
test-0/test.egg-info/PKG-INFO
test-0/test.egg-info/SOURCES.txt
test-0/test.egg-info/dependency_links.txt
test-0/test.egg-info/top_level.txt
- Dominant language
- Python
- Stars
- 2.9k
- Forks
- 1.4k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 1
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from pypa/setuptools
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
pypa/setuptools#5272 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
pypa/setuptools#5235 · 1 comment · 1 reaction ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
pypa/setuptools#5234 · 1 comment ·
-
bug Needs Triage
Difficulty 1/5 Under an hour Newbie friendliness 78/100
pypa/setuptools#4135 · 1 comment · 1 reaction ·
-
documentation Needs Triage
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
pypa/setuptools#2753 ·
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
bancolombia/sentinel#23 ·
-
test md OpenCI
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
bug client
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100