register.py (8996B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\distutils\command\register.py 2 __revision__ = '$Id: register.py 82110 2010-06-20 13:38:51Z kristjan.jonsson $' 3 import urllib2 4 import getpass 5 import urlparse 6 import StringIO 7 from warnings import warn 8 from distutils.core import PyPIRCCommand 9 from distutils import log 10 11 class register(PyPIRCCommand): 12 description = 'register the distribution with the Python package index' 13 user_options = PyPIRCCommand.user_options + [('list-classifiers', None, 'list the valid Trove classifiers'), ('strict', None, 'Will stop the registering if the meta-data are not fully compliant')] 14 boolean_options = PyPIRCCommand.boolean_options + ['verify', 'list-classifiers', 'strict'] 15 sub_commands = [('check', lambda self: True)] 16 17 def initialize_options(self): 18 PyPIRCCommand.initialize_options(self) 19 self.list_classifiers = 0 20 self.strict = 0 21 22 def finalize_options(self): 23 PyPIRCCommand.finalize_options(self) 24 check_options = {'strict': ('register', self.strict), 25 'restructuredtext': ('register', 1)} 26 self.distribution.command_options['check'] = check_options 27 28 def run(self): 29 self.finalize_options() 30 self._set_config() 31 for cmd_name in self.get_sub_commands(): 32 self.run_command(cmd_name) 33 34 if self.dry_run: 35 self.verify_metadata() 36 elif self.list_classifiers: 37 self.classifiers() 38 else: 39 self.send_metadata() 40 41 def check_metadata(self): 42 warn('distutils.command.register.check_metadata is deprecated, use the check command instead', PendingDeprecationWarning) 43 check = self.distribution.get_command_obj('check') 44 check.ensure_finalized() 45 check.strict = self.strict 46 check.restructuredtext = 1 47 check.run() 48 49 def _set_config(self): 50 config = self._read_pypirc() 51 if config != {}: 52 self.username = config['username'] 53 self.password = config['password'] 54 self.repository = config['repository'] 55 self.realm = config['realm'] 56 self.has_config = True 57 else: 58 if self.repository not in ('pypi', self.DEFAULT_REPOSITORY): 59 raise ValueError('%s not found in .pypirc' % self.repository) 60 if self.repository == 'pypi': 61 self.repository = self.DEFAULT_REPOSITORY 62 self.has_config = False 63 64 def classifiers(self): 65 response = urllib2.urlopen(self.repository + '?:action=list_classifiers') 66 log.info(response.read()) 67 68 def verify_metadata(self): 69 code, result = self.post_to_server(self.build_post_data('verify')) 70 log.info('Server response (%s): %s' % (code, result)) 71 72 def send_metadata(self): 73 if self.has_config: 74 choice = '1' 75 username = self.username 76 password = self.password 77 else: 78 choice = 'x' 79 username = password = '' 80 choices = '1 2 3 4'.split() 81 while choice not in choices: 82 self.announce('We need to know who you are, so please choose either:\n 1. use your existing login,\n 2. register as a new user,\n 3. have the server generate a new password for you (and email it to you), or\n 4. quit\nYour selection [default 1]: ', log.INFO) 83 choice = raw_input() 84 if not choice: 85 choice = '1' 86 elif choice not in choices: 87 print 'Please choose one of the four options!' 88 89 if choice == '1': 90 while not username: 91 username = raw_input('Username: ') 92 93 while not password: 94 password = getpass.getpass('Password: ') 95 96 auth = urllib2.HTTPPasswordMgr() 97 host = urlparse.urlparse(self.repository)[1] 98 auth.add_password(self.realm, host, username, password) 99 code, result = self.post_to_server(self.build_post_data('submit'), auth) 100 self.announce('Server response (%s): %s' % (code, result), log.INFO) 101 if code == 200: 102 if self.has_config: 103 self.distribution.password = password 104 else: 105 self.announce('I can store your PyPI login so future submissions will be faster.', log.INFO) 106 self.announce('(the login will be stored in %s)' % self._get_rc_file(), log.INFO) 107 choice = 'X' 108 while choice.lower() not in 'yn': 109 choice = raw_input('Save your login (y/N)?') 110 if not choice: 111 choice = 'n' 112 113 if choice.lower() == 'y': 114 self._store_pypirc(username, password) 115 elif choice == '2': 116 data = {':action': 'user'} 117 data['name'] = data['password'] = data['email'] = '' 118 data['confirm'] = None 119 while not data['name']: 120 data['name'] = raw_input('Username: ') 121 122 while data['password'] != data['confirm']: 123 while not data['password']: 124 data['password'] = getpass.getpass('Password: ') 125 126 while not data['confirm']: 127 data['confirm'] = getpass.getpass(' Confirm: ') 128 129 if data['password'] != data['confirm']: 130 data['password'] = '' 131 data['confirm'] = None 132 print "Password and confirm don't match!" 133 134 while not data['email']: 135 data['email'] = raw_input(' EMail: ') 136 137 code, result = self.post_to_server(data) 138 if code != 200: 139 log.info('Server response (%s): %s' % (code, result)) 140 else: 141 log.info('You will receive an email shortly.') 142 log.info('Follow the instructions in it to complete registration.') 143 elif choice == '3': 144 data = {':action': 'password_reset'} 145 data['email'] = '' 146 while not data['email']: 147 data['email'] = raw_input('Your email address: ') 148 149 code, result = self.post_to_server(data) 150 log.info('Server response (%s): %s' % (code, result)) 151 152 def build_post_data(self, action): 153 meta = self.distribution.metadata 154 data = {':action': action, 155 'metadata_version': '1.0', 156 'name': meta.get_name(), 157 'version': meta.get_version(), 158 'summary': meta.get_description(), 159 'home_page': meta.get_url(), 160 'author': meta.get_contact(), 161 'author_email': meta.get_contact_email(), 162 'license': meta.get_licence(), 163 'description': meta.get_long_description(), 164 'keywords': meta.get_keywords(), 165 'platform': meta.get_platforms(), 166 'classifiers': meta.get_classifiers(), 167 'download_url': meta.get_download_url(), 168 'provides': meta.get_provides(), 169 'requires': meta.get_requires(), 170 'obsoletes': meta.get_obsoletes()} 171 if data['provides'] or data['requires'] or data['obsoletes']: 172 data['metadata_version'] = '1.1' 173 return data 174 175 def post_to_server(self, data, auth = None): 176 if 'name' in data: 177 self.announce('Registering %s to %s' % (data['name'], self.repository), log.INFO) 178 boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' 179 sep_boundary = '\n--' + boundary 180 end_boundary = sep_boundary + '--' 181 body = StringIO.StringIO() 182 for key, value in data.items(): 183 if type(value) not in (type([]), type(())): 184 value = [value] 185 for value in value: 186 body.write(sep_boundary) 187 body.write('\nContent-Disposition: form-data; name="%s"' % key) 188 body.write('\n\n') 189 body.write(value) 190 if value and value[-1] == '\r': 191 body.write('\n') 192 193 body.write(end_boundary) 194 body.write('\n') 195 body = body.getvalue() 196 headers = {'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8' % boundary, 197 'Content-length': str(len(body))} 198 req = urllib2.Request(self.repository, body, headers) 199 opener = urllib2.build_opener(urllib2.HTTPBasicAuthHandler(password_mgr=auth)) 200 data = '' 201 try: 202 result = opener.open(req) 203 except urllib2.HTTPError as e: 204 if self.show_response: 205 data = e.fp.read() 206 result = (e.code, e.msg) 207 except urllib2.URLError as e: 208 result = (500, str(e)) 209 else: 210 if self.show_response: 211 data = result.read() 212 result = (200, 'OK') 213 214 if self.show_response: 215 dashes = '-' * 75 216 self.announce('%s%s%s' % (dashes, data, dashes)) 217 return result