Skip to content

Commit f8e69ea

Browse files
committed
Merge branch 'windows-notepad'
* windows-notepad: Incorporate review feedback Add cross platform temporary file creation
2 parents 782e860 + 70d5e9a commit f8e69ea

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

awsshell/app.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"""
66
from __future__ import unicode_literals
77
import os
8-
import tempfile
98
import subprocess
109
import logging
1110
import sys
@@ -26,7 +25,7 @@
2625
from awsshell.keys import KeyManager
2726
from awsshell.style import StyleFactory
2827
from awsshell.toolbar import Toolbar
29-
from awsshell.utils import build_config_file_path
28+
from awsshell.utils import build_config_file_path, temporary_file
3029
from awsshell import compat
3130

3231

@@ -75,7 +74,7 @@ def run(self, command, application):
7574
all_commands = '\n'.join(
7675
['aws ' + h for h in list(application.history)
7776
if not h.startswith(('.', '!'))])
78-
with tempfile.NamedTemporaryFile('w') as f:
77+
with temporary_file('w') as f:
7978
f.write(all_commands)
8079
f.flush()
8180
editor = self._get_editor_command()

awsshell/utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
from __future__ import print_function
33
import os
44
import awscli
5+
import contextlib
6+
import tempfile
7+
import uuid
8+
import shutil
59

610
from awsshell.compat import HTMLParser
711

@@ -22,6 +26,28 @@ def build_config_file_path(file_name):
2226
return os.path.join(os.path.expanduser('~'), '.aws', 'shell', file_name)
2327

2428

29+
@contextlib.contextmanager
30+
def temporary_file(mode):
31+
"""Cross platform temporary file creation.
32+
33+
This is an alternative to ``tempfile.NamedTemporaryFile`` that
34+
also works on windows and avoids the "file being used by
35+
another process" error.
36+
"""
37+
tempdir = tempfile.gettempdir()
38+
basename = 'tmpfile-%s' % (uuid.uuid4())
39+
full_filename = os.path.join(tempdir, basename)
40+
if 'w' not in mode:
41+
# We need to create the file before we can open
42+
# it in 'r' mode.
43+
open(full_filename, 'w').close()
44+
try:
45+
with open(full_filename, mode) as f:
46+
yield f
47+
finally:
48+
os.remove(f.name)
49+
50+
2551
class DataOnly(HTMLParser):
2652
def __init__(self):
2753
# HTMLParser is an old-style class, which can't be used with super()

tests/unit/test_utils.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from awsshell.utils import FSLayer
77
from awsshell.utils import InMemoryFSLayer
88
from awsshell.utils import FileReadError
9+
from awsshell.utils import temporary_file
910

1011

1112
class TestFSLayer(unittest.TestCase):
@@ -64,3 +65,31 @@ def test_can_read_file_contents(self):
6465
def test_file_does_not_exist_error(self):
6566
with self.assertRaises(FileReadError):
6667
self.fslayer.file_contents('/tmp/thisdoesnot-exist.asdf')
68+
69+
70+
class TestTemporaryFile(unittest.TestCase):
71+
def test_can_use_as_context_manager(self):
72+
with temporary_file('w') as f:
73+
filename = f.name
74+
f.write("foobar")
75+
f.flush()
76+
self.assertEqual(open(filename).read(), "foobar")
77+
78+
def test_is_removed_after_exiting_context(self):
79+
with temporary_file('w') as f:
80+
filename = f.name
81+
f.write("foobar")
82+
f.flush()
83+
self.assertFalse(os.path.isfile(filename))
84+
85+
def test_can_open_in_read(self):
86+
with temporary_file('r') as f:
87+
filename = f.name
88+
assert f.read() == ''
89+
# Verify we can open the file again
90+
# in another file descriptor.
91+
with open(filename, 'w') as f2:
92+
f2.write("foobar")
93+
f.seek(0)
94+
assert f.read() == "foobar"
95+
self.assertFalse(os.path.isfile(filename))

0 commit comments

Comments
 (0)