40def 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.
54 """
55 if doCopy not in [ 'Always', 'Never', 'ifNotLocal' ]:
56 print ("doCopy value of %s not recognised. Resetting it to 'ifNotLocal'" % doCopy)
57 doCopy = 'ifNotLocal'
58 fromWhereShorts = { 'data' : 'DATAPATH' }
59
60 if isinstance( listOfFiles, str ):
61 listOfFiles = listOfFiles.split(',')
62
63 fromPath = fromWhereShorts.get( fromWhere, fromWhere )
64
65 if doCopy == 'Always':
66 copy_func = shutil.copyfile
67 elif doCopy == 'Never':
68 copy_func = os.symlink
69 else:
70 copy_func = None
71 fileDict = {}
72
73 realDirList = []
74 symLinkList = []
75
76
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 ):
82 continue
83 srcFilePrefix = os.path.dirname( os.path.commonprefix( srcFileList ) )
84 dirName = os.path.dirname( filename )
85
86
87
88 try:
89 realDirList.append( symLinkList.pop( symLinkList.index( dirName ) ) )
90 except ValueError:
91 pass
92 else:
93 continue
94 print ("srcFilePrefix = %s, dirName = %s" % ( srcFilePrefix, dirName ))
95 try:
96 srcFilePrefix.rindex( dirName, len( srcFilePrefix ) - len( dirName ) )
97 except ValueError:
98 realDirList.append( dirName )
99 else:
100 symLinkList.append( dirName )
101 del symLinkList
102
103 for filename, srcFileList in fileDict.items():
104 if not srcFileList:
105 if errorIfNotFound:
106 raise EnvironmentError('Auxiliary file %s not found in %s' % (filename,fromPath) )
107 else:
108 print ("WARNING: auxiliary file %s not found in %s" % (filename,fromPath))
109 parentDirLinked = None
110 for srcFile in srcFileList:
111
112
113 if os.path.dirname( srcFile ) == parentDirLinked:
114 print ("%s has been symlinked." % parentDirLinked)
115 continue
116
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():
121 subdir = ''
122 else:
123 targetFile = os.path.abspath( os.path.basename( srcFile ) )
124 subdir = ''
125
126 if doCopy == 'ifNotLocal':
127 if isOnLocalFileSystem( srcFile ):
128 copy_func = os.symlink
129 else:
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:
134
135
136
137 if subdir:
138 if subdir in realDirList:
139 print ("%s found in realDirList: %s" % ( subdir, realDirList ))
140 realDirRequired = True
141 else:
142
143 targetFile = subdir
144 srcFile = os.path.dirname( srcFile ).rstrip( os.sep )
145
146 parentDirLinked = srcFile
147
148 if copy_func is shutil.copyfile or realDirRequired:
149 if subdir and not os.path.isdir( subdir ):
150 brokenLink = linkPresent( subdir, findBrokenLink = True )
151 if brokenLink:
152 try:
153 print ("Attempting to remove broken symlink %s" % brokenLink)
154 os.remove( brokenLink )
155 except OSError as x:
156 raise EnvironmentError( 'Unable to create the directory %s as the broken symlink %s cannot be removed: %s' % ( subdir, brokenLink, x ) )
157
158 os.makedirs( subdir )
159
160 try:
161 isSameFile = os.path.samefile( srcFile, targetFile )
162 except OSError:
163
164 if os.path.islink( targetFile ):
165 try:
166 print ("*Attempting to remove %s" % targetFile)
167 os.remove( targetFile )
168 except OSError as x:
169 raise EnvironmentError( 'Unable to remove broken symlink %s: %s' % ( targetFile, x ) )
170 try:
171 copy_func( srcFile, targetFile )
172 except OSError:
173
174 shutil.copyfile( srcFile, targetFile )
175 continue
176
177
178
179
180
181 if isSameFile:
182 print ("%s is the same as %s. No further action." % ( srcFile, targetFile ))
183 continue
184 print ("%s is not the same as %s" % ( srcFile, targetFile ))
185
186
187
188
189 try:
190 print ("**Attempting to remove %s" % targetFile)
191 os.remove( targetFile )
192 except Exception:
193 for _root, _dirs, _files in os.walk( targetFile , topdown = False ):
194 for name in _files:
195 os.remove( os.path.join( _root, name ) )
196 for name in _dirs:
197 os.rmdir( os.path.join( _root, name ) )
198 os.rmdir( targetFile )
199 try:
200 copy_func( srcFile, targetFile )
201 except OSError:
202
203 shutil.copyfile( srcFile, targetFile )