def sync(self): """ (VFSEntry implementation) """ assert self.filesystem() is not None if self.__state == FileState.NEW: filename = os.sep.join(self.abspath()) try: libconfix.core.utils.helper.write_lines_to_file_if_changed( filename=filename, lines=self.__lines) except Error as err: raise Error('Could not write file '+filename, [err]) if self.mode() is not None: try: os.chmod(filename, self.mode()) except OSError as err: raise Error('Could not change mode of file '+filename, [NativeError(err, sys.exc_traceback)]) pass if FileSystem.CLEAR_ON_SYNC in self.filesystem().flags(): self.__lines = None self.__state = FileState.SYNC_CLEAR else: self.__state = FileState.SYNC_INMEM pass return if self.__state == FileState.SYNC_CLEAR: return if self.__state == FileState.SYNC_INMEM: if FileSystem.CLEAR_ON_SYNC in self.filesystem().flags(): self.__lines = None self.__state = FileState.SYNC_CLEAR pass return if self.__state == FileState.DIRTY: filename = os.sep.join(self.abspath()) try: libconfix.core.utils.helper.write_lines_to_file( filename=filename, lines=self.__lines) except Error as err: raise Error('Could not write file '+filename, [err]) if FileSystem.CLEAR_ON_SYNC in self.filesystem().flags(): self.__lines = None self.__state = FileState.SYNC_CLEAR else: self.__state = FileState.SYNC_INMEM pass return if self.__state == FileState.VIRTUAL: return assert 0 pass
def CMAKE_CMAKELISTS_ADD_FIND_CALL(self, find_call, flags): """ Add a find call to the toplevel CMakeLists.txt file. A find call is simply a string, and you can add just about anything. It's just that the position matters. If CMAKE_BUILDINFO_LOCAL is in flags, then it is added to the toplevel CMakeLists.txt file of the local package. If CMAKE_BUILDINFO_PROPAGATE is in flags, then it is added to the toplevel CMakeLists.txt file of the receiving package. """ if type(find_call) not in (str, tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_FIND_CALL(): "find_call" parameter must be str, list, or tuple' ) if type(find_call) is str: find_call = [find_call] pass if type(flags) is int: flags = (flags, ) pass if type(flags) not in (tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_FIND_CALL(): "flags" parameter must be int, list or tuple' ) if self.CMAKE_BUILDINFO_LOCAL in flags: find_cmake_output_builder( self.__dirbuilder).top_cmakelists().add_find_call(find_call) pass if self.CMAKE_BUILDINFO_PROPAGATE in flags: self.__dirbuilder.add_buildinfo( BuildInfo_Toplevel_CMakeLists_FindCall(find_call=find_call)) pass pass
def find_namespaces(lines): stack_growth = 0 stack = [] found_namespaces = [] lineno = 0 for l in lines: lineno = lineno + 1 m = _re_beg_ns.search(l) if m: n = _re_beg_ns_named.search(m.group(1)) ns_name = n and n.group(1) or '' stack.append(ns_name) stack_growth = 1 continue m = _re_end_ns.search(l) if m: if len(stack) == 0: raise Error('error at line ' + str(lineno) + ': ' 'end of namespace found though none was begun') if stack_growth == 1 and len(stack[-1]) > 0: found_namespaces.append(stack[0:]) # copy, not just ref del stack[-1] stack_growth = 0 continue if len(stack): raise Error( 'namespace \'' + '::'.join(stack) + '\' was opened but not closed ' '(remember, you have to close it with a line like \'} // /namespace\')' ) return found_namespaces
def CMAKE_CMAKELISTS_ADD_INCLUDE(self, include, flags): """ Add an INCLUDE(include) command to the toplevel CMakeLists.txt file. If CMAKE_BUILDINFO_LOCAL is in flags, then it is added to the toplevel CMakeLists.txt file of the local package. If CMAKE_BUILDINFO_PROPAGATE is in flags, then it is added to the toplevel CMakeLists.txt file of the receiving package. """ if type(include) is not str: raise Error( 'CMAKE_CMAKELISTS_ADD_INCLUDE(): "include" parameter must be a string' ) if type(flags) is int: flags = (flags, ) pass if type(flags) not in (tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_INCLUDE(): "flags" parameter must be list or tuple' ) if self.CMAKE_BUILDINFO_LOCAL in flags: find_cmake_output_builder( self.__dirbuilder).top_cmakelists().add_include(include) pass if self.CMAKE_BUILDINFO_PROPAGATE in flags: self.__dirbuilder.add_buildinfo( BuildInfo_Toplevel_CMakeLists_Include(include=include)) pass pass
def __init__(self, prefix): assert type(prefix) in [types.ListType, types.TupleType], prefix CompositePackageRepository.__init__(self, []) repodir = prefix+self.REPO_FULL_PATH if not os.path.isdir(os.sep.join(repodir)): debug.warn('No repository directory '+os.sep.join(repodir)) return fs = scan_filesystem(path=repodir) errlist = [] for name, entry in fs.rootdirectory().entries(): if not isinstance(entry, VFSFile): continue if _re_repo.match(name): try: self.add_repo(PackageFileRepository(file=entry)) except Error, e: errlist.append(Error('Error reading file "'+os.sep.join(entry.abspath()), [e])) except Exception, e: errlist.append(Error('Error reading file "'+os.sep.join(entry.abspath()), [e])) pass pass
def H(self, filename, install=[], public=None, relocate_to=None): if install is not None and type(install) is not list: raise Error( "H(): 'install' parameter must be None or a list of strings") if type(filename) is not str: raise Error("H(): 'filename' parameter must be string") if public is not None and type(public) is not bool: raise Error("H(): 'public' parameter must be bool") h = HeaderBuilder(file=self.__find_file(filename)) if install is not None: h.set_visibility(install) pass if public is not None: h.set_public(public) pass self.__dirbuilder.add_builder(h) if relocate_to is not None: try: the_path_to_relocate_to = helper.make_path(relocate_to) except Error, e: raise Error('H(): invalid "relocate_to" value', [e]) self.__dirbuilder.add_builder( Master(filename=filename, directory=the_path_to_relocate_to)) pass
class AutoconfAuxDirWatcher(Builder): """ On enlarge(), if my parent directory is of type AutoconfAuxDirBuilder, put the necessary files in it.""" def locally_unique_id(self): # I am supposed to be the only one of my kind in a given # directory, so my class suffices as an ID. return str(self.__class__) def enlarge(self): super(AutoconfAuxDirWatcher, self).enlarge() if not isinstance(self.parentbuilder(), AutoconfAuxDirBuilder): return try: confix_root = helper.find_confix_root(sys.argv[0]) except Error, e: raise Error('Cannot find KDE hack support files', [e]) kde_hack_dir = os.path.join(confix_root, 'share', 'confix', 'kde-hack') conf_change_pl = os.path.join(kde_hack_dir, 'conf.change.pl') config_pl = os.path.join(kde_hack_dir, 'config.pl') if not os.path.isfile(conf_change_pl): raise Error('Cannot apply KDE hack: ' + conf_change_pl + ' not found') if not os.path.isfile(config_pl): raise Error('Cannot apply KDE hack: ' + config_pl + ' not found') self.parentbuilder().eat_file(sourcename=conf_change_pl, mode=0755) self.parentbuilder().eat_file(sourcename=config_pl, mode=0755) pass
def enlarge(self): """ If my parentbuilder has any subdirectories, see if they contain a Confix2.dir file. If any, wrap DirectoryBuilder objects around them and add them to the parentbuilder. """ super(SubdirectoryRecognizer, self).enlarge() errors = [] for name, entry in self.parentbuilder().directory().entries(): if not isinstance(entry, VFSDirectory): continue if entry in self.__recognized_directories: continue confix2_dir_file = entry.get(const.CONFIX2_DIR) if confix2_dir_file is None: continue if not isinstance(confix2_dir_file, VFSFile): errors.append( Error( os.sep.join( confix2_dir_file.relpath( self.package().rootdirectory())) + ' is not a file')) continue self.parentbuilder().add_builder(DirectoryBuilder(directory=entry)) self.__recognized_directories.add(entry) pass if len(errors): raise Error('There were errors in directory '+\ os.sep.join(self.parentbuilder().directory().relpath(self.package().rootdirectory())), errors) pass
def CMAKE_CMAKELISTS_ADD_INCLUDE_DIRECTORY(self, directory, flags): """ Add an INCLUDE_DIRECTORIES(directory) command to the toplevel CMakeLists.txt file. If CMAKE_BUILDINFO_LOCAL is in flags, then it is added to the CMakeLists.txt file of the calling module. If CMAKE_BUILDINFO_PROPAGATE is in flags, then it is added to the CMakeLists.txt file of the receiving module. """ if type(directory) is not str: raise Error( 'CMAKE_CMAKELISTS_ADD_INCLUDE_DIRECTORY(): "directory" parameter must be a string' ) if type(flags) is int: flags = (flags, ) pass if type(flags) not in (tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_INCLUDE_DIRECTORY(): "flags" parameter must be list or tuple' ) if self.CMAKE_BUILDINFO_LOCAL in flags: find_cmake_output_builder( self.__dirbuilder).local_cmakelists().add_include_directory( directory) pass if self.CMAKE_BUILDINFO_PROPAGATE in flags: self.__dirbuilder.add_buildinfo( BuildInfo_IncludePath_External_CMake(incpath=[directory])) pass pass
def CMAKE_CMAKELISTS_ADD_CUSTOM_COMMAND__OUTPUT(self, outputs, commands, depends, working_directory=None): """ Add a ADD_CUSTOM_COMMAND (OUTPUT signature) to the CMakeLists.txt file of the current directory. """ if type(outputs) not in (tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_CUSTOM_COMMAND__OUTPUT(): "outputs" parameter must be a list or tuple' ) if type(commands) not in (tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_CUSTOM_COMMAND__OUTPUT(): "commands" parameter must be a list or tuple' ) if type(depends) not in (tuple, list): raise Error( 'CMAKE_CMAKELISTS_ADD_CUSTOM_COMMAND__OUTPUT(): "depends" parameter must be a list or tuple' ) if working_directory is not None and type( working_directory) is not str: raise Error( 'CMAKE_CMAKELISTS_ADD_CUSTOM_COMMAND__OUTPUT(): "working_directory" must be None os string' ) find_cmake_output_builder( self.__dirbuilder).local_cmakelists().add_custom_command__output( outputs=outputs, commands=commands, depends=depends, working_directory=working_directory, ) pass
def main(): try: config = CompositeConfiguration() (cmdlinecfg, actions) = cmdline.parse(sys.argv[1:]) config.add(cmdlinecfg) configfile = cmdlinecfg.configfile() configfileobj = None if configfile is not None: configfileobj = FileSystem(path=os.path.dirname(configfile).split( os.sep)).rootdirectory().add( name=os.path.basename(configfile), entry=File(state=FileState.SYNC_CLEAR)) else: configdir = cmdlinecfg.configdir() if configdir is None: candidate = os.path.expanduser('~/.confix2') if os.path.exists(candidate): configdir = candidate pass pass if configdir is not None: if not os.path.exists(configdir): raise Error('Directory "' + configdir + '" does not exist') if not os.path.isdir(configdir): raise Error('"' + configdir + '" exists but is not a directory') confixfs = scan_filesystem(path=configdir.split(os.sep)) configfileobj = confixfs.rootdirectory().find(['config']) pass pass if configfileobj is not None: configfile = ConfigFile(file=configfileobj) if cmdlinecfg.profile() is not None: profilename = cmdlinecfg.profile() else: profilename = 'default' pass config.add(configfile.get_profile(profilename)) pass config.add(DefaultConfiguration()) todo.TODO = actions todo.CONFIG = config # normally todo failures will throw exceptions, but this is in here just # as a safety measure. if todo.todo(): sys.exit(1) pass pass except Error, e: sys.stderr.write('***ERROR***\n') sys.stderr.write(str(e) + '\n') sys.exit(1)
def enlarge(self): super(Master, self).enlarge() if self.__slave is not None: return # first, we collect everything that is necessary to perform # the relocation - the header builder and the target directory # builder. # note that both need not be present from the beginning. they # just might not have been seen yet because of indeterminisms # in the order in which builders are called, or the respective # directory entries might physically not exist because they # are subject to be created. if self.__header_builder is None: self.__header_builder = self.parentbuilder().find_entry_builder( [self.__filename]) if self.__header_builder is None: self.force_enlarge() self.__num_retries += 1 if self.__num_retries > 20: raise Error(self.__error_prefix() + ': ' + self.__filename + ' not seen after 20 rounds') pass elif not isinstance(self.__header_builder, HeaderBuilder): raise Error(self.__error_prefix() + ': not a header file (' + str(source_header_builder) + ')') pass if self.__target_directory_builder is None: self.__target_directory_builder = self.package().rootbuilder( ).find_entry_builder(self.__directory) if self.__target_directory_builder is None: self.force_enlarge() self.__num_retries += 1 if self.__num_retries > 20: raise Error(self.__error_prefix() + ': ' + '/'.join(self.__directory) + ' not seen after 20 rounds') pass elif not isinstance(self.__target_directory_builder, DirectoryBuilder): raise Error(self.__error_prefix() + ': target not a directory (' + str(self.__target_directory_builder) + ')') pass # once we have everything at hand, create a slave in the # target directory and tell our header builder to shut up. if self.__header_builder is None or self.__target_directory_builder is None: return self.__slave = Slave(header_builder=self.__header_builder) self.__target_directory_builder.add_builder(self.__slave) self.__header_builder.disable_dependency_info() pass
def rescan_dir(dir): if dir.state() != DirectoryState.SYNC: raise Error('Cannot rescan directory: not yet in sync') abspath = os.sep.join(dir.abspath()) physical_dir_entries = set(os.listdir(abspath)) # first pass: add entries that are new in the physical directory. for name in physical_dir_entries: if name in ['.', '..']: continue absname = os.path.join(abspath, name) existing_entry = dir.get(name) if existing_entry is not None: if os.path.isfile(absname): if not isinstance(existing_entry, File): # entry type change; bail out raise Error('Cannot convert existing entry ' + name + ' to a file') pass elif os.path.isdir(absname): if not isinstance(existing_entry, Directory): # entry type change; bail out raise Error('Cannot convert existing entry ' + name + ' to a directory') # descend rescanning into subdirectory. rescan_dir(existing_entry) pass else: raise Error(absname + ' has unknown type') pass else: # go add the new entry if os.path.isfile(absname): dir.add(name=name, entry=File(state=FileState.SYNC_CLEAR)) elif os.path.isdir(absname): dir.add(name=name, entry=scan_dir(dir.abspath() + [name])) else: raise Error(absname + ' has unknown type') pass pass # second pass: remove entries that have disappeared from the # physical directory. (first iterate, then remove) remove_names = [] for name, entry in dir.entries(): if not entry.is_persistent(): # the file has been added up in the air for the purpose of # persisting it later. continue if name in physical_dir_entries: continue remove_names.append(name) pass for name in remove_names: dir.remove_but_be_careful_no_sync(name) pass pass
def PROVIDE_SYMBOL(self, symbol, match=Provide.EXACT_MATCH): if not symbol or len(symbol) == 0: raise Error('PROVIDE_SYMBOL(): need a non-zero symbol parameter') if not match in [Provide.EXACT_MATCH, Provide.GLOB_MATCH]: raise Error( 'PROVIDE_SYMBOL(): match must be one of EXACT_MATCH, GLOB_MATCH' ) self.__builder.add_provide(Provide_Symbol(symbol=symbol, match=match)) pass
def RELOCATE_HEADER(self, filename, directory): if not type(filename) is str: raise Error( 'RELOCATE_HEADER(): filename parameter must be a string') if not type(directory) in (list, tuple): raise Error( 'RELOCATE_HEADER(): directory parameter must be list or tuple') self.__dirbuilder.add_builder(Master(filename, directory)) pass
def get_profile(self, name): profiles_dict = self.context_.get('PROFILES') if profiles_dict is None: raise Error('PROFILES dictionary not found in ' + os.sep.join(self.filename_)) profile = profiles_dict.get(name) if profile is None: raise Error('Profile "' + name + '" not found in ' + os.sep.join(self.filename_)) return ProfileConfiguration(profile)
def DIRECTORY(self, path): if type(path) not in (list, tuple): raise Error('DIRECTORY(' + str(path) + '): path argument must be list or tuple') directory = self.__dirbuilder.directory().find(path=path) if directory is None: raise Error('DIRECTORY(): could not find directory ' + str(path)) dirbuilder = DirectoryBuilder(directory=directory) self.__dirbuilder.add_builder(dirbuilder) return dirbuilder
def PROVIDE_H(self, filename, match=Provide.AUTO_MATCH): if not filename or len(filename) == 0: raise Error('PROVIDE_H(): need a non-zero filename parameter') if match not in [ Provide.EXACT_MATCH, Provide.GLOB_MATCH, Provide.AUTO_MATCH ]: raise Error( 'PROVIDE_H(): match parameter must be one of EXACT_MATCH, GLOB_MATCH, AUTO_MATCH' ) self.__builder.add_provide(Provide_CInclude(filename, match)) pass
def dump_object_to_file(object, filename): try: file = open(filename, 'w') except IOError as e: raise Error('Cannot open file ' + filename + ' for writing', [e]) try: pickle.dump(object, file) except Exception as e: raise Error( 'Cannot dump Python object "' + str(object) + '" to file ' + filename, [NativeError(e, sys.exc_traceback)]) pass
def SET_FILE_PROPERTY(self, filename, name, value): file = self.__dirbuilder.directory().find([filename]) if file is None: raise Error('SET_FILE_PROPERTY(): ' 'file "'+filename+'" not found in directory "'+\ os.sep.join(self.__dirbuilder.directory().relpath())+'"') try: file.set_property(name, value) except Error, e: raise Error( 'SET_FILE_PROPERTY(' + filename + '): could not set property "' + name + '"', [e])
def find_confix_share_dir(argv0): '''We use the `share/confix/` directory to distribute the autoconf archive, and other kinds of support material. Given an argv[0], we use this location to find out what could be the location of the .../share/confix directory. Note that the algorithm used here is in no way comprehensive - rather, it just guesses, and guessing might fail. ''' progdir = os.path.normpath(argv0) progdir = os.path.abspath(progdir) if not os.path.isdir(progdir): progdir = os.path.dirname(progdir) # first the uninstalled case. argv0 has been called from the # source directory. either the path points there, or a relative # path has been given. search upwards for a directory that # contains AUTHORS, COPYING, MANIFEST.in and guess that this is # the source root. root = progdir while root != '/': authors_file = os.path.join(root, 'AUTHORS') copying_file = os.path.join(root, 'COPYING') manifest_file = os.path.join(root, 'MANIFEST.in') # check for files, requiring that all three or none are there. have_authors = os.path.exists(authors_file) and 1 or 0 have_copying = os.path.exists(copying_file) and 1 or 0 have_manifest = os.path.exists(manifest_file) and 1 or 0 all = have_authors + have_copying + have_manifest if all == 0: root = os.path.dirname(root) continue if all < 3: raise Error( 'WTF: only a subset of {AUTHORS, COPYING, MANIFEST.in} seen in {}' .format(root)) # more sanity checking for f in (authors_file, copying_file, manifest_file): if not os.path.isfile(f): raise Error('{} is not a file'.format(f)) return os.path.join(root, 'share', 'confix') # the installed case. root, bin = os.path.split(progdir) if bin != 'bin': raise Error("{} does not end with 'bin/'".format(argv0)) return os.path.join(root, 'share', 'confix')
def ADD_PLAINFILE(self, filename, datadir=None, prefixdir=None): if type(filename) is not types.StringType: raise Error('ADD_PLAINFILE(): filename must be a string') if (datadir is not None and prefixdir is not None) or \ (datadir is None and prefixdir is None): raise Error('ADD_PLAINFILE('+filename+'): specify either datadir or prefixdir') the_datadir = the_prefixdir = None if datadir is not None: try: the_datadir = helper.make_path(datadir) except Error, e: raise Error('ADD_PLAINFILE('+filename+'): datadir', [e]) pass
def load_object_from_file(filename): try: file = open(filename, 'r') except IOError as e: raise Error('Cannot open file ' + filename + ' for reading', [e]) try: object = pickle.load(file) except Exception as e: raise Error('Cannot read Python object from file ' + filename, [NativeError(e, sys.exc_traceback)]) return object
def REQUIRE_SYMBOL(self, symbol, urgency=Require.URGENCY_IGNORE): if not symbol or len(symbol) == 0: raise Error('REQUIRE_SYMBOL(): need a non-zero symbol parameter') if not urgency in [ Require.URGENCY_IGNORE, Require.URGENCY_WARN, Require.URGENCY_ERROR ]: raise Error( 'REQUIRE_SYMBOL(): urgency must be one of URGENCY_IGNORE, URGENCY_WARN, URGENCY_ERROR' ) self.__builder.add_require( Require_Symbol(symbol, found_in=[str(self.__builder)], urgency=urgency)) pass
def load(self): try: # fixme: File.lines() is currently the only method of # reading the content of a file. we read the lines, join # them together, and then unpickle the object from the # whole buffer. to make this more efficient, we'd need # something like File.content(). obj = helper_pickle.load_object_from_lines(self.__file.lines()) if obj['version'] != PackageFile.VERSION: raise Error('Version mismatch in repository file '+os.sep.join(self.__file.abspath())+'' ' (file: '+str(obj['version'])+',' ' current: '+str(PackageFile.VERSION)+')') return obj['package'] except Error, e: raise Error('Could not read package file '+os.sep.join(self.__file.abspath()), [e])
def SET_FILE_PROPERTIES(self, properties): if properties is None: raise Error( "SET_FILE_PROPERTIES(): 'properties' parameter cannot be None") if not type(properties) is types.DictionaryType: raise Error( "SET_FILE_PROPERTIES(): 'properties' parameter must be a dictionary" ) for name, value in properties.iteritems(): self.__builder.file().set_property(name=name, value=value) # we have modified a property, which at least *might* have # influence on the graph self.__builder.force_enlarge() pass pass
def LIBRARY_VERSION(self, version): if type(version) not in [types.ListType, types.TupleType]: raise Error( "LIBRARY_VERSION(): 'version' argument must be a tuple") if len(version) != 3: raise Error( "LIBRARY_VERSION(): 'version' argument must be a tuple of 3 integers" ) for i in xrange(len(version)): if type(version[i]) is not types.IntType: raise Error("LIBRARY_VERSION(): part " + str(i) + " of version is not an integer") pass self.__clusterer.set_libtool_version_info(version) pass
def HAS_UNDEFINED_SYMBOLS(self, has_undefined_symbols): if type(has_undefined_symbols) is not types.BooleanType: raise Error( "HAS_UNDEFINED_SYMBOLS(): 'has_undefined_symbols' argument must be a boolean" ) self.__clusterer.set_has_undefined_symbols(has_undefined_symbols) pass
def initialize(self, package): super(IDLBuilder, self).initialize(package) lines = self.file().lines() # remember the #includes for later use (we generate require # objects, and we generate a buildinfo object that carries # them). fortunately IDL is similar to C in that it uses the C # preprocessor for includes, so we can use the C plugin for # that. self.__includes = [i for i in libconfix.plugins.c.helper.iter_includes(lines)] # search lines for a namespace. if one is found, our install # path is the namespace (or the concatenation of nested # namespaces). if none is found, the file is installed # directly into <prefix>/include. paths = self.parse_modules_(lines) if len(paths) > 1: raise Error(os.sep.join(self.file().relpath(self.package().rootdirectory())) + ': error: ' 'found multiple modules, ' + ', '.join(['::'.join(p) for p in paths])) if len(paths): for p in paths[0]: self.__install_path.append(p) pass pass self.add_buildinfo( BuildInfo_IDL_NativeLocal(filename='/'.join(self.__install_path + [self.file().name()]), includes=self.__includes)) pass
class ADD_PLAINFILE(InterfaceProxy): def __init__(self, dirbuilder): assert isinstance(dirbuilder, DirectoryBuilder) InterfaceProxy.__init__(self) self.__dirbuilder = dirbuilder self.add_global('ADD_PLAINFILE', getattr(self, 'ADD_PLAINFILE')) pass def ADD_PLAINFILE(self, filename, datadir=None, prefixdir=None): if type(filename) is not types.StringType: raise Error('ADD_PLAINFILE(): filename must be a string') if (datadir is not None and prefixdir is not None) or \ (datadir is None and prefixdir is None): raise Error('ADD_PLAINFILE('+filename+'): specify either datadir or prefixdir') the_datadir = the_prefixdir = None if datadir is not None: try: the_datadir = helper.make_path(datadir) except Error, e: raise Error('ADD_PLAINFILE('+filename+'): datadir', [e]) pass if prefixdir is not None: try: the_prefixdir = helper.make_path(prefixdir) except Error, e: raise Error('ADD_PLAINFILE('+filename+'): prefixdir', [e]) pass