+++ /dev/null
-'''
-Upload script specifically engineered for the PyWeek challenge.
-
-Handles authentication and gives upload progress feedback.
-'''
-import sys, os, httplib, cStringIO, socket, time, getopt
-
-class Upload:
- def __init__(self, filename):
- self.filename = filename
-
-boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
-sep_boundary = '\n--' + boundary
-end_boundary = sep_boundary + '--'
-
-def mimeEncode(data, sep_boundary=sep_boundary, end_boundary=end_boundary):
- '''Take the mapping of data and construct the body of a
- multipart/form-data message with it using the indicated boundaries.
- '''
- ret = cStringIO.StringIO()
- for key, value in data.items():
- # handle multiple entries for the same name
- if type(value) != type([]): value = [value]
- for value in value:
- ret.write(sep_boundary)
- if isinstance(value, Upload):
- ret.write('\nContent-Disposition: form-data; name="%s"'%key)
- filename = os.path.basename(value.filename)
- ret.write('; filename="%s"\n\n'%filename)
- value = open(os.path.join(value.filename), "rb").read()
- else:
- ret.write('\nContent-Disposition: form-data; name="%s"'%key)
- ret.write("\n\n")
- value = str(value)
- ret.write(str(value))
- if value and value[-1] == '\r':
- ret.write('\n') # write an extra newline
- ret.write(end_boundary)
- return ret.getvalue()
-
-class Progress:
- def __init__(self, info, data):
- self.info = info
- self.tosend = len(data)
- self.total = self.tosend/1024
- self.data = cStringIO.StringIO(data)
- self.start = self.now = time.time()
- self.sent = 0
- self.num = 0
- self.stepsize = self.total / 100 or 1
- self.steptimes = []
- self.display()
-
- def __iter__(self): return self
-
- def next(self):
- self.num += 1
- if self.sent >= self.tosend:
- print self.info, 'done', ' '*(75-len(self.info)-6)
- sys.stdout.flush()
- raise StopIteration
-
- chunk = self.data.read(1024)
- self.sent += len(chunk)
- #print (self.num, self.stepsize, self.total, self.sent, self.tosend)
-
- if self.num % self.stepsize:
- return chunk
- self.display()
- return chunk
-
- def display(self):
- # figure how long we've spent - guess how long to go
- now = time.time()
- steptime = now - self.now
- self.steptimes.insert(0, steptime)
- if len(self.steptimes) > 5:
- self.steptimes.pop()
- steptime = sum(self.steptimes) / len(self.steptimes)
- self.now = now
- eta = steptime * ((self.total - self.num)/self.stepsize)
-
- # tell it like it is (or might be)
- if now - self.start > 3:
- M = eta / 60
- H = M / 60
- M = M % 60
- S = eta % 60
- if self.total:
- s = '%s %2d%% (ETA %02d:%02d:%02d)'%(self.info,
- self.num * 100. / self.total, H, M, S)
- else:
- s = '%s 0%% (ETA %02d:%02d:%02d)'%(self.info, H, M, S)
- elif self.total:
- s = '%s %2d%%'%(self.info, self.num * 100. / self.total)
- else:
- s = '%s %d done'%(self.info, self.num)
- sys.stdout.write(s + ' '*(75-len(s)) + '\r')
- sys.stdout.flush()
-
-class progressHTTPConnection(httplib.HTTPConnection):
- def progress_send(self, str):
- """Send `str' to the server."""
- if self.sock is None:
- self.connect()
-
- p = Progress('Uploading', str)
- for chunk in p:
- sent = 0
- while sent != len(chunk):
- try:
- sent += self.sock.send(chunk)
- except socket.error, v:
- if v[0] == 32: # Broken pipe
- self.close()
- raise
- p.display()
-
-class progressHTTP(httplib.HTTP):
- _connection_class = progressHTTPConnection
- def _setup(self, conn):
- httplib.HTTP._setup(self, conn)
- self.progress_send = self._conn.progress_send
-
-def http_request(data, server, port, url):
- h = progressHTTP(server, port)
-
- data = mimeEncode(data)
- h.putrequest('POST', url)
- h.putheader('Content-type', 'multipart/form-data; boundary=%s'%boundary)
- h.putheader('Content-length', str(len(data)))
- h.putheader('Host', server)
- h.endheaders()
-
- h.progress_send(data)
-
- errcode, errmsg, headers = h.getreply()
-
- f = h.getfile()
- response = f.read().strip()
- f.close()
-
- print '%s %s'%(errcode, errmsg)
- if response: print response
-
-def usage():
- print '''This program is to be used to upload files to the PyWeek system.
-You may use it to upload screenshots or code submissions.
-
-REQUIRED ARGUMENTS:
- -u username
- -p password
- -d description of file
- -c file to upload
- -e entry short name
-
-OPTIONAL ARGUMENTS:
- -s file is a screenshot
- -f file is FINAL submission
- -h override default host name (www.pyweek.org)
- -P override default host port (80)
-
-In order to qualify for judging at the end of the challenge, you MUST
-upload your source and check the "Final Submission" checkbox.
-'''
-
-
-if __name__ == '__main__':
- try:
- optlist, args = getopt.getopt(sys.argv[1:], 'e:u:p:sfd:h:P:c:')
- except getopt.GetoptError, message:
- print message
- usage()
- sys.exit(1)
- host = 'www.pyweek.org'
- port = 80
- data = dict(version=2)
- optional = {}
- url = None
- for opt, arg in optlist:
- if opt == '-u': data['user'] = arg
- elif opt == '-p': data['password'] = arg
- elif opt == '-s': optional['is_screenshot'] = 'yes'
- elif opt == '-f': optional['is_final'] = 'yes'
- elif opt == '-d': data['description'] = arg
- elif opt == '-c': data['content_file'] = Upload(arg)
- elif opt == '-e': url = '/e/%s/oup/'%arg
- elif opt == '-h': host = arg
- elif opt == '-P': port = int(arg)
-
- if len(data) < 4 or url is None:
- print 'Required argument missing'
- usage()
- sys.exit(1)
-
- data.update(optional)
- http_request(data, host, port, url)
-