[py-svn] r18055 - in py/dist/py/path/local: . testing

arigo at codespeak.net arigo at codespeak.net
Sat Oct 1 16:07:05 CEST 2005


Author: arigo
Date: Sat Oct  1 16:06:58 2005
New Revision: 18055

Modified:
   py/dist/py/path/local/local.py
   py/dist/py/path/local/testing/test_local.py
Log:
Lock the numbered temporary directories while they are in use.
Strategy: '.lock' files in the temporary directory, removed at
process exit, but ignored if it's more than 2 days old.


Modified: py/dist/py/path/local/local.py
==============================================================================
--- py/dist/py/path/local/local.py	(original)
+++ py/dist/py/path/local/local.py	Sat Oct  1 16:06:58 2005
@@ -6,7 +6,7 @@
 
 """
 from __future__ import generators
-import sys, os, stat, re
+import sys, os, stat, re, atexit
 import py
 from py.__.path import common
 
@@ -535,7 +535,8 @@
         raise py.error.ENOENT(dpath, "could not create tempdir, %d tries" % tries)
     mkdtemp = classmethod(mkdtemp)
 
-    def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3):
+    def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3,
+                          lock_timeout = 172800):   # two days
         """ return unique directory with a number greater than the current
             maximum one.  The number is assumed to start directly after prefix.
             if keep is true directories with a number less than (maxnum-keep)
@@ -564,11 +565,33 @@
         # make the new directory
         udir = rootdir.mkdir(prefix + str(maxnum+1))
 
+        # put a .lock file in the new directory that will be removed at
+        # process exit
+        lockfile = udir.join('.lock')
+        if hasattr(lockfile, 'mksymlinkto'):
+            lockfile.mksymlinkto(str(os.getpid()))
+        else:
+            lockfile.write(str(os.getpid()))
+        def try_remove_lockfile():
+            try:
+                lockfile.remove()
+            except py.error.Error:
+                pass
+        atexit.register(try_remove_lockfile)
+
         # prune old directories
         if keep:
             for path in rootdir.listdir():
                 num = parse_num(path)
                 if num is not None and num <= (maxnum - keep):
+                    lf = path.join('.lock')
+                    try:
+                        t1 = lf.lstat().mtime
+                        t2 = lockfile.lstat().mtime
+                        if abs(t2-t1) < lock_timeout:
+                            continue   # skip directories still locked
+                    except py.error.Error:
+                        pass   # assume that it means that there is no 'lf'
                     try:
                         path.remove(rec=1)
                     except py.error.Error: 

Modified: py/dist/py/path/local/testing/test_local.py
==============================================================================
--- py/dist/py/path/local/testing/test_local.py	(original)
+++ py/dist/py/path/local/testing/test_local.py	Sat Oct  1 16:06:58 2005
@@ -192,7 +192,8 @@
         root = self.tmpdir
         root.ensure('base.not_an_int', dir=1)
         for i in range(10):
-            numdir = local.make_numbered_dir(prefix='base.', rootdir=root, keep=2)
+            numdir = local.make_numbered_dir(prefix='base.', rootdir=root,
+                                             keep=2, lock_timeout=0)
             assert numdir.check()
             assert numdir.basename == 'base.%d' %i
             if i>=1:
@@ -202,6 +203,16 @@
             if i>=3:
                 assert not numdir.new(ext=str(i-3)).check()
 
+    def test_locked_make_numbered_dir(self):
+        root = self.tmpdir
+        for i in range(10):
+            numdir = local.make_numbered_dir(prefix='base.', rootdir=root,
+                                             keep=2)
+            assert numdir.check()
+            assert numdir.basename == 'base.%d' %i
+            for j in range(i):
+                assert numdir.new(ext=str(j)).check()
+
     def test_error_preservation(self):
         py.test.raises (EnvironmentError, self.root.join('qwoeqiwe').mtime)
         py.test.raises (EnvironmentError, self.root.join('qwoeqiwe').read)



More information about the pytest-commit mailing list