ソースを参照

Adding other directory routines (rmdir, mkdir, mkdirs) and uploadFile

Andrej Studen 6 年 前
コミット
ed2a849dbb
1 ファイル変更134 行追加19 行削除
  1. 134 19
      labkeySlicerPythonExtension/slicerNetwork.py

+ 134 - 19
labkeySlicerPythonExtension/slicerNetwork.py

@@ -11,6 +11,21 @@ import distutils
 import os
 import base64
 
+#see https://gist.github.com/logic/2715756, allow requests to do Put
+class MethodRequest(urllib2.Request):
+    def __init__(self, *args, **kwargs):
+        if 'method' in kwargs:
+            self._method = kwargs['method']
+            del kwargs['method']
+        else:
+            self._method = None
+        return urllib2.Request.__init__(self, *args, **kwargs)
+
+    def get_method(self, *args, **kwargs):
+        if self._method is not None:
+            return self._method
+        return urllib2.Request.get_method(self, *args, **kwargs)
+
 class slicerNetwork:
     def __init__(self,parent):
         parent.title = "slicerNetwork"
@@ -49,13 +64,43 @@ class labkeyURIHandler(slicer.vtkURIHandler):
     def GetLocalCacheDirectory(self):
         return self.localCacheDirectory
 
+    def GetLabkeyUrl(self):
+        return self.hostname+"/labkey/_webdav"
+
     def GetLocalPath(self,source):
+        debug=False
         relativePath=re.sub('labkey://','',source)
         sp=os.sep.encode('string-escape')
-        print "Substituting / with {0} in {1}".format(sp,relativePath)
+        if debug:
+            print "Substituting / with {0} in {1}".format(sp,relativePath)
         relativePath=re.sub('/',sp,relativePath)
         return os.path.join(self.localCacheDirectory,relativePath)
 
+    def GetRemotePath(self,source):
+        return self.GetLabkeyUrl()+"/"+GetLabkeyPathFromLocalPath(source)
+
+    def GetLabkeyPathFromLocalPath(self,f):
+        #report it with URL separator, forward-slash
+        if f.find(self.localCacheDirectory)<-1:
+            print "Localpath misformation. Exiting"
+            return "NULL"
+        dest=re.sub(self.localCacheDirectory,'',f)
+        #leaves /ContextPath/%40files/subdirectory_list/files
+        #remove first separator
+        sp=os.sep.encode('string-escape')
+        if dest[0]==sp:
+            dest=dest[1:len(dest)]
+        return re.sub(sp,'/',dest)
+
+    def GetLabkeyPathFromRemotePath(self,f):
+        #used to query labkey stuff, so URL separator is used
+        f=re.sub('labkey://','',f)
+        f=re.sub(self.GetLabkeyUrl(),'',f)
+        if f[0]=='/':
+            f=f[1:len(f)]
+        return f;
+
+
     def GetFile(self,source):
         # check for file in cache. If available, use, if not, download
         localPath=self.GetLocalPath(source)
@@ -179,10 +224,72 @@ class labkeyURIHandler(slicer.vtkURIHandler):
         f=self.opener.open(r)
         #f contains json as a return value
 
