5 from .envutil
import find_files_env
9 """Check if the given filename path contains a symlink. This function also checks all it's parent directories.
10 If findBrokenLink is True, the first path component that is a symlink and is broken is returned.
11 If findBrokenLink is False, the first symlink in the path in returned."""
12 if os.path.isabs( filename ):
14 p = os.path.commonprefix( [ os.getcwd(), filename ] )
15 filename = filename[ len( p ) + 1: ]
18 initial_p = p + os.sep
19 intermediateList = filename.split( os.sep )
20 while intermediateList:
21 p = os.sep.join( [ p, intermediateList.pop(0) ] )
22 if os.path.islink( p ):
23 if findBrokenLink
and os.path.exists( p ):
25 return p.lstrip( initial_p )
29 """Check in the filename at every directory level to determine if any of its parent directories have different mount points."""
30 filename = os.path.realpath( filename )
31 cPrefix = os.path.commonprefix( [ os.getcwd(), filename ] )
32 intermediateDirList = os.path.dirname( filename[ len( cPrefix ): ] ).
split( os.sep )
33 cPrefix = cPrefix.rstrip( os.sep )
34 while intermediateDirList:
35 cPrefix = os.sep.join( [ cPrefix, intermediateDirList.pop(0) ] )
36 if os.path.ismount( cPrefix ):
40 def get_files( listOfFiles, fromWhere='data', doCopy='ifNotLocal', errorIfNotFound=True, keepDir=True, depth=0, sep=os.pathsep ):
41 """Copy or symlink a list of files given from a search path given in an environment variable.
42 <listOfFiles> is either as a python list of strings, or as a comma separated list in one string.
43 Each entry in the list can contain wildcards (a la unix commands)
44 <fromWhere>: name of the environment variable containing the search paths. Available shortcuts: 'data' -> 'DATAPATH'.
45 <doCopy>='Always': copy the file
46 ='Never' : symlink the file
47 ='ifNotLocal': symlink the file if the original is in a subdirectory of the run directory, otherwise copy.
48 <errorIfNotFound>=True: An EnvironmentError exception is raised if any filename in the list is not found.
49 If the filename contains wildcards, it is considered not found if no files are found at all.
50 =False: If a file is not found, only a warning is printed
51 <keepDir>=True : copy the file into a local subdirectory if the requested filename includes its directory part
52 False: copy the file in the current directory with the requested filename while ignoring its directory part
53 If a filename in <listOfFiles> contains an absolute path, the directory part is ignored in the copied filename.
55 if doCopy
not in [
'Always',
'Never',
'ifNotLocal' ]:
56 print (
"doCopy value of %s not recognised. Resetting it to 'ifNotLocal'" % doCopy)
58 fromWhereShorts = {
'data' :
'DATAPATH' }
60 if isinstance( listOfFiles, str ):
61 listOfFiles = listOfFiles.split(
',')
63 fromPath = fromWhereShorts.get( fromWhere, fromWhere )
65 if doCopy ==
'Always':
66 copy_func = shutil.copyfile
67 elif doCopy ==
'Never':
68 copy_func = os.symlink
77 for filename
in listOfFiles:
78 filename = os.path.expanduser( os.path.expandvars( os.path.normpath( filename ) ) )
79 srcFileList =
find_files_env( filename, fromPath, sep=sep, depth=depth )
80 fileDict[ filename ] = srcFileList
81 if os.path.isabs( filename ):
83 srcFilePrefix = os.path.dirname( os.path.commonprefix( srcFileList ) )
84 dirName = os.path.dirname( filename )
89 realDirList.append( symLinkList.pop( symLinkList.index( dirName ) ) )
94 print (
"srcFilePrefix = %s, dirName = %s" % ( srcFilePrefix, dirName ))
96 srcFilePrefix.rindex( dirName, len( srcFilePrefix ) - len( dirName ) )
98 realDirList.append( dirName )
100 symLinkList.append( dirName )
103 for filename, srcFileList
in fileDict.items():
106 raise EnvironmentError(
'Auxiliary file %s not found in %s' % (filename,fromPath) )
108 print (
"WARNING: auxiliary file %s not found in %s" % (filename,fromPath))
109 parentDirLinked =
None
110 for srcFile
in srcFileList:
113 if os.path.dirname( srcFile ) == parentDirLinked:
114 print (
"%s has been symlinked." % parentDirLinked)
117 if keepDir
and not os.path.isabs( filename ):
118 subdir = os.path.dirname( filename )
119 targetFile = os.path.abspath( os.path.join( subdir, os.path.basename( srcFile ) ) )
120 if subdir == os.getcwd():
123 targetFile = os.path.abspath( os.path.basename( srcFile ) )
126 if doCopy ==
'ifNotLocal':
128 copy_func = os.symlink
130 print (
"%s is on a different mount point as $CWD." % srcFile)
131 copy_func = shutil.copyfile
132 realDirRequired =
False
133 if copy_func
is os.symlink:
138 if subdir
in realDirList:
139 print (
"%s found in realDirList: %s" % ( subdir, realDirList ))
140 realDirRequired =
True
144 srcFile = os.path.dirname( srcFile ).rstrip( os.sep )
146 parentDirLinked = srcFile
148 if copy_func
is shutil.copyfile
or realDirRequired:
149 if subdir
and not os.path.isdir( subdir ):
150 brokenLink =
linkPresent( subdir, findBrokenLink =
True )
153 print (
"Attempting to remove broken symlink %s" % brokenLink)
154 os.remove( brokenLink )
156 raise EnvironmentError(
'Unable to create the directory %s as the broken symlink %s cannot be removed: %s' % ( subdir, brokenLink, x ) )
158 os.makedirs( subdir )
161 isSameFile = os.path.samefile( srcFile, targetFile )
164 if os.path.islink( targetFile ):
166 print (
"*Attempting to remove %s" % targetFile)
167 os.remove( targetFile )
169 raise EnvironmentError(
'Unable to remove broken symlink %s: %s' % ( targetFile, x ) )
171 copy_func( srcFile, targetFile )
174 shutil.copyfile( srcFile, targetFile )
182 print (
"%s is the same as %s. No further action." % ( srcFile, targetFile ))
184 print (
"%s is not the same as %s" % ( srcFile, targetFile ))
190 print (
"**Attempting to remove %s" % targetFile)
191 os.remove( targetFile )
193 for _root, _dirs, _files
in os.walk( targetFile , topdown =
False ):
195 os.remove( os.path.join( _root, name ) )
197 os.rmdir( os.path.join( _root, name ) )
198 os.rmdir( targetFile )
200 copy_func( srcFile, targetFile )
203 shutil.copyfile( srcFile, targetFile )