home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Inkscape / Inkscape-0.48.2-1-win32.exe / python / Lib / distutils / command / upload.py < prev    next >
Encoding:
Python Source  |  2010-05-29  |  6.7 KB  |  187 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. from base64 import standard_b64encode
  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 " + standard_b64encode(self.username + ":" +
  119.                                              self.password)
  120.  
  121.         # Build up the MIME payload for the POST data
  122.         boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
  123.         sep_boundary = '\n--' + boundary
  124.         end_boundary = sep_boundary + '--'
  125.         body = StringIO.StringIO()
  126.         for key, value in data.items():
  127.             # handle multiple entries for the same name
  128.             if type(value) != type([]):
  129.                 value = [value]
  130.             for value in value:
  131.                 if type(value) is tuple:
  132.                     fn = ';filename="%s"' % value[0]
  133.                     value = value[1]
  134.                 else:
  135.                     fn = ""
  136.  
  137.                 body.write(sep_boundary)
  138.                 body.write('\nContent-Disposition: form-data; name="%s"'%key)
  139.                 body.write(fn)
  140.                 body.write("\n\n")
  141.                 body.write(value)
  142.                 if value and value[-1] == '\r':
  143.                     body.write('\n')  # write an extra newline (lurve Macs)
  144.         body.write(end_boundary)
  145.         body.write("\n")
  146.         body = body.getvalue()
  147.  
  148.         self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
  149.  
  150.         # build the Request
  151.         # We can't use urllib2 since we need to send the Basic
  152.         # auth right with the first request
  153.         schema, netloc, url, params, query, fragments = \
  154.             urlparse.urlparse(self.repository)
  155.         assert not params and not query and not fragments
  156.         if schema == 'http':
  157.             http = httplib.HTTPConnection(netloc)
  158.         elif schema == 'https':
  159.             http = httplib.HTTPSConnection(netloc)
  160.         else:
  161.             raise AssertionError, "unsupported schema "+schema
  162.  
  163.         data = ''
  164.         loglevel = log.INFO
  165.         try:
  166.             http.connect()
  167.             http.putrequest("POST", url)
  168.             http.putheader('Content-type',
  169.                            'multipart/form-data; boundary=%s'%boundary)
  170.             http.putheader('Content-length', str(len(body)))
  171.             http.putheader('Authorization', auth)
  172.             http.endheaders()
  173.             http.send(body)
  174.         except socket.error, e:
  175.             self.announce(str(e), log.ERROR)
  176.             return
  177.  
  178.         r = http.getresponse()
  179.         if r.status == 200:
  180.             self.announce('Server response (%s): %s' % (r.status, r.reason),
  181.                           log.INFO)
  182.         else:
  183.             self.announce('Upload failed (%s): %s' % (r.status, r.reason),
  184.                           log.ERROR)
  185.         if self.show_response:
  186.             print '-'*75, r.read(), '-'*75
  187.