File: mergeall-products/unzipped/docetc/miscnotes/Windows-path-limits/windows-path-limits.py

#!/usr/bin/env python3
"""
--------------------------------------------------------------------------------
Isolate and verify the actual path-length limits on Windows.
See the corresponding output text file here for results.

Note that all paths here use _characters_, not bytes, strongly
sugggesting that length limits are not subject to any expansions
required for Unicode encodings.

Also note that relative path limits are _less_ than those of abs
paths, but correspond exactly to the lenth of their abs paths
forms (i.e., the lengths of the rel path + the CWD prefix).  To
check lengths against the limits, code must use absolute paths.
--------------------------------------------------------------------------------
"""

import os, shutil
PREFIX = '\\\\?\\'


def TEST(root, rel=False):

    def prefix(path):
        if not rel:
            return PREFIX + path
        else:
            return PREFIX + os.path.abspath(path)
        
    #------------------------------------------------------------------------------
    # DIRS
    #------------------------------------------------------------------------------

    print()
    print('MAKE DIRS')
    path = root
    while True:
        try:
            path += 'x'            # up to 255 for component > 247 dirpath limit
            os.mkdir(path)
        except:
            print(' os.mkdir failed at len=%d chars' % len(path))
            print('\tadding len=', end='')
            for i in range(15):
                print('%d ' % len(path), end='')
                os.mkdir(prefix(path))            # add longer paths for more 
                path += 'x'
            print()
            break

    print('ACCESS DIRS')
    for func in(os.path.isdir, os.listdir, os.lstat):
        path = root
        while True:
            try:
                path += 'x'
                res = func(path)
                if res == False and func is os.path.isdir:    # False on fail
                    raise OSError
            except:
                print(' %s failed at len=%d chars' %
                      (getattr(func, '__name__', func), len(path)))
                break

    print('ACCESS DIRS WITH PREFIX')
    for func in(os.path.isdir, os.listdir, os.lstat):
        path = root
        while True:
            try:
                path += 'x'
                res = func(prefix(path))
                if res == False and func is os.path.isdir:
                    raise OSError
            except:
                print(' %s failed at len=%d chars' %
                      (getattr(func, '__name__', func), len(path)))
                break

    #------------------------------------------------------------------------------
    # FILES
    #------------------------------------------------------------------------------

    print()
    print('MAKE FILES')
    path = root
    while True:
        try:
            path += 'f' 
            f = open(path, 'w')
            f.write('spam')
            f.close()
        except:
            print(' open failed at len=%d chars' % len(path))
            print('\tadding len=', end='')
            for i in range(15):
                print('%d ' % len(path), end='')
                f = open(prefix(path), 'w')
                f.write('spam')
                f.close()  
                path += 'f'
            print()
            break

    print('ACCESS FILES')
    for func in(open, os.path.isfile, os.lstat):
        path = root
        while True:
            try:
                path += 'f'
                res = func(path)
                if res == False and func is os.path.isfile:    # False on fail
                    raise OSError
            except:
                print(' %s failed at len=%d chars' %
                      (getattr(func, '__name__', func), len(path)))
                break

    print('ACCESS FILES WITH PREFIX')
    for func in(open, os.path.isfile, os.lstat):
        path = root
        while True:
            try:
                path += 'f'
                res = func(prefix(path))
                if res == False and func is os.path.isfile:    # False on fail
                    raise OSError
            except:
                print(' %s failed at len=%d chars' %
                      (getattr(func, '__name__', func), len(path)))
                break


#------------------------------------------------------------------------------
# TEST ABSOLUTE PATHS (NOT REL)
#------------------------------------------------------------------------------

print()
print('ABSOLUTE PATHS', '*'*60)
root = 'C:\\Users\\mark\\Desktop\\dirlentest\\'   # 33 chars here
if os.path.exists(root):
    shutil.rmtree('\\\\?\\' + root)               # clean up prior run's dirs
os.mkdir(root)
print('root prefix len=%d' % len(root))
TEST(root, rel=False)


#------------------------------------------------------------------------------
# REDO ALL WITH RELATIVE PATH (NOT ABS)
#------------------------------------------------------------------------------

print()
print('RELATIVE PATHS', '*'*60)
runin = 'C:\\Users\\mark\\Desktop'
os.chdir(runin)
root = 'dirlentest\\'
if os.path.exists(root):
    shutil.rmtree('\\\\?\\' + os.path.abspath(root))    # clean up prior run
os.mkdir(root)
print('cwd len=%d (%d with \\)' % (len(runin), len(runin)+1))
print('root prefix len=%d' % len(root))
TEST(root, rel=True)





[Home page] Books Code Blog Python Author Train Find ©M.Lutz