diff options
author | malthe <devnull@localhost> | 2014-07-08 10:48:29 +0200 |
---|---|---|
committer | malthe <devnull@localhost> | 2014-07-08 10:48:29 +0200 |
commit | 1c580ae5ae23e64bfffd7597a8336d26017765cb (patch) | |
tree | 72197e0fbf30449fb11eeb8a71b23fd8dc830fd0 | |
parent | 159e2abd981ea16b3594a476a44f25358a9a96d9 (diff) | |
download | wheel-use-temporary-file-and-rename-with-force.tar.gz |
Write to temporary file and then rename when using --force.use-temporary-file-and-rename-with-force
-rw-r--r-- | CHANGES.txt | 6 | ||||
-rw-r--r-- | wheel/install.py | 37 | ||||
-rw-r--r-- | wheel/test/test_install.py | 21 |
3 files changed, 41 insertions, 23 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 26754c9..e6beb32 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,9 @@ +In next release ... + +- When force is given, write to temporary file and rename. This is + necessary because when a file exists, it may already be in use by a + running process. + 0.24.0 ====== - The python tag used for pure-python packages is now .pyN (major version diff --git a/wheel/install.py b/wheel/install.py index 3af6d0c..768fec4 100644 --- a/wheel/install.py +++ b/wheel/install.py @@ -335,25 +335,36 @@ class WheelFile(object): record_name = self.distinfo_name + '/RECORD' for info, (key, target, filename, dest) in name_trans.items(): name = info.filename - source = self.zipfile.open(info) - # Skip the RECORD file - if name == record_name: - continue ddir = os.path.dirname(dest) if not os.path.isdir(ddir): os.makedirs(ddir) - destination = HashingFile(open(dest, 'wb')) - if key == 'scripts': - hashbang = source.readline() - if hashbang.startswith(b'#!python'): - hashbang = b'#!' + exename + binary(os.linesep) - destination.write(hashbang) - shutil.copyfileobj(source, destination) + + if force: + dest = "{0}.tmp".format(dest) + + with self.zipfile.open(info) as source, open(dest, 'wb') as f: + destination = HashingFile(f) + + # Skip the RECORD file + if name == record_name: + continue + + if key == 'scripts': + hashbang = source.readline() + if hashbang.startswith(b'#!python'): + hashbang = b'#!' + exename + binary(os.linesep) + destination.write(hashbang) + shutil.copyfileobj(source, destination) + + if force: + tmp = dest + dest = dest[:-4] + os.rename(tmp, dest) + reldest = os.path.relpath(dest, root) reldest.replace(os.sep, '/') record_data.append((reldest, destination.digest(), destination.length)) - destination.close() - source.close() + # preserve attributes (especially +x bit for scripts) attrs = info.external_attr >> 16 if attrs: # tends to be 0 if Windows. diff --git a/wheel/test/test_install.py b/wheel/test/test_install.py index ddcddf5..ff76c18 100644 --- a/wheel/test/test_install.py +++ b/wheel/test/test_install.py @@ -36,15 +36,16 @@ def test_install(): for key in ('purelib', 'platlib', 'scripts', 'headers', 'data'):
locs[key] = os.path.join(tempdir, key)
os.mkdir(locs[key])
- whl.install(overrides=locs)
- assert len(os.listdir(locs['purelib'])) == 0
- assert check(locs['platlib'], 'hello.pyd')
- assert check(locs['platlib'], 'hello', 'hello.py')
- assert check(locs['platlib'], 'hello', '__init__.py')
- assert check(locs['data'], 'hello.dat')
- assert check(locs['headers'], 'hello.dat')
- assert check(locs['scripts'], 'hello.sh')
- assert check(locs['platlib'], 'test-1.0.dist-info', 'RECORD')
+ for force in (False, True):
+ whl.install(force=force, overrides=locs)
+ assert len(os.listdir(locs['purelib'])) == 0
+ assert check(locs['platlib'], 'hello.pyd')
+ assert check(locs['platlib'], 'hello', 'hello.py')
+ assert check(locs['platlib'], 'hello', '__init__.py')
+ assert check(locs['data'], 'hello.dat')
+ assert check(locs['headers'], 'hello.dat')
+ assert check(locs['scripts'], 'hello.sh')
+ assert check(locs['platlib'], 'test-1.0.dist-info', 'RECORD')
finally:
shutil.rmtree(tempdir)
@@ -52,4 +53,4 @@ def test_install_tool(): """Slightly improve coverage of wheel.install"""
wheel.tool.install([TESTWHEEL], force=True, dry_run=True)
-
\ No newline at end of file +
|