Back to index

plone3  3.1.7
upload.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Marshall: A framework for pluggable marshalling policies
00003 # Copyright (C) 2004-2006 Enfold Systems, LLC
00004 #
00005 # This program is free software; you can redistribute it and/or modify
00006 # it under the terms of the GNU General Public License as published by
00007 # the Free Software Foundation; either version 2 of the License, or
00008 # (at your option) any later version.
00009 #
00010 # This program is distributed in the hope that it will be useful,
00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 # GNU General Public License for more details.
00014 #
00015 # You should have received a copy of the GNU General Public License
00016 # along with this program; if not, write to the Free Software
00017 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 #
00019 
00020 """
00021 ATXML data uploader
00022 Give it a list of ATXML files, and it will do a PUT
00023 to the server of those files, plus any "content" with the
00024 same base name but different extension. If no list is specified,
00025 will use all in the current directory.
00026 
00027 Doesn't currently iterate over directories.
00028 
00029 If you want to use this for content without ATXML files,
00030 set the ATXML extension as the content
00031 
00032 $Id: __init__.py 2886 2004-08-25 03:51:04Z dreamcatcher $
00033 """
00034 
00035 import os, sys, time
00036 import httplib, urllib
00037 import string
00038 from optparse import OptionParser
00039 from base64 import encodestring
00040 from WebDAV import davlib     # not the standard davlib
00041 from xml.dom import minidom
00042 
00043 class FakeResponse: pass
00044 
00045 def upload(content, conn, path):
00046     if content:
00047         return conn.put(path, content, content_type='text/html')
00048     else:
00049         x = FakeResponse()
00050         x.status = 0
00051         return x
00052 
00053 def getText(nodelist):
00054     """DOM helper, for extracting text"""
00055     rc = ""
00056     for node in nodelist:
00057         if node.nodeType == node.TEXT_NODE:
00058             rc = rc + node.data
00059     return rc
00060 
00061 start = time.time()
00062 
00063 usage = "usage: %prog [options] server[:port] /path/to/col/ [atxml files...]"
00064 parser = OptionParser(usage=usage)
00065 parser.add_option("-u", "--username", dest="username",
00066                  help="WebDAV user name", metavar="USER",
00067                  default="admin")
00068 parser.add_option("-p", "--password", dest="password",
00069                  help="WebDAV password", metavar="PASS",
00070                  default="admin")
00071 parser.add_option("-a", "--atxml", dest="atxmlend",
00072                  help="File extension of ATXML", metavar=".atxml",
00073                  default=".atxml")
00074 parser.add_option("-c", "--content", dest="contentend",
00075                  help="File extension of content", metavar=".xml",
00076                  default=".xml")
00077 parser.add_option("-s", "--server", dest="serverend",
00078                  help="File extension on server", metavar=".html",
00079                  default=".html")
00080 (options, args) = parser.parse_args()
00081 
00082 if len(args) < 2:
00083     print "Error: Server and path are required. Use -h for help."
00084     print
00085     sys.exit(-1)
00086 
00087 if len(args) > 2:
00088     print "Using ATXML files supplied on commandline:"
00089     files = args[2:]
00090 else:
00091     print "Using all ATXML files in directory:"
00092     files = [x for x in os.listdir(".") if x.endswith(options.atxmlend)]
00093 
00094 server = args[0]
00095 pathstarts = args[1].rstrip('/')+'/'
00096 conn = davlib.DAV(server, timeout=300)
00097 conn.setauth(options.username, options.password)
00098 
00099 bad = []
00100 count = 0
00101 for file in files:
00102     try:
00103         metafile = open(file)
00104         metacontent = metafile.read()
00105 
00106         name = metafile.name
00107         print name,
00108         if not name.endswith(options.atxmlend):
00109             print "Not properly named. Expected to end with '%s'" % options.atxmlend
00110             continue
00111         if len(options.atxmlend) > 0:
00112             id = fid = name[:-len(options.atxmlend)]
00113         else:
00114             id = fid = name
00115 
00116         metafile.close()
00117 
00118         try:
00119             f = open(fid+options.contentend)
00120             content = f.read()
00121             f.close()
00122         except IOError:
00123             content = ""
00124 
00125         # find our true id, regardless of file name, if specified in the file
00126         try:
00127             dom = minidom.parseString(metacontent)
00128             field = [x for x in dom.getElementsByTagName('field') \
00129                      if x.getAttribute("id")=="id"][0]
00130             id = getText(field.childNodes) or fid
00131             dom.unlink()
00132         except:
00133             pass
00134 
00135         path = "%s%s%s" % (pathstarts,id,options.serverend)
00136         print "-> %s" % path,
00137 
00138         errormeta = None
00139         response = upload(metacontent, conn, path)
00140         if not response.status in(201, 204):
00141             errormeta = "%s %s" % (response.status,response.reason)
00142         #print response.status,
00143 
00144         errorcontent = None
00145         response = upload(content, conn, path)
00146         if not response.status in (204, 0):
00147             errorcontent = "%s %s" % (response.status,response.reason)
00148         #print response.status,
00149 
00150         if errormeta or errorcontent:
00151             print "FAIL"
00152             print "   Metadata: %s" % errormeta
00153             print "   Content:  %s" % errorcontent
00154             bad += [name]
00155         else:
00156             print "ok"
00157             count += 1
00158     except "ExpatError":
00159         print "FAIL: malformed ATXML file"
00160         bad += [name]
00161     except Exception, e:
00162         print "FAIL"
00163         print "  %s" % e
00164         bad += [name]
00165 
00166 conn.close()
00167 
00168 end = time.time()
00169 
00170 print "Successfully imported: %s pieces out of %s" % (`count`,`len(files)`)
00171 print "Time elapsed: %s" % `end-start`
00172 print
00173 print "There were %s failures: " % `len(bad)`,
00174 for num in bad:
00175     print num,