import os from distutils import util from distutils.core import Command from distutils.filelist import FileList class InstallMisc(Command): """ Common base class for installing some files in a subdirectory. Currently used by install_data and install_localstate. """ user_options = [ ('force', 'f', "force installation (overwrite existing files)"), ] def initialize_options(self): self.install_dir = None self.force = None self.allfiles = None self.filelists = None return def finalize_options (self): self.set_undefined_options('install', (self.get_command_name(), 'install_dir'), ('force', 'force')) return def _get_distribution_filelists(self): raise NotImplementedError('subclass %s must override' % self.__class__) def run(self): for filelist in self.get_filelists(): sources = filelist.files outputs = self.get_filelist_outputs(filelist) # If there are no files listed, the user must be # trying to create an empty directory. if not sources: assert len(outputs) == 1 self.mkpath(outputs[0]) else: assert len(sources) == len(outputs) for src, dst in zip(sources, outputs): self.mkpath(os.path.dirname(dst)) self.copy_file(src, dst) return def process_filelist(self, filelist): assert isinstance(filelist, FileList) filelist.set_allfiles(self.distribution.get_allfiles()) for source in tuple(filelist.sources): pattern = util.convert_path(source) if filelist.recursive: found = filelist.include_pattern(None, prefix=pattern) else: found = filelist.include_pattern(pattern, anchor=True) if not found: self.warn("no files found matching '%s'" % source) filelist.sources.remove(source) for exclude in filelist.excludes: pattern = util.convert_path(exclude) if filelist.recursive: found = filelist.exclude_pattern(None, prefix=pattern) else: found = filelist.exclude_pattern(pattern, anchor=True) if not found: self.warn("no previously included files found" " matching '%s'" % exclude) filelist.sort() filelist.remove_duplicates() return filelist def get_filelists(self): if self.filelists is None: # Convert the list of filespecs into a list of actual files self.filelists = self._get_distribution_filelists() for filelist in self.filelists: self.process_filelist(filelist) return self.filelists def get_filelist_outputs(self, filelist): outputs = [] destdir = util.convert_path(filelist.dest) destdir = os.path.join(self.install_dir, destdir) if not filelist.sources: # If there are no files listed, the user must be # trying to create an empty directory, so add the # directory to the list of output files. outputs.append(destdir) elif filelist.recursive: for pattern in filelist.sources: pattern = util.convert_path(pattern) for filename in filelist.files: assert filename.startswith(pattern) source = filename[len(pattern):] assert source.startswith(os.sep) outputs.append(destdir + source) else: # all files in the filelist are copied directly into the # destination directory for filename in filelist.files: source = os.path.basename(filename) outputs.append(os.path.join(destdir, source)) return outputs # -- Reporting methods --------------------------------------------- def get_source_files(self): sources = [] for filelist in self.get_filelists(): sources.extend(filelist.files) return sources def get_inputs(self): inputs = [] for filelist in self.get_filelists(): inputs.extend(filelist.files) return inputs def get_outputs(self): outputs = [] for filelist in self.get_filelists(): outputs.extend(self.get_filelist_outputs(filelist)) return outputs