Viewing file: PathImp.py (9.8 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/Drivers/PathImp.py,v 1.16 2005/04/06 06:17:13 mbrown Exp $ """ Repository path related classes and functions
Copyright 2005 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
import urllib, urlparse, types, warnings from Ft.Server import FTSS_URI_SCHEME from Ft.Server.Common import Schema, ResourceTypes from Ft.Server.Server import FtServerServerException, Error
def RepoPathToUri(path): from Ft.Server.Common import Util return Util.RepoPathToUri(path)
def CreateInitialPath(documentRoot, driver): """Called to get the first path in a transaction""" tempP = Path('/;no-traverse', driver, None, None) p = tempP.normalize(documentRoot+';no-traverse') #Now fix the display stuff p.displayPath = '/' p.displaySteps = ['/'] p.displayPaths = ['/'] p._documentRoot = p return p
def QuickCreate(path): p = CreateInitialPath('/',None) return p.normalize(path)
class Path: """ An abstraction of a path in a particular repository; provides functionality for relative path resolution, alias traversal, and non-'/' document root.
If basePath constructor arg is not None, pathString must be relative. """ def __init__(self, pathString, driver, documentRoot, basePath): self._driver = driver #Needed to resolve aliases self._documentRoot = documentRoot #Needed to resolve absolute paths
if basePath is None: #Very special case self.displayPath = '/' self.absolutePath = '/' self.absolutePathAsUri = RepoPathToUri('/') self.displaySteps = ['/'] #self.absoluteSteps = ['/'] self.displayPaths = ['/'] self.absolutePaths = ['/'] self.name = '/' self.resourceType = ResourceTypes.RESOURCE_CONTENT else: #Initialize ourselves from the basePath
# FIXME: urlparse is much less efficient than a regex tailored # to this task. We only need to split on the last ';' to get # a path and a suffix. # #Not anymore (since we support multiple ;s pathString, suffixString = urlparse.urlparse(pathString)[2:4]
suffixes = suffixString.split(';') self.resourceType = ResourceTypes.RESOURCE_CONTENT traverseAlias = 1 #Default is to traverse
#Do these in order to allow for overriding for s in suffixes: if not s: continue elif s == 'metadata': self.resourceType = ResourceTypes.RESOURCE_METADATA elif s == 'cache': self.resourceType = ResourceTypes.RESOURCE_CACHE elif s == 'content': self.resourceType = ResourceTypes.RESOURCE_CONTENT elif s == 'no-traverse': traverseAlias = 0 elif s == 'traverse': traverseAlias = 1 else: warnings.warn("Unknown Path argument: " + str(s), RuntimeWarning, 2)
# pathString could be empty, so use [:1], not [0] if pathString[:1] == '/': #We got a whole # FIXME: l10n raise "Should not have a '/'"
# When we get in here, we have a base path and the new path is # based off of the base path. Always do this based on steps # because it is the easiest
dSteps = basePath.displaySteps[:] dPaths = basePath.displayPaths[:] aPaths = basePath.absolutePaths[:]
fields = filter(None, pathString.split('/'))
for curStep in fields: lastStep = curStep is fields[-1] if curStep == '.': continue elif curStep == '..': #The limiting factor here is the dPath if len(dPaths) > 1: dSteps = dSteps[:-1] dPaths = dPaths[:-1] aPaths = aPaths[:-1] continue
dSteps.append(curStep) if dPaths[-1] == '/': dPaths.append('/' + curStep) else: dPaths.append(dPaths[-1] + '/' + curStep)
#See if this step is an alias. If it is, then we need to #Adjust the absolute step and path accordingly
if aPaths[-1] == '/': testPath = '/' + curStep else: testPath = aPaths[-1] + '/' + curStep
if self._driver and (not lastStep or traverseAlias): while len(self._driver.getSystemModel().complete(testPath, Schema.TYPE, Schema.g_rdfResourceTypes[ResourceTypes.ResourceType.ALIAS])): #It is!!! #Actually add the alias reference to the path testPath = str(self._driver.getSystemModel().complete(testPath, Schema.ALIAS_REFERENCE, None)[0].object) aPaths.append(testPath)
self.absolutePath = aPaths[-1] self.absolutePathAsUri = RepoPathToUri(self.absolutePath)
self.displayPath = dPaths[-1] if len(suffixes): #We never add in "no-traverse", "traverse" or "content" for s in suffixes: if not (s in ['',"no-traverse","traverse","content"]): self.displayPath += ';' + s
self.displaySteps = dSteps self.displayPaths = dPaths self.absolutePaths = aPaths self.name = dSteps[-1]
return
def normalize(self, pathString, traverseLastAlias=None): """ Returns a new Path instance representing the result of resolving the given pathString (a relative path, usually), with the current path as the base. """ if not isinstance(pathString, (str, unicode)) or not pathString: raise FtServerServerException(Error.UNKNOWN_PATH,path=pathString)
if (traverseLastAlias != None): warnings.warn("You are using a deprecated traverse alias feature. Please specify with path arguments ;traverse or ;no-traverse", DeprecationWarning, 2) if traverseLastAlias: pathString += ";traverse" else: pathString += ";no-traverse"
#Quick normalization of // at the beginning while pathString[:2] == '//': pathString = pathString[1:]
# this is a massive bug. sigh. scheme, netloc, pathString, params, query, fragment = urlparse.urlparse(pathString)
#Quick normalization of // at the beginning (We must do this twice because of a potential scheme) while pathString[:2] == '//': pathString = pathString[1:]
suffixes = params.split(';') rt = self.resourceType #Default to ours traverseAlias = 1 #Default is to traverse
#Do these in order to allow for overiding for s in suffixes: if not s: continue elif s == 'metadata': rt = ResourceTypes.RESOURCE_METADATA elif s == 'cache': rt = ResourceTypes.RESOURCE_CACHE elif s == 'content': rt = ResourceTypes.RESOURCE_CONTENT elif s == 'no-traverse': traverseAlias = 0 elif s == 'traverse': traverseAlias = 1 else: warnings.warn("Unknown Path argument: " + str(s), RuntimeWarning, 2)
sufPathString = pathString if params: sufPathString += ';' + params
# pathString could be empty, so use [:1], not [0] if pathString[:1] == '/': #Should alias traversal logic fall in here? if self._documentRoot: dr = self._documentRoot else: #If we have no document Root then we are the document Root dr = self if len(pathString) == 1: if rt == dr.resourceType: return dr if rt == ResourceTypes.RESOURCE_METADATA: return dr.normalize('.;metadata') elif rt == ResourceTypes.RESOURCE_CACHE: return dr.normalize('.;cache') return dr.normalize('.;content') #Save a recurse here #return dr.normalize(sufPathString[1:]) return Path(sufPathString[1:], self._driver, dr, dr)
return Path(sufPathString, self._driver, self._documentRoot, self)
def getParentPath(self): """ Returns a new Path instance representing the current path's parent. """ return self.normalize('..')
def __str__(self): t = "content" if self.resourceType == ResourceTypes.RESOURCE_METADATA: t = "metadata" elif self.resourceType == ResourceTypes.RESOURCE_CACHE: t = 'cache' return "<Path '%s' abs='%s' type='%s'>" % (self.displayPath, self.absolutePath, t)
|