Commit f71e81f1 authored by Alexandre Vassalotti's avatar Alexandre Vassalotti

Merged revisions...

Merged revisions 62998-63003,63005-63006,63009-63012,63014-63017,63019-63020,63022-63024,63026-63029,63031-63041,63043-63045,63047-63054,63056-63062 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r62998 | andrew.kuchling | 2008-05-10 15:51:55 -0400 (Sat, 10 May 2008) | 7 lines

  #1858 from Tarek Ziade:
  Allow multiple repositories in .pypirc; see http://wiki.python.org/moin/EnhancedPyPI
  for discussion.

  The patch is slightly revised from Tarek's last patch: I've simplified
  the PyPIRCCommand.finalize_options() method to not look at sys.argv.
  Tests still pass.
........
  r63000 | alexandre.vassalotti | 2008-05-10 15:59:16 -0400 (Sat, 10 May 2008) | 5 lines

  Cleaned up io._BytesIO.write().

  I am amazed that the old code, for inserting null-bytes, actually
  worked. Who wrote that thing? Oh, it is me... doh.
........
  r63002 | brett.cannon | 2008-05-10 16:52:01 -0400 (Sat, 10 May 2008) | 2 lines

  Revert r62998 as it broke the build (seems distutils.config is missing).
........
  r63014 | andrew.kuchling | 2008-05-10 18:12:38 -0400 (Sat, 10 May 2008) | 1 line

  #1858: add distutils.config module
........
  r63027 | brett.cannon | 2008-05-10 21:09:32 -0400 (Sat, 10 May 2008) | 2 lines

  Flesh out the 3.0 deprecation to suggest using the ctypes module.
........
  r63028 | skip.montanaro | 2008-05-10 22:59:30 -0400 (Sat, 10 May 2008) | 4 lines

  Copied two versions of the example from the interactive session.  Delete
  one.
........
  r63037 | georg.brandl | 2008-05-11 03:02:17 -0400 (Sun, 11 May 2008) | 2 lines

  reload() takes the module itself.
........
  r63038 | alexandre.vassalotti | 2008-05-11 03:06:04 -0400 (Sun, 11 May 2008) | 4 lines

  Added test framework for handling module renames.
  Factored the import guard in test_py3kwarn.TestStdlibRemovals into
  a context manager, namely test_support.CleanImport.
........
  r63039 | georg.brandl | 2008-05-11 03:06:05 -0400 (Sun, 11 May 2008) | 2 lines

  #2742: ``''`` is not converted to NULL in getaddrinfo.
........
  r63040 | alexandre.vassalotti | 2008-05-11 03:08:12 -0400 (Sun, 11 May 2008) | 2 lines

  Fixed typo in a comment of test_support.CleanImport.
........
  r63041 | alexandre.vassalotti | 2008-05-11 03:10:25 -0400 (Sun, 11 May 2008) | 2 lines

  Removed a dead line of code.
........
  r63043 | georg.brandl | 2008-05-11 04:47:53 -0400 (Sun, 11 May 2008) | 2 lines

  #2812: document property.getter/setter/deleter.
........
  r63049 | georg.brandl | 2008-05-11 05:06:30 -0400 (Sun, 11 May 2008) | 2 lines

  #1153769: document PEP 237 changes to string formatting.
........
  r63050 | georg.brandl | 2008-05-11 05:11:40 -0400 (Sun, 11 May 2008) | 2 lines

  #2809: elaborate str.split docstring a bit.
........
  r63051 | georg.brandl | 2008-05-11 06:13:59 -0400 (Sun, 11 May 2008) | 2 lines

  Fix typo.
........
  r63052 | georg.brandl | 2008-05-11 06:33:27 -0400 (Sun, 11 May 2008) | 2 lines

  #2709: clarification.
........
  r63053 | georg.brandl | 2008-05-11 06:42:28 -0400 (Sun, 11 May 2008) | 2 lines

  #2659: add ``break_on_hyphens`` to TextWrapper.
........
  r63057 | georg.brandl | 2008-05-11 06:59:39 -0400 (Sun, 11 May 2008) | 2 lines

  #2741: clarification of value range for address_family.
........
  r63058 | georg.brandl | 2008-05-11 07:09:35 -0400 (Sun, 11 May 2008) | 2 lines

  #2452: timeout is used for all blocking operations.
........
  r63059 | andrew.kuchling | 2008-05-11 09:33:56 -0400 (Sun, 11 May 2008) | 2 lines

  #1792: Improve performance of marshal.dumps() on large objects by increasing
  the size of the buffer more quickly.
