home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 June / maximum-cd-2011-06.iso / DiscContents / LibO_3.3.1_Win_x86_install_multi.exe / libreoffice1.cab / upload.py < prev    next >
Encoding:
Python Source  |  2011-02-15  |  6.5 KB  |  186 lines

  1. """distutils.command.upload
  2.  
  3. Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
  4.  
  5. from distutils.errors import *
  6. from distutils.core import PyPIRCCommand
  7. from distutils.spawn import spawn
  8. from distutils import log
  9. from hashlib import md5
  10. import os
  11. import socket
  12. import platform
  13. import httplib
  14. import base64
  15. import urlparse
  16. import cStringIO as StringIO
  17. from ConfigParser import ConfigParser
  18.  
  19.  
  20. class upload(PyPIRCCommand):
  21.  
  22.     description = "upload binary package to PyPI"
  23.  
  24.     user_options = PyPIRCCommand.user_options + [
  25.         ('sign', 's',
  26.          'sign files to upload using gpg'),
  27.         ('identity=', 'i', 'GPG identity used to sign files'),
  28.         ]
  29.  
  30.     boolean_options = PyPIRCCommand.boolean_options + ['sign']
  31.  
  32.     def initialize_options(self):
  33.         PyPIRCCommand.initialize_options(self)
  34.         self.username = ''
  35.         self.password = ''
  36.         self.show_response = 0
  37.         self.sign = False
  38.         self.identity = None
  39.  
  40.     def finalize_options(self):
  41.         PyPIRCCommand.finalize_options(self)
  42.         if self.identity and not self.sign:
  43.             raise DistutilsOptionError(
  44.                 "Must use --sign for --identity to have meaning"
  45.             )
  46.         config = self._read_pypirc()
  47.         if config != {}:
  48.             self.username = config['username']
  49.             self.password = config['password']
  50.             self.repository = config['repository']
  51.             self.realm = config['realm']
  52.  
  53.     def run(self):
  54.         if not self.distribution.dist_files:
  55.             raise DistutilsOptionError("No dist file created in earlier command")
  56.         for command, pyversion, filename in self.distribution.dist_files:
  57.             self.upload_file(command, pyversion, filename)
  58.  
  59.     def upload_file(self, command, pyversion, filename):
  60.         # Sign if requested
  61.         if self.sign:
  62.             gpg_args = ["gpg", "--detach-sign", "-a", filename]
  63.             if self.identity:
  64.                 gpg_args[2:2] = ["--local-user", self.identity]
  65.             spawn(gpg_args,
  66.                   dry_run=self.dry_run)
  67.  
  68.         # Fill in the data - send all the meta-data in case we need to
  69.         # register a new release
  70.         content = open(filename,'rb').read()
  71.         meta = self.distribution.metadata
  72.         data = {
  73.             # action
  74.             ':action': 'file_upload',
  75.             'protcol_version': '1',
  76.  
  77.             # identify release
  78.             'name': meta.get_name(),
  79.             'version': meta.get_version(),
  80.  
  81.             # file content
  82.             'content': (os.path.basename(filename),content),
  83.             'filetype': command,
  84.             'pyversion': pyversion,
  85.             'md5_digest': md5(content).hexdigest(),
  86.  
  87.             # additional meta-data
  88.             'metadata_version' : '1.0',
  89.             'summary': meta.get_description(),
  90.             'home_page': meta.get_url(),
  91.             'author': meta.get_contact(),
  92.             'author_email': meta.get_contact_email(),
  93.             'license': meta.get_licence(),
  94.             'description': meta.get_long_description(),
  95.             'keywords': meta.get_keywords(),
  96.             'platform': meta.get_platforms(),
  97.             'classifiers': meta.get_classifiers(),
  98.             'download_url': meta.get_download_url(),
  99.             # PEP 314
  100.             'provides': meta.get_provides(),
  101.             'requires': meta.get_requires(),
  102.             'obsoletes': meta.get_obsoletes(),
  103.             }
  104.         comment = ''
  105.         if command == 'bdist_rpm':
  106.             dist, version, id = platform.dist()
  107.             if dist:
  108.                 comment = 'built for %s %s' % (dist, version)
  109.         elif command == 'bdist_dumb':
  110.             comment = 'built for %s' % platform.platform(terse=1)
  111.         data['comment'] = comment
  112.  
  113.         if self.sign:
  114.             data['gpg_signature'] = (os.path.basename(filename) + ".asc",
  115.                                      open(filename+".asc").read())
  116.  
  117.         # set up the authentication
  118.         auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip()
  119.  
  120.         # Build up the MIME payload for the POST data
  121.         boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
  122.         sep_boundary = '\n--' + boundary
  123.         end_boundary = sep_boundary + '--'
  124.         body = StringIO.StringIO()
  125.         for key, value in data.items():
  126.             # handle multiple entries for the same name
  127.             if type(value) != type([]):
  128.                 value = [value]
  129.             for value in value:
  130.                 if type(value) is tuple:
  131.                     fn = ';filename="%s"' % value[0]
  132.                     value = value[1]
  133.                 else:
  134.                     fn = ""
  135.                 value = str(value)
  136.                 body.write(sep_boundary)
  137.                 body.write('\nContent-Disposition: form-data; name="%s"'%key)
  138.                 body.write(fn)
  139.                 body.write("\n\n")
  140.                 body.write(value)
  141.                 if value and value[-1] == '\r':
  142.                     body.write('\n')  # write an extra newline (lurve Macs)
  143.         body.write(end_boundary)
  144.         body.write("\n")
  145.         body = body.getvalue()
  146.  
  147.         self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
  148.  
  149.         # build the Request
  150.         # We can't use urllib2 since we need to send the Basic
  151.         # auth right with the first request
  152.         schema, netloc, url, params, query, fragments = \
  153.             urlparse.urlparse(self.repository)
  154.         assert not params and not query and not fragments
  155.         if schema == 'http':
  156.             http = httplib.HTTPConnection(netloc)
  157.         elif schema == 'https':
  158.             http = httplib.HTTPSConnection(netloc)
  159.         else:
  160.             raise AssertionError, "unsupported schema "+schema
  161.  
  162.         data = ''
  163.         loglevel = log.INFO
  164.         try:
  165.             http.connect()
  166.             http.putrequest("POST", url)
  167.             http.putheader('Content-type',
  168.                            'multipart/form-data; boundary=%s'%boundary)
  169.             http.putheader('Content-length', str(len(body)))
  170.             http.putheader('Authorization', auth)
  171.             http.endheaders()
  172.             http.send(body)
  173.         except socket.error, e:
  174.             self.announce(str(e), log.ERROR)
  175.             return
  176.  
  177.         r = http.getresponse()
  178.         if r.status == 200:
  179.             self.announce('Server response (%s): %s' % (r.status, r.reason),
  180.                           log.INFO)
  181.         else:
  182.             self.announce('Upload failed (%s): %s' % (r.status, r.reason),
  183.                           log.ERROR)
  184.         if self.show_response:
  185.             print '-'*75, r.read(), '-'*75
  186.