+    def put(self,url,data):
+
+        r=MethodRequest(url,method="PUT")
+        #makes it a post
+        r.add_data(data)
+        r.add_header("content-type","application/octet-stream")
+        base64string = base64.b64encode('%s:%s' % (self.auth_name, self.auth_pass))
+        r.add_header("Authorization", "Basic %s" % base64string)
+
+        f=self.opener.open(r)
+        #f contains json as a return value
+
+    def remoteDirExists(self,url):
+        status,dirs=self.listRemoteDir(url);
+        return status
+
+    def mkdir(self,remoteDir):
+        if self.remoteDirExists(remoteDir):
+            return False
+        r=MethodRequest(remoteDir,method="MKCOL")
+        base64string = base64.b64encode('%s:%s' % (self.auth_name, self.auth_pass))
+        r.add_header("Authorization", "Basic %s" % base64string)
+        try:
+            f=self.opener.open(r)
+        except:
+            print "Error: Failed MKCOL {}".format(remoteDir)
+            return False
+        return True
+
+    def mkdirs(self,remoteDir):
+        labkeyPath=self.GetLabkeyPathFromRemotePath(remoteDir)
+        s=0
+        while True:
+            s1=labkeyPath.find('/',s)
+            if s1<0:
+                break
+            path=labkeyPath[0:s1]
+            remotePath=self.GetLabkeyUrl()+'/'+path
+            dirExists=self.remoteDirExists(remotePath)
+            if not dirExists:
+                if not self.mkdir(remotePath):
+                    return False
+            s=s1+1
+        return self.mkdir(remoteDir)
+
+    def rmdir(self,remoteDir):
+        if not self.remoteDirExists(remoteDir):
+            return True
+        r=MethodRequest(remoteDir,method="DELETE")
+        base64string = base64.b64encode('%s:%s' % (self.auth_name, self.auth_pass))
+        r.add_header("Authorization", "Basic %s" % base64string)
+        try:
+            f=self.opener.open(r)
+        except:
+            print "Error: Failed DELETE {}".format(remoteDir)
+            return False
+        return True
+
     def listDir(self,dir):
         print "Listing for {0}".format(dir)
-        dirUrl=self.hostname+"/labkey/_webdav"+"/"+dir
-        r=propfindRequest(dirUrl)
+        dirUrl=self.GetLabkeyUrl()+"/"+dir
+        status,dirs=self.listRemoteDir(dirUrl)
+        return dirs
+
+    def listRemoteDir(self,dirUrl):
+        r=MethodRequest(dirUrl,method="PROPFIND")
         PROPFIND=u"""<?xml version="1.0" encoding="utf-8"?>\n
                     <propfind xmlns="DAV:">\n
                     <prop>\n
@@ -200,8 +307,7 @@ class labkeyURIHandler(slicer.vtkURIHandler):
         try:
             f=self.opener.open(r)
         except:
-            print "No data"
-            return dirs
+            return False,dirs
         tree=ET.XML(f.read())
         rps=tree.findall('{DAV:}response')
         for r in rps:
@@ -210,7 +316,7 @@ class labkeyURIHandler(slicer.vtkURIHandler):
             dirent=re.sub('/labkey/_webdav/','',dirent)
             dirs.append(dirent)
         del dirs[0]
-        return dirs
+        return True,dirs
 
     def toRelativePath(self,dirs):
         flist1=[]
@@ -227,6 +333,28 @@ class labkeyURIHandler(slicer.vtkURIHandler):
         f=self.get(dirUrl)
         return StringIO.StringIO(f.read())
 
+    def uploadFile(self,localPath):
+        #get upstream directories sorted out
+        labkeyPath=self.GetLabkeyPathFromLocalPath(localPath)
+        if labkeyPath=="NULL":
+            errorCode="Failed to upload {}. Potential incorrect location"
+            errorCode+=". Should be in labkeyCache!"
+            print errorCode.format(localPath)
+            return False
+        labkeyDir=labkeyPath[0:labkeyPath.rfind('/')]
+        remoteDir=self.GetLabkeyUrl()+'/'+labkeyDir
+        if not self.remoteDirExists(remoteDir):
+            if not self.mkdirs(remoteDir):
+                errorCode="UploadFile: Could not create directory {}"
+                print errorCode.format(remoteDir)
+                return False
+
+        #make an URL request
+        with open(localPath, 'r') as f:
+            data=f.read()
+        remotePath=self.GetLabkeyUrl()+'/'+labkeyPath
+        self.put(remotePath,data)
+
     def loadDir(self, path):
         #dirURL=serverUrl+"/labkey/_webdav/"+path
         files=self.listDir(path)
@@ -239,16 +367,3 @@ class labkeyURIHandler(slicer.vtkURIHandler):
                 #fails if there is a subdirectory; go recursively
                 self.readDir(f)
         return fdir
-
-class propfindRequest(urllib2.Request):
-    """
-    This request subclass allows explicit specification of
-    the HTTP request method. Basic urllib2.Request class
-    chooses GET or POST depending on self.has_data()
-    """
-    def __init__(self, *args, **kwargs):
-        #self.method = 'Propfind'
-        urllib2.Request.__init__(self, *args, **kwargs)
-
-    def get_method(self):
-        return 'PROPFIND'