........
  r63060 | andrew.kuchling | 2008-05-11 10:00:00 -0400 (Sun, 11 May 2008) | 1 line

  #1858: re-apply patch for this, adding the missing files
........
  r63061 | benjamin.peterson | 2008-05-11 10:13:25 -0400 (Sun, 11 May 2008) | 2 lines

  Add the "until" command to pdb
........
  r63062 | georg.brandl | 2008-05-11 10:17:13 -0400 (Sun, 11 May 2008) | 2 lines

  Add some sentence endings.
........
parent 67495c27
......@@ -8,42 +8,34 @@ Implements the Distutils 'register' command (register with the repository).
__revision__ = "$Id$"
import os, string, urllib2, getpass, urlparse
import io, configparser
import io
from distutils.core import Command
from distutils.core import PyPIRCCommand
from distutils.errors import *
from distutils import log
def raw_input(prompt):
sys.stdout.write(prompt)
sys.stdout.flush()
return sys.stdin.readline()
class register(Command):
class register(PyPIRCCommand):
description = ("register the distribution with the Python package index")
DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
user_options = [
('repository=', 'r',
"url of repository [default: %s]"%DEFAULT_REPOSITORY),
user_options = PyPIRCCommand.user_options + [
('list-classifiers', None,
'list the valid Trove classifiers'),
('show-response', None,
'display full response text from server'),
]
boolean_options = ['verify', 'show-response', 'list-classifiers']
boolean_options = PyPIRCCommand.boolean_options + [
'verify', 'list-classifiers']
def initialize_options(self):
self.repository = None
self.show_response = 0
PyPIRCCommand.initialize_options(self)
self.list_classifiers = 0
def finalize_options(self):
if self.repository is None:
self.repository = self.DEFAULT_REPOSITORY
def run(self):
self.finalize_options()
self._set_config()
self.check_metadata()
if self.dry_run:
self.verify_metadata()
......@@ -82,6 +74,23 @@ class register(Command):
"or (maintainer and maintainer_email) " +
"must be supplied")
def _set_config(self):
''' Reads the configuration file and set attributes.
'''
config = self._read_pypirc()
if config != {}:
self.username = config['username']
self.password = config['password']
self.repository = config['repository']
self.realm = config['realm']
self.has_config = True
else:
if self.repository not in ('pypi', self.DEFAULT_REPOSITORY):
raise ValueError('%s not found in .pypirc' % self.repository)
if self.repository == 'pypi':
self.repository = self.DEFAULT_REPOSITORY
self.has_config = False
def classifiers(self):
''' Fetch the list of classifiers from the server.
'''
......@@ -95,6 +104,7 @@ class register(Command):
(code, result) = self.post_to_server(self.build_post_data('verify'))
print('Server response (%s): %s'%(code, result))
def send_metadata(self):
''' Send the metadata to the package index server.
......@@ -104,10 +114,14 @@ class register(Command):
First we try to read the username/password from $HOME/.pypirc,
which is a ConfigParser-formatted file with a section
[server-login] containing username and password entries (both
[distutils] containing username and password entries (both
in clear text). Eg:
[server-login]
[distutils]
index-servers =
pypi
[pypi]
username: fred
password: sekrit
......@@ -119,21 +133,15 @@ class register(Command):
3. set the password to a random string and email the user.
'''
choice = 'x'
username = password = ''
# see if we can short-cut and get the username/password from the
# config
config = None
if 'HOME' in os.environ:
rc = os.path.join(os.environ['HOME'], '.pypirc')
if os.path.exists(rc):
print('Using PyPI login from %s'%rc)
config = ConfigParser.ConfigParser()
config.read(rc)
username = config.get('server-login', 'username')
password = config.get('server-login', 'password')
choice = '1'
if self.has_config:
choice = '1'
username = self.username
password = self.password
else:
choice = 'x'
username = password = ''
# get the user's login info
choices = '1 2 3 4'.split()
......@@ -160,32 +168,24 @@ Your selection [default 1]: ''', end=' ')
# set up the authentication
auth = urllib2.HTTPPasswordMgr()
host = urlparse.urlparse(self.repository)[1]
auth.add_password('pypi', host, username, password)
auth.add_password(self.realm, host, username, password)
# send the info to the server and report the result
code, result = self.post_to_server(self.build_post_data('submit'),
auth)
print('Server response (%s): %s'%(code, result))
# possibly save the login
if 'HOME' in os.environ and config is None and code == 200:
rc = os.path.join(os.environ['HOME'], '.pypirc')
if not self.has_config and code == 200:
print('I can store your PyPI login so future submissions will be faster.')
print('(the login will be stored in %s)'%rc)
print('(the login will be stored in %s)' % self._get_rc_file())
choice = 'X'
while choice.lower() not in 'yn':
choice = raw_input('Save your login (y/N)?')
if not choice:
choice = 'n'
if choice.lower() == 'y':
f = open(rc, 'w')
f.write('[server-login]\nusername:%s\npassword:%s\n'%(
username, password))
f.close()
try:
os.chmod(rc, 0o600)
except:
pass
self._store_pypirc(username, password)
elif choice == '2':
data = {':action': 'user'}
data['name'] = data['password'] = data['email'] = ''
......@@ -248,7 +248,8 @@ Your selection [default 1]: ''', end=' ')
def post_to_server(self, data, auth=None):
''' Post a query to the server, and return a string response.
'''
self.announce('Registering %s to %s' % (data['name'],
self.repository), log.INFO)
# Build up the MIME payload for the urllib2 POST data
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = '\n--' + boundary
......
......@@ -3,7 +3,7 @@
Implements the Distutils 'upload' subcommand (upload package to PyPI)."""
from distutils.errors import *
from distutils.core import Command
from distutils.core import PyPIRCCommand
from distutils.spawn import spawn
from distutils import log
from hashlib import md5
......@@ -15,53 +15,38 @@ import httplib
import base64
import urlparse
class upload(Command):
class upload(PyPIRCCommand):
description = "upload binary package to PyPI"
DEFAULT_REPOSITORY = 'http://pypi.python.org/pypi'
user_options = [
('repository=', 'r',
"url of repository [default: %s]" % DEFAULT_REPOSITORY),
('show-response', None,
'display full response text from server'),
user_options = PyPIRCCommand.user_options + [
('sign', 's',
'sign files to upload using gpg'),
('identity=', 'i', 'GPG identity used to sign files'),
]
boolean_options = ['show-response', 'sign']
boolean_options = PyPIRCCommand.boolean_options + ['sign']
def initialize_options(self):
PyPIRCCommand.initialize_options(self)
self.username = ''
self.password = ''
self.repository = ''
self.show_response = 0
self.sign = False
self.identity = None
def finalize_options(self):
PyPIRCCommand.finalize_options(self)
if self.identity and not self.sign:
raise DistutilsOptionError(
"Must use --sign for --identity to have meaning"
)
if 'HOME' in os.environ:
rc = os.path.join(os.environ['HOME'], '.pypirc')
if os.path.exists(rc):
self.announce('Using PyPI login from %s' % rc)
config = ConfigParser.ConfigParser({
'username':'',
'password':'',
'repository':''})
config.read(rc)
if not self.repository:
self.repository = config.get('server-login', 'repository')
if not self.username:
self.username = config.get('server-login', 'username')
if not self.password:
self.password = config.get('server-login', 'password')
if not self.repository:
self.repository = self.DEFAULT_REPOSITORY
config = self._read_pypirc()
if config != {}:
self.username = config['username']
self.password = config['password']
self.repository = config['repository']
self.realm = config['realm']
def run(self):
if not self.distribution.dist_files:
......
......@@ -49,7 +49,7 @@ class PyPIRCCommand(Command):
finally:
f.close()
try:
os.chmod(rc, 0600)
os.chmod(rc, 0o600)
except OSError:
# should do something better here
pass
......@@ -58,7 +58,7 @@ class PyPIRCCommand(Command):
"""Reads the .pypirc file."""
rc = self._get_rc_file()
if os.path.exists(rc):
print 'Using PyPI login from %s' % rc
print('Using PyPI login from %s' % rc)
repository = self.repository or self.DEFAULT_REPOSITORY
realm = self.realm or self.DEFAULT_REALM
......
......@@ -17,6 +17,7 @@ from distutils.util import grok_environment_error
# Mainly import these so setup scripts can "from distutils.core import" them.
from distutils.dist import Distribution
from distutils.cmd import Command
from distutils.config import PyPIRCCommand
from distutils.extension import Extension
# This is a barebones help message generated displayed when the user
......
......@@ -334,10 +334,9 @@ Common commands: (see '--help-commands' for more)
user_filename = "pydistutils.cfg"
# And look for the user config file
if 'HOME' in os.environ:
user_file = os.path.join(os.environ.get('HOME'), user_filename)
if os.path.isfile(user_file):
files.append(user_file)
user_file = os.path.join(os.path.expanduser('~'), user_filename)
if os.path.isfile(user_file):
files.append(user_file)
# All platforms support local setup.cfg
local_file = "setup.cfg"
......
"""Tests for distutils.pypirc.pypirc."""
import sys
import os
import unittest
from distutils.core import PyPIRCCommand
from distutils.core import Distribution
from distutils.tests import support
PYPIRC = """\
[distutils]
index-servers =
server1
server2
[server1]
username:me
password:secret
[server2]
username:meagain
password: secret
realm:acme
repository:http://another.pypi/
"""
PYPIRC_OLD = """\
[server-login]
username:tarek
password:secret
"""
class PyPIRCCommandTestCase(support.TempdirManager, unittest.TestCase):
def setUp(self):
"""Patches the environment."""
if 'HOME' in os.environ:
self._old_home = os.environ['HOME']
else:
self._old_home = None
curdir = os.path.dirname(__file__)
os.environ['HOME'] = curdir
self.rc = os.path.join(curdir, '.pypirc')
self.dist = Distribution()
class command(PyPIRCCommand):
def __init__(self, dist):
PyPIRCCommand.__init__(self, dist)
def initialize_options(self):
pass
finalize_options = initialize_options
self._cmd = command
def tearDown(self):
"""Removes the patch."""
if self._old_home is None:
del os.environ['HOME']
else:
os.environ['HOME'] = self._old_home
if os.path.exists(self.rc):
os.remove(self.rc)
def test_server_registration(self):
# This test makes sure PyPIRCCommand knows how to:
# 1. handle several sections in .pypirc
# 2. handle the old format
# new format
f = open(self.rc, 'w')
try:
f.write(PYPIRC)
finally:
f.close()
cmd = self._cmd(self.dist)
config = cmd._read_pypirc()
config = list(sorted(config.items()))
waited = [('password', 'secret'), ('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi'),
('server', 'server1'), ('username', 'me')]
self.assertEquals(config, waited)
# old format
f = open(self.rc, 'w')
f.write(PYPIRC_OLD)
f.close()
config = cmd._read_pypirc()
config = list(sorted(config.items()))
waited = [('password', 'secret'), ('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi'),
('server', 'server-login'), ('username', 'tarek')]
self.assertEquals(config, waited)
def test_suite():
return unittest.makeSuite(PyPIRCCommandTestCase)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
......@@ -55,6 +55,7 @@ class DistributionTestCase(unittest.TestCase):
self.assertEqual(d.get_command_packages(), ["distutils.command"])
def test_command_packages_cmdline(self):
from distutils.tests.test_dist import test_dist
sys.argv.extend(["--command-packages",
"foo.bar,distutils.tests",
"test_dist",
......@@ -179,9 +180,54 @@ class MetadataTestCase(unittest.TestCase):
dist.metadata.write_pkg_file(sio)
return sio.getvalue()
def test_custom_pydistutils(self):
# fixes #2166
# make sure pydistutils.cfg is found
old = {}
for env in ('HOME', 'HOMEPATH', 'HOMEDRIVE'):
value = os.environ.get(env)
old[env] = value
if value is not None:
del os.environ[env]
if os.name == 'posix':
user_filename = ".pydistutils.cfg"
else:
user_filename = "pydistutils.cfg"
curdir = os.path.dirname(__file__)
user_filename = os.path.join(curdir, user_filename)
f = open(user_filename, 'w')
f.write('.')
f.close()
try:
dist = distutils.dist.Distribution()
# linux-style
if sys.platform in ('linux', 'darwin'):
os.environ['HOME'] = curdir
files = dist.find_config_files()
self.assert_(user_filename in files)
# win32-style
if sys.platform == 'win32':
# home drive should be found
os.environ['HOMEPATH'] = curdir
files = dist.find_config_files()
self.assert_(user_filename in files)
finally:
for key, value in old.items():
if value is None:
continue
os.environ[key] = value
os.remove(user_filename)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DistributionTestCase))
suite.addTest(unittest.makeSuite(MetadataTestCase))
return suite
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
"""Tests for distutils.command.upload."""
import sys
import os
import unittest
from distutils.command.upload import upload
from distutils.core import Distribution
from distutils.tests import support
from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
class uploadTestCase(PyPIRCCommandTestCase):
def test_finalize_options(self):
# new format
f = open(self.rc, 'w')
f.write(PYPIRC)
f.close()
dist = Distribution()
cmd = upload(dist)
cmd.finalize_options()
for attr, waited in (('username', 'me'), ('password', 'secret'),
('realm', 'pypi'),
('repository', 'http://pypi.python.org/pypi')):
self.assertEquals(getattr(cmd, attr), waited)
def test_suite():
return unittest.makeSuite(uploadTestCase)
if __name__ == "__main__":
unittest.main(defaultTest="test_suite")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment