Skip to content

Commit

Permalink
Merge pull request #2046 from pypa/bugfix/1607-retain-executable-mode
Browse files Browse the repository at this point in the history
Retain executable mode
  • Loading branch information
jaraco committed Mar 25, 2020
2 parents e5a8bfe + ef3a386 commit 7e2f307
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog.d/2041.bugfix.rst
@@ -0,0 +1 @@
Preserve file modes during pkg files copying, but clear read only flag for target afterwards.
9 changes: 7 additions & 2 deletions setuptools/command/build_py.py
Expand Up @@ -7,6 +7,7 @@
import io
import distutils.errors
import itertools
import stat

from setuptools.extern import six
from setuptools.extern.six.moves import map, filter, filterfalse
Expand All @@ -20,6 +21,10 @@ def run_2to3(self, files, doctests=True):
"do nothing"


def make_writable(target):
os.chmod(target, os.stat(target).st_mode | stat.S_IWRITE)


class build_py(orig.build_py, Mixin2to3):
"""Enhanced 'build_py' command that includes data files with packages
Expand Down Expand Up @@ -120,8 +125,8 @@ def build_package_data(self):
target = os.path.join(build_dir, filename)
self.mkpath(os.path.dirname(target))
srcfile = os.path.join(src_dir, filename)
outf, copied = self.copy_file(
srcfile, target, preserve_mode=False)
outf, copied = self.copy_file(srcfile, target)
make_writable(target)
srcfile = os.path.abspath(srcfile)
if (copied and
srcfile in self.distribution.convert_2to3_doctests):
Expand Down
41 changes: 38 additions & 3 deletions setuptools/tests/test_build_py.py
Expand Up @@ -2,6 +2,8 @@
import stat
import shutil

import pytest

from setuptools.dist import Distribution


Expand All @@ -26,9 +28,10 @@ def test_directories_in_package_data_glob(tmpdir_cwd):

def test_read_only(tmpdir_cwd):
"""
Ensure mode is not preserved in copy for package modules
and package data, as that causes problems
with deleting read-only files on Windows.
Ensure read-only flag is not preserved in copy
for package modules and package data, as that
causes problems with deleting read-only files on
Windows.
#1451
"""
Expand All @@ -47,3 +50,35 @@ def test_read_only(tmpdir_cwd):
dist.parse_command_line()
dist.run_commands()
shutil.rmtree('build')


@pytest.mark.xfail(
'platform.system() == "Windows"',
reason="On Windows, files do not have executable bits",
raises=AssertionError,
strict=True,
)
def test_executable_data(tmpdir_cwd):
"""
Ensure executable bit is preserved in copy for
package data, as users rely on it for scripts.
#2041
"""
dist = Distribution(dict(
script_name='setup.py',
script_args=['build_py'],
packages=['pkg'],
package_data={'pkg': ['run-me']},
name='pkg',
))
os.makedirs('pkg')
open('pkg/__init__.py', 'w').close()
open('pkg/run-me', 'w').close()
os.chmod('pkg/run-me', 0o700)

dist.parse_command_line()
dist.run_commands()

assert os.stat('build/lib/pkg/run-me').st_mode & stat.S_IEXEC, \
"Script is not executable"

0 comments on commit 7e2f307

Please sign in to comment.