symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/distutils/command/upload.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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