sbsv2/raptor/python/generic_path.py
changeset 0 044383f39525
child 3 e1eecf4d390d
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 #
       
     2 # Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 # generic_path module
       
    16 #
       
    17 
       
    18 import os
       
    19 import sys
       
    20 import re
       
    21 import types
       
    22 
       
    23 # are we on windows, and if so what is the current drive letter
       
    24 isWin = sys.platform.lower().startswith("win")
       
    25 if isWin:
       
    26 	drive = re.match('^([A-Za-z]:)',os.getcwd()).group(0)
       
    27 
       
    28 # regex for "bare" drive letters	
       
    29 driveRE = re.compile('^[A-Za-z]:$')
       
    30 
       
    31 # Base class
       
    32 
       
    33 class Path:
       
    34 	"""This class represents a file path.
       
    35 	
       
    36 	A generic path object supports operations without needing to know
       
    37 	about Windows and Linux differences. The standard str() function can
       
    38 	obtain a string version of the path in Local format for use by
       
    39 	platform-specific functions (file opening for example).
       
    40 	
       
    41 	We use forward slashes as path separators (even on Windows).
       
    42 	
       
    43 	For example,
       
    44 	
       
    45 		path1 = generic_path.Path("/foo")
       
    46 		path2 = generic_path.Path("bar", "bing.bang")
       
    47 		
       
    48 		print str(path1.Append(path2))
       
    49 		
       
    50 	Prints /foo/bar/bing.bang		on Linux
       
    51 	Prints c:/foo/bar/bing.bang		on Windows (if c is the current drive)
       
    52 	""" 
       
    53 		
       
    54 	def __init__(self, *arguments):
       
    55 		"""construct a path from a list of path elements"""
       
    56 		
       
    57 		if len(arguments) == 0:
       
    58 			self.path = ""
       
    59 			return
       
    60 		
       
    61 		list = []
       
    62 		for i,arg in enumerate(arguments):
       
    63 			if isWin:
       
    64 				if i == 0:
       
    65 					# If the first element starts with \ or / then we will
       
    66 					# add the current drive letter to make a fully absolute path
       
    67 					if arg.startswith("\\\\"):
       
    68 						list.append(arg) # A UNC path - don't mess with it
       
    69 					elif arg.startswith("\\") or arg.startswith("/"):
       
    70 						list.append(drive + arg)
       
    71 					# If the first element is a bare drive then dress it with a \
       
    72 					# temporarily otherwise "join" will not work properly.
       
    73 					elif driveRE.match(arg):
       
    74 						list.append(arg + "\\")
       
    75 					# nothing special about the first element
       
    76 					else:
       
    77 						list.append(arg)
       
    78 				else:
       
    79 					if arg.startswith("\\\\"):
       
    80 						raise ValueError("non-initial path components must not start with \\\\ : %s" % arg)
       
    81 					else:
       
    82 						list.append(arg)
       
    83 				if ";" in arg:
       
    84 					raise ValueError("An individual windows Path may not contain ';' : %s" % arg)
       
    85 			else:
       
    86 				list.append(arg)
       
    87 	
       
    88 		self.path = os.path.join(*list)
       
    89 		
       
    90 		# normalise to avoid nastiness with dots and multiple separators
       
    91 		# but do not normalise "" as it will become "."
       
    92 		if self.path != "":
       
    93 			self.path = os.path.normpath(self.path)
       
    94 		
       
    95 		# always use forward slashes as separators
       
    96 		self.path = self.path.replace("\\", "/")
       
    97 		
       
    98 		# remove trailing slashes unless we are just /
       
    99 		if self.path != "/":
       
   100 			self.path = self.path.rstrip("/")
       
   101 		
       
   102 	def __str__(self):
       
   103 		return self.path
       
   104 	
       
   105 	def GetNeutralStr(self):
       
   106 		"""return the path as a string that could be included in other paths."""
       
   107 		return self.path.replace(":","").replace("/","")
       
   108 
       
   109 	def GetLocalString(self):
       
   110 		"""return a string in the local file-system format.
       
   111 		
       
   112 		e.g. C:/tmp on Windows or /C/tmp on Linux"""
       
   113 		return self.path
       
   114 	
       
   115 	def isAbsolute(self):
       
   116 		"test whether this path is absolute or relative"
       
   117 		# C: is an absolute directory
       
   118 		return (os.path.isabs(self.path) or driveRE.match(self.path))
       
   119 	
       
   120 	def Absolute(self):
       
   121 		"""return an object for the absolute version of this path.
       
   122 		
       
   123 		Prepends the current working directory to relative paths and
       
   124 		the current drive (on Windows) to /something type paths."""
       
   125 		# leave C: alone as abspath will stick the cwd on
       
   126 		if driveRE.match(self.path):
       
   127 			return Path(self.path)
       
   128 		else:
       
   129 			return Path(os.path.abspath(self.path))
       
   130 	
       
   131 	def Append(self, *arguments):
       
   132 		"return an object with path elements added at the end of this path"
       
   133 		return Join(*((self,) + arguments))
       
   134 	
       
   135 	def Prepend(self, *arguments):
       
   136 		"return an object with path elements added at the start of this path"
       
   137 		return Join(*(arguments + (self,)))
       
   138 	
       
   139 	def isDir(self):
       
   140 		"test whether this path points to an existing directory"
       
   141 		# C: is a directory
       
   142 		return (os.path.isdir(self.path) or driveRE.match(self.path))
       
   143 	
       
   144 	def isFile(self):
       
   145 		"test whether this path points to an existing file"
       
   146 		return os.path.isfile(self.path)
       
   147 
       
   148 	def Exists(self):
       
   149 		"test whether this path exists in the filesystem"
       
   150 		if driveRE.match(self.path):
       
   151 			return os.path.exists(self.path + "/")
       
   152 		else:
       
   153 			return os.path.exists(self.path)
       
   154 		
       
   155 	def Dir(self):
       
   156 		"return an object for the directory part of this path"
       
   157 		if driveRE.match(self.path):
       
   158 			return Path(self.path)
       
   159 		else:
       
   160 			return Path(os.path.dirname(self.path))
       
   161 
       
   162 	def File(self):
       
   163 		"return a string for the file part of this path"
       
   164 		return os.path.basename(self.path)
       
   165 
       
   166 	def Components(self):
       
   167 		"""return a list of the components of this path."""
       
   168 		return self.path.split('/')
       
   169 
       
   170 	def FindCaseless(self):
       
   171 		"""Given a path which may not be not correct in terms of case,
       
   172 		search the filesystem to find the corresponding, correct path.
       
   173 		paths are assumed to be absolute and normalised (which they
       
   174 		should be in this class).
       
   175 
       
   176 		Assumes that the path is more right than wrong, i.e. starts
       
   177 		with the full path and tests for existence - then takes the
       
   178 		last component off and check for that.
       
   179 
       
   180 		This will be inefficient if used in cases where the file 
       
   181 		has a high probability of not existing.
       
   182 		"""
       
   183 
       
   184 		if os.path.exists(self.path):
       
   185 			return Path(self.path)
       
   186 
       
   187 		unknown_elements = []
       
   188 		tail = self.path
       
   189 		head = None
       
   190 		while tail != '': 
       
   191 			if os.path.exists(tail):
       
   192 				break
       
   193 			else:
       
   194 				(tail,head) = os.path.split(tail)
       
   195 				#print "(head,tail) = (%s,%s)\n" % (head,tail)
       
   196 				unknown_elements.append(head)
       
   197 
       
   198 		if tail == None:
       
   199 			result = ""
       
   200 		else:
       
   201 			result = tail
       
   202 
       
   203 		# Now we know the bits that may be wrong so we can search for them
       
   204 		unknown_elements.reverse()
       
   205 		for item in unknown_elements:
       
   206 			possible = os.path.join(result, item) 
       
   207 			if os.path.exists(possible):
       
   208 				result = possible
       
   209 				continue # not finished yet - only this element is ok
       
   210 
       
   211 			# Nope, we really do have to search for this component of the path
       
   212 			possible = None
       
   213 			if result:
       
   214 				for file in os.listdir(result):
       
   215 					if file.lower() == item.lower():
       
   216 						possible = os.path.join(result,file)
       
   217 						break # find first matching name (might not be right)
       
   218 				if possible is None:
       
   219 					result = "" 
       
   220 					break # really couldn't find the file
       
   221 				result = possible
       
   222 
       
   223 		if result == "":
       
   224 			return None
       
   225 
       
   226 		return Path(result)
       
   227 
       
   228 	def From(self,source):
       
   229 		"""Returns the relative path from 'source' to here."""
       
   230 		list1 = source.Absolute().Components()
       
   231 		list2 = self.Absolute().Components()
       
   232 
       
   233 		# on windows if the drives are different
       
   234 		# then the relative path is the absolute one.
       
   235 		if isWin and list1[0] != list2[0]:
       
   236 			return self.Absolute()
       
   237 
       
   238 		final_list = []
       
   239 		for item in list1:
       
   240 			if list2 != []:
       
   241 				for widget in list2:
       
   242 					if item == widget:
       
   243 						list2.pop(0)
       
   244 						break
       
   245 					else:
       
   246 						final_list.insert(0, "..")
       
   247 						final_list.append(widget)
       
   248 						list2.pop(0)
       
   249 						break
       
   250 			else:
       
   251 				final_list.insert(0, "..")
       
   252 
       
   253 		final_list.extend(list2)
       
   254 
       
   255 		return Join(*final_list)
       
   256 
       
   257 	def GetShellPath(self):
       
   258 		"""Returns correct slashes according to os type as a string
       
   259 		"""
       
   260 		if isWin:
       
   261 			if  "OSTYPE" in os.environ and os.environ['OSTYPE'] == "cygwin" :
       
   262 				return self.path
       
   263 
       
   264 			return self.path.replace("/", "\\")
       
   265 
       
   266 		return self.path
       
   267 
       
   268 
       
   269 # Module functions
       
   270 
       
   271 def Join(*arguments):
       
   272 	"""Concatenate the given list to make a generic path object. 
       
   273 	
       
   274 	This can accept both strings and Path objects, and join
       
   275 	them "intelligently" to make a complete path."""
       
   276 	list = []
       
   277 	for arg in arguments:
       
   278 		if isinstance(arg, Path):
       
   279 			list.append(arg.path)
       
   280 		else:
       
   281 			list.append(arg)
       
   282 		
       
   283 	return Path(*list)
       
   284 
       
   285 def CurrentDir():
       
   286 	"return a Path object for the current working directory"
       
   287 	return Path(os.getcwd())
       
   288 
       
   289 def NormalisePathList(aList):
       
   290 	"""Convert a list of strings into a list of Path objects"""
       
   291 	return map(lambda x: Path(x), aList)
       
   292 
       
   293 def Where(afile):
       
   294 	"""Return the location of a file 'afile' in the system path.
       
   295 	
       
   296 	On windows, adds .exe onto the filename if it's not there. Returns the first location it found or None if it wasn't found.
       
   297 	
       
   298 	>>> Where("python")
       
   299 	"/usr/bin/python"
       
   300 	>>> Where("nonexistentfile")
       
   301 	None
       
   302 	"""
       
   303 	location = None
       
   304 	if sys.platform.startswith("win"):
       
   305 		if not afile.lower().endswith(".exe"):
       
   306 			afile += ".exe"
       
   307 			
       
   308 	for current_file in [os.path.join(loop_number,afile) for loop_number in
       
   309 			     os.environ["PATH"].split(os.path.pathsep)]:
       
   310 		if os.path.isfile(current_file):
       
   311 			location = current_file
       
   312 			break
       
   313 	return location
       
   314 
       
   315 # end of generic_path module