Back to index

python3.2  3.2.2
Public Member Functions | Public Attributes | Static Public Attributes
distutils.command.upload.upload Class Reference
Inheritance diagram for distutils.command.upload.upload:
Inheritance graph
[legend]
Collaboration diagram for distutils.command.upload.upload:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def initialize_options
def finalize_options
def run
def upload_file

Public Attributes

 username
 password
 show_response
 sign
 identity
 repository
 realm

Static Public Attributes

string description = "upload binary package to PyPI"
list user_options
list boolean_options = PyPIRCCommand.boolean_options+['sign']

Detailed Description

Definition at line 24 of file upload.py.


Member Function Documentation

Definition at line 44 of file upload.py.

00044 
00045     def finalize_options(self):
00046         PyPIRCCommand.finalize_options(self)
00047         if self.identity and not self.sign:
00048             raise DistutilsOptionError(
00049                 "Must use --sign for --identity to have meaning"
00050             )
00051         config = self._read_pypirc()
00052         if config != {}:
00053             self.username = config['username']
00054             self.password = config['password']
00055             self.repository = config['repository']
00056             self.realm = config['realm']
00057 
00058         # getting the password from the distribution
00059         # if previously set by the register command
00060         if not self.password and self.distribution.password:
00061             self.password = self.distribution.password

Here is the call graph for this function:

Definition at line 36 of file upload.py.

00036 
00037     def initialize_options(self):
00038         PyPIRCCommand.initialize_options(self)
00039         self.username = ''
00040         self.password = ''
00041         self.show_response = 0
00042         self.sign = False
00043         self.identity = None

Definition at line 62 of file upload.py.

00062 
00063     def run(self):
00064         if not self.distribution.dist_files:
00065             raise DistutilsOptionError("No dist file created in earlier command")
00066         for command, pyversion, filename in self.distribution.dist_files:
00067             self.upload_file(command, pyversion, filename)

Here is the call graph for this function:

Here is the caller graph for this function:

def distutils.command.upload.upload.upload_file (   self,
  command,
  pyversion,
  filename 
)

Definition at line 68 of file upload.py.

00068 
00069     def upload_file(self, command, pyversion, filename):
00070         # Sign if requested
00071         if self.sign:
00072             gpg_args = ["gpg", "--detach-sign", "-a", filename]
00073             if self.identity:
00074                 gpg_args[2:2] = ["--local-user", self.identity]
00075             spawn(gpg_args,
00076                   dry_run=self.dry_run)
00077 
00078         # Fill in the data - send all the meta-data in case we need to
00079         # register a new release
00080         f = open(filename,'rb')
00081         try:
00082             content = f.read()
00083         finally:
00084             f.close()
00085         meta = self.distribution.metadata
00086         data = {
00087             # action
00088             ':action': 'file_upload',
00089             'protcol_version': '1',
00090 
00091             # identify release
00092             'name': meta.get_name(),
00093             'version': meta.get_version(),
00094 
00095             # file content
00096             'content': (os.path.basename(filename),content),
00097             'filetype': command,
00098             'pyversion': pyversion,
00099             'md5_digest': md5(content).hexdigest(),
00100 
00101             # additional meta-data
00102             'metadata_version' : '1.0',
00103             'summary': meta.get_description(),
00104             'home_page': meta.get_url(),
00105             'author': meta.get_contact(),
00106             'author_email': meta.get_contact_email(),
00107             'license': meta.get_licence(),
00108             'description': meta.get_long_description(),
00109             'keywords': meta.get_keywords(),
00110             'platform': meta.get_platforms(),
00111             'classifiers': meta.get_classifiers(),
00112             'download_url': meta.get_download_url(),
00113             # PEP 314
00114             'provides': meta.get_provides(),
00115             'requires': meta.get_requires(),
00116             'obsoletes': meta.get_obsoletes(),
00117             }
00118         comment = ''
00119         if command == 'bdist_rpm':
00120             dist, version, id = platform.dist()
00121             if dist:
00122                 comment = 'built for %s %s' % (dist, version)
00123         elif command == 'bdist_dumb':
00124             comment = 'built for %s' % platform.platform(terse=1)
00125         data['comment'] = comment
00126 
00127         if self.sign:
00128             data['gpg_signature'] = (os.path.basename(filename) + ".asc",
00129                                      open(filename+".asc").read())
00130 
00131         # set up the authentication
00132         user_pass = (self.username + ":" + self.password).encode('ascii')
00133         # The exact encoding of the authentication string is debated.
00134         # Anyway PyPI only accepts ascii for both username or password.
00135         auth = "Basic " + standard_b64encode(user_pass).decode('ascii')
00136 
00137         # Build up the MIME payload for the POST data
00138         boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
00139         sep_boundary = b'\n--' + boundary.encode('ascii')
00140         end_boundary = sep_boundary + b'--'
00141         body = io.BytesIO()
00142         for key, value in data.items():
00143             title = '\nContent-Disposition: form-data; name="%s"' % key
00144             # handle multiple entries for the same name
00145             if type(value) != type([]):
00146                 value = [value]
00147             for value in value:
00148                 if type(value) is tuple:
00149                     title += '; filename="%s"' % value[0]
00150                     value = value[1]
00151                 else:
00152                     value = str(value).encode('utf-8')
00153                 body.write(sep_boundary)
00154                 body.write(title.encode('utf-8'))
00155                 body.write(b"\n\n")
00156                 body.write(value)
00157                 if value and value[-1:] == b'\r':
00158                     body.write(b'\n')  # write an extra newline (lurve Macs)
00159         body.write(end_boundary)
00160         body.write(b"\n")
00161         body = body.getvalue()
00162 
00163         self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
00164 
00165         # build the Request
00166         # We can't use urllib since we need to send the Basic
00167         # auth right with the first request
00168         # TODO(jhylton): Can we fix urllib?
00169         schema, netloc, url, params, query, fragments = \
00170             urllib.parse.urlparse(self.repository)
00171         assert not params and not query and not fragments
00172         if schema == 'http':
00173             http = httpclient.HTTPConnection(netloc)
00174         elif schema == 'https':
00175             http = httpclient.HTTPSConnection(netloc)
00176         else:
00177             raise AssertionError("unsupported schema "+schema)
00178 
00179         data = ''
00180         loglevel = log.INFO
00181         try:
00182             http.connect()
00183             http.putrequest("POST", url)
00184             http.putheader('Content-type',
00185                            'multipart/form-data; boundary=%s'%boundary)
00186             http.putheader('Content-length', str(len(body)))
00187             http.putheader('Authorization', auth)
00188             http.endheaders()
00189             http.send(body)
00190         except socket.error as e:
00191             self.announce(str(e), log.ERROR)
00192             return
00193 
00194         r = http.getresponse()
00195         if r.status == 200:
00196             self.announce('Server response (%s): %s' % (r.status, r.reason),
00197                           log.INFO)
00198         else:
00199             self.announce('Upload failed (%s): %s' % (r.status, r.reason),
00200                           log.ERROR)
00201         if self.show_response:
00202             msg = '\n'.join(('-' * 75, r.read(), '-' * 75))
00203             self.announce(msg, log.INFO)

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

list distutils.command.upload.upload.boolean_options = PyPIRCCommand.boolean_options+['sign'] [static]

Definition at line 34 of file upload.py.

string distutils.command.upload.upload.description = "upload binary package to PyPI" [static]

Definition at line 26 of file upload.py.

Definition at line 42 of file upload.py.

Definition at line 39 of file upload.py.

Definition at line 55 of file upload.py.

Definition at line 54 of file upload.py.

Definition at line 40 of file upload.py.

Definition at line 41 of file upload.py.

Initial value:
PyPIRCCommand.user_options+[
        ('sign', 's',
         'sign files to upload using gpg'),
        ('identity=', 'i', 'GPG identity used to sign files'),
        ]

Definition at line 28 of file upload.py.

Definition at line 38 of file upload.py.


The documentation for this class was generated from the following file: