]> git.rkrishnan.org Git - tahoe-lafs/zfec.git/blob - zfec/setuptools-0.6c15dev.egg/setuptools/command/upload.py
setup: install_requires argparse only if Python version is < 2.7
[tahoe-lafs/zfec.git] / zfec / setuptools-0.6c15dev.egg / setuptools / command / upload.py
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 Command
7 from distutils.spawn import spawn
8 from distutils import log
9 try:
10     from hashlib import md5
11 except ImportError:
12     from md5 import md5
13 import os
14 import socket
15 import platform
16 import ConfigParser
17 import httplib
18 import base64
19 import urlparse
20 import cStringIO as StringIO
21
22 class upload(Command):
23
24     description = "upload binary package to PyPI"
25
26     DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
27
28     user_options = [
29         ('repository=', 'r',
30          "url of repository [default: %s]" % DEFAULT_REPOSITORY),
31         ('show-response', None,
32          'display full response text from server'),
33         ('sign', 's',
34          'sign files to upload using gpg'),
35         ('identity=', 'i', 'GPG identity used to sign files'),
36         ]
37     boolean_options = ['show-response', 'sign']
38
39     def initialize_options(self):
40         self.username = ''
41         self.password = ''
42         self.repository = ''
43         self.show_response = 0
44         self.sign = False
45         self.identity = None
46
47     def finalize_options(self):
48         if self.identity and not self.sign:
49             raise DistutilsOptionError(
50                 "Must use --sign for --identity to have meaning"
51             )
52         if os.environ.has_key('HOME'):
53             rc = os.path.join(os.environ['HOME'], '.pypirc')
54             if os.path.exists(rc):
55                 self.announce('Using PyPI login from %s' % rc)
56                 config = ConfigParser.ConfigParser({
57                         'username':'',
58                         'password':'',
59                         'repository':''})
60                 config.read(rc)
61                 if not self.repository:
62                     self.repository = config.get('server-login', 'repository')
63                 if not self.username:
64                     self.username = config.get('server-login', 'username')
65                 if not self.password:
66                     self.password = config.get('server-login', 'password')
67         if not self.repository:
68             self.repository = self.DEFAULT_REPOSITORY
69
70     def run(self):
71         if not self.distribution.dist_files:
72             raise DistutilsOptionError("No dist file created in earlier command")
73         for command, pyversion, filename in self.distribution.dist_files:
74             self.upload_file(command, pyversion, filename)
75
76     def upload_file(self, command, pyversion, filename):
77         # Sign if requested
78         if self.sign:
79             gpg_args = ["gpg", "--detach-sign", "-a", filename]
80             if self.identity:
81                 gpg_args[2:2] = ["--local-user", self.identity]
82             spawn(gpg_args,
83                   dry_run=self.dry_run)
84
85         # Fill in the data
86         content = open(filename,'rb').read()
87         basename = os.path.basename(filename)
88         comment = ''
89         if command=='bdist_egg' and self.distribution.has_ext_modules():
90             comment = "built on %s" % platform.platform(terse=1)
91         data = {
92             ':action':'file_upload',
93             'protcol_version':'1',
94             'name':self.distribution.get_name(),
95             'version':self.distribution.get_version(),
96             'content':(basename,content),
97             'filetype':command,
98             'pyversion':pyversion,
99             'md5_digest':md5(content).hexdigest(),
100             }
101         if command == 'bdist_rpm':
102             dist, version, id = platform.dist()
103             if dist:
104                 comment = 'built for %s %s' % (dist, version)
105         elif command == 'bdist_dumb':
106             comment = 'built for %s' % platform.platform(terse=1)
107         data['comment'] = comment
108
109         if self.sign:
110             data['gpg_signature'] = (os.path.basename(filename) + ".asc",
111                                      open(filename+".asc").read())
112
113         # set up the authentication
114         auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip()
115
116         # Build up the MIME payload for the POST data
117         boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
118         sep_boundary = '\n--' + boundary
119         end_boundary = sep_boundary + '--'
120         body = StringIO.StringIO()
121         for key, value in data.items():
122             # handle multiple entries for the same name
123             if type(value) != type([]):
124                 value = [value]
125             for value in value:
126                 if type(value) is tuple:
127                     fn = ';filename="%s"' % value[0]
128                     value = value[1]
129                 else:
130                     fn = ""
131                 value = str(value)
132                 body.write(sep_boundary)
133                 body.write('\nContent-Disposition: form-data; name="%s"'%key)
134                 body.write(fn)
135                 body.write("\n\n")
136                 body.write(value)
137                 if value and value[-1] == '\r':
138                     body.write('\n')  # write an extra newline (lurve Macs)
139         body.write(end_boundary)
140         body.write("\n")
141         body = body.getvalue()
142
143         self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
144
145         # build the Request
146         # We can't use urllib2 since we need to send the Basic
147         # auth right with the first request
148         schema, netloc, url, params, query, fragments = \
149             urlparse.urlparse(self.repository)
150         assert not params and not query and not fragments
151         if schema == 'http':
152             http = httplib.HTTPConnection(netloc)
153         elif schema == 'https':
154             http = httplib.HTTPSConnection(netloc)
155         else:
156             raise AssertionError, "unsupported schema "+schema
157
158         data = ''
159         loglevel = log.INFO
160         try:
161             http.connect()
162             http.putrequest("POST", url)
163             http.putheader('Content-type',
164                            'multipart/form-data; boundary=%s'%boundary)
165             http.putheader('Content-length', str(len(body)))
166             http.putheader('Authorization', auth)
167             http.endheaders()
168             http.send(body)
169         except socket.error, e:
170             self.announce(str(e), log.ERROR)
171             return
172
173         r = http.getresponse()
174         if r.status == 200:
175             self.announce('Server response (%s): %s' % (r.status, r.reason),
176                           log.INFO)
177         else:
178             self.announce('Upload failed (%s): %s' % (r.status, r.reason),
179                           log.ERROR)
180         if self.show_response:
181             print '-'*75, r.read(), '-'*75