Welcome, guest | Sign In | My Account | Store | Cart
```"""
find a unique name based on a prefix for a content in a container
(eg. a file in a directory) adding a digit to the name

Does it in log2(n) + log2(n/2) were n is the number of duplicates
"""

def go_down(name, exists, lower, upper):
"""bisection to find first free slot
"""
if upper - lower < 2:
if exists(name + '-%d' % lower):
return name + '-%d' % upper
else:
return name + '-%d' % lower
else:
mid = (upper + lower) // 2
if exists(name + '-%d' % mid):
return go_down(name, exists, mid, upper)
else:
return go_down(name, exists, lower, mid)

def go_up(name, exists, n):
"""find a free slot in log2(n) time
"""
if exists(name + '-%d' % n):
return go_up(name, exists, n * 2)
else:
# NOTE : 'or 1' for we don't want <name>-0
return go_down(name, exists, n // 2 or 1, n)

def getname(name, exists):
"""return a unique name, using name as suffix

exists is a function that will test existence
"""
if not exists(name):
return name
else:
return  go_up(name, exists, 1)

if __name__ == '__main__':
# quick test
import os
import glob
import tempfile
import shutil
cwd = os.getcwd()
tmpdir = tempfile.mkdtemp()
try:
os.chdir(tmpdir)
for i in xrange(50):
name = getname('a', os.path.exists)
with open(name, 'w') as f:
f.write(str(i))
# verify (do not verify 0 as it is a special case)
assert set(glob.glob('a-*')) == set('a-%d' % i for i in xrange(1, 50))
# verify content to assert order of allocation was correct
for i in xrange(1, 50):
with open('a-%d' % i) as f: