##// END OF EJS Templates
atomictempfile: avoid infinite recursion in __del__()....
Greg Ward -
r14007:d764463b default
parent child Browse files
Show More
@@ -0,0 +1,49 b''
1 import os
2 import glob
3 from mercurial.util import atomictempfile
4
5 # basic usage
6 def test1_simple():
7 if os.path.exists('foo'):
8 os.remove('foo')
9 file = atomictempfile('foo')
10 (dir, basename) = os.path.split(file._tempname)
11 assert not os.path.isfile('foo')
12 assert basename in glob.glob('.foo-*')
13
14 file.write('argh\n')
15 file.rename()
16
17 assert os.path.isfile('foo')
18 assert basename not in glob.glob('.foo-*')
19 print 'OK'
20
21 # close() removes the temp file but does not make the write
22 # permanent -- essentially discards your work (WTF?!)
23 def test2_close():
24 if os.path.exists('foo'):
25 os.remove('foo')
26 file = atomictempfile('foo')
27 (dir, basename) = os.path.split(file._tempname)
28
29 file.write('yo\n')
30 file.close()
31
32 assert not os.path.isfile('foo')
33 assert basename not in os.listdir('.')
34 print 'OK'
35
36 # if a programmer screws up and passes bad args to atomictempfile, they
37 # get a plain ordinary TypeError, not infinite recursion
38 def test3_oops():
39 try:
40 file = atomictempfile()
41 except TypeError:
42 print "OK"
43 else:
44 print "expected TypeError"
45
46 if __name__ == '__main__':
47 test1_simple()
48 test2_close()
49 test3_oops()
@@ -0,0 +1,3 b''
1 OK
2 OK
3 OK
@@ -726,31 +726,31 b' class atomictempfile(object):'
726 name, making the changes visible.
726 name, making the changes visible.
727 """
727 """
728 def __init__(self, name, mode='w+b', createmode=None):
728 def __init__(self, name, mode='w+b', createmode=None):
729 self.__name = name
729 self.__name = name # permanent name
730 self._fp = None
730 self._tempname = mktempcopy(name, emptyok=('w' in mode),
731 self.temp = mktempcopy(name, emptyok=('w' in mode),
731 createmode=createmode)
732 createmode=createmode)
732 self._fp = posixfile(self._tempname, mode)
733 self._fp = posixfile(self.temp, mode)
734
733
735 def __getattr__(self, name):
734 # delegated methods
736 return getattr(self._fp, name)
735 self.write = self._fp.write
736 self.fileno = self._fp.fileno
737
737
738 def rename(self):
738 def rename(self):
739 if not self._fp.closed:
739 if not self._fp.closed:
740 self._fp.close()
740 self._fp.close()
741 rename(self.temp, localpath(self.__name))
741 rename(self._tempname, localpath(self.__name))
742
742
743 def close(self):
743 def close(self):
744 if not self._fp:
745 return
746 if not self._fp.closed:
744 if not self._fp.closed:
747 try:
745 try:
748 os.unlink(self.temp)
746 os.unlink(self._tempname)
749 except: pass
747 except OSError:
748 pass
750 self._fp.close()
749 self._fp.close()
751
750
752 def __del__(self):
751 def __del__(self):
753 self.close()
752 if hasattr(self, '_fp'): # constructor actually did something
753 self.close()
754
754
755 def makedirs(name, mode=None):
755 def makedirs(name, mode=None):
756 """recursive directory creation with parent mode inheritance"""
756 """recursive directory creation with parent mode inheritance"""
General Comments 0
You need to be logged in to leave comments. Login now