[Python-checkins] r62998 - in python/trunk: Doc/distutils/packageindex.rst Doc/distutils/uploading.rst Lib/distutils/command/register.py Lib/distutils/command/upload.py Lib/distutils/core.py Lib/distutils/dist.py Lib/distutils/tests/test_dist.py

Brett Cannon brett at python.org
Sat May 10 22:53:03 CEST 2008


r63002 reverts this to get the build working again.

On Sat, May 10, 2008 at 12:51 PM, andrew.kuchling
<python-checkins at python.org> wrote:
> Author: andrew.kuchling
> Date: Sat May 10 21:51:55 2008
> New Revision: 62998
>
> Log:
> #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.
>
> Modified:
>   python/trunk/Doc/distutils/packageindex.rst
>   python/trunk/Doc/distutils/uploading.rst
>   python/trunk/Lib/distutils/command/register.py
>   python/trunk/Lib/distutils/command/upload.py
>   python/trunk/Lib/distutils/core.py
>   python/trunk/Lib/distutils/dist.py
>   python/trunk/Lib/distutils/tests/test_dist.py
>   python/trunk/Misc/ACKS
>   python/trunk/Misc/NEWS
>
> Modified: python/trunk/Doc/distutils/packageindex.rst
> ==============================================================================
> --- python/trunk/Doc/distutils/packageindex.rst (original)
> +++ python/trunk/Doc/distutils/packageindex.rst Sat May 10 21:51:55 2008
> @@ -55,11 +55,40 @@
>
>  The format of the :file:`.pypirc` file is as follows::
>
> -   [server-login]
> +   [distutils]
> +   index-servers =
> +     pypi
> +
> +   [pypi]
>    repository: <repository-url>
>    username: <username>
>    password: <password>
>
>  *repository* can be omitted and defaults to ``http://www.python.org/pypi``.
>
> +If you want to define another server a new section can be created::
> +
> +   [distutils]
> +   index-servers =
> +     pypi
> +     other
> +
> +   [pypi]
> +   repository: <repository-url>
> +   username: <username>
> +   password: <password>
> +
> +   [other]
> +   repository: http://example.com/pypi
> +   username: <username>
> +   password: <password>
> +
> +The command can then be called with the -r option::
> +
> +   python setup.py register -r http://example.com/pypi
> +
> +Or even with the section name::
> +
> +   python setup.py register -r other
>
> +
>
> Modified: python/trunk/Doc/distutils/uploading.rst
> ==============================================================================
> --- python/trunk/Doc/distutils/uploading.rst    (original)
> +++ python/trunk/Doc/distutils/uploading.rst    Sat May 10 21:51:55 2008
> @@ -24,14 +24,20 @@
>  from the :file:`$HOME/.pypirc` file (see section :ref:`pypirc` for more on this
>  file).
>
> +You can specify another PyPI server with the :option:`--repository=*url*` option::
> +
> +   python setup.py sdist bdist_wininst upload -r http://example.com/pypi
> +
> +See section :ref:`pypirc` for more on defining several servers.
> +
>  You can use the :option:`--sign` option to tell :command:`upload` to sign each
>  uploaded file using GPG (GNU Privacy Guard).  The  :program:`gpg` program must
>  be available for execution on the system :envvar:`PATH`.  You can also specify
>  which key to use for signing using the :option:`--identity=*name*` option.
>
> -Other :command:`upload` options include  :option:`--repository=*url*` (which
> -lets you override the repository setting from :file:`$HOME/.pypirc`), and
> +Other :command:`upload` options include  :option:`--repository=*url*`
> +or :option:`--repository=*section*` where `url` is the url of the server
> +and `section` the name of the section in :file:`$HOME/.pypirc`, and
>  :option:`--show-response` (which displays the full response text from the PyPI
>  server for help in debugging upload problems).
>
> -
>
> Modified: python/trunk/Lib/distutils/command/register.py
> ==============================================================================
> --- python/trunk/Lib/distutils/command/register.py      (original)
> +++ python/trunk/Lib/distutils/command/register.py      Sat May 10 21:51:55 2008
> @@ -8,37 +8,29 @@
>  __revision__ = "$Id$"
>
>  import os, string, urllib2, getpass, urlparse
> -import StringIO, ConfigParser
> +import StringIO
>
> -from distutils.core import Command
> +from distutils.core import PyPIRCCommand
>  from distutils.errors import *
> +from distutils import log
>
> -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()
> @@ -77,6 +69,23 @@
>                       "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.
>         '''
> @@ -90,6 +99,7 @@
>         (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.
>
> @@ -99,10 +109,14 @@
>
>             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
>
> @@ -114,21 +128,15 @@
>              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()
> @@ -155,32 +163,24 @@
>             # 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)
> +            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, 0600)
> -                    except:
> -                        pass
> +                    self._store_pypirc(username, password)
> +
>         elif choice == '2':
>             data = {':action': 'user'}
>             data['name'] = data['password'] = data['email'] = ''
> @@ -243,7 +243,8 @@
>     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
>
> Modified: python/trunk/Lib/distutils/command/upload.py
> ==============================================================================
> --- python/trunk/Lib/distutils/command/upload.py        (original)
> +++ python/trunk/Lib/distutils/command/upload.py        Sat May 10 21:51:55 2008
> @@ -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
> @@ -16,53 +16,38 @@
>  import urlparse
>  import cStringIO as StringIO
>
> -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:
>
> Modified: python/trunk/Lib/distutils/core.py
> ==============================================================================
> --- python/trunk/Lib/distutils/core.py  (original)
> +++ python/trunk/Lib/distutils/core.py  Sat May 10 21:51:55 2008
> @@ -20,6 +20,7 @@
>  # 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
>
> Modified: python/trunk/Lib/distutils/dist.py
> ==============================================================================
> --- python/trunk/Lib/distutils/dist.py  (original)
> +++ python/trunk/Lib/distutils/dist.py  Sat May 10 21:51:55 2008
> @@ -343,10 +343,9 @@
>             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"
>
> Modified: python/trunk/Lib/distutils/tests/test_dist.py
> ==============================================================================
> --- python/trunk/Lib/distutils/tests/test_dist.py       (original)
> +++ python/trunk/Lib/distutils/tests/test_dist.py       Sat May 10 21:51:55 2008
> @@ -55,6 +55,7 @@
>         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",
> @@ -65,6 +66,7 @@
>         self.assertEqual(d.get_command_packages(),
>                          ["distutils.command", "foo.bar", "distutils.tests"])
>         cmd = d.get_command_obj("test_dist")
> +        print cmd.__class__, test_dist
>         self.assert_(isinstance(cmd, test_dist))
>         self.assertEqual(cmd.sample_option, "sometext")
>
> @@ -179,9 +181,54 @@
>         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")
>
> Modified: python/trunk/Misc/ACKS
> ==============================================================================
> --- python/trunk/Misc/ACKS      (original)
> +++ python/trunk/Misc/ACKS      Sat May 10 21:51:55 2008
> @@ -758,3 +758,4 @@
>  Uwe Zessin
>  Amaury Forgeot d'Arc
>  Peter Åstrand
> +Tarek ZiadŽ
>
> Modified: python/trunk/Misc/NEWS
> ==============================================================================
> --- python/trunk/Misc/NEWS      (original)
> +++ python/trunk/Misc/NEWS      Sat May 10 21:51:55 2008
> @@ -369,6 +369,11 @@
>   platforms when x is too large to fit into an IEEE 754 float; previously
>   it only raised OverflowError on non IEEE 754 platforms.
>
> +- Issues #2166, #1741 and #1531505: now distutils deals with HOME
> +  correctly under win32
> +
> +- distutils: added multiple server support in .pypirc
> +
>  - Issue #1106316: pdb.post_mortem()'s parameter, "traceback", is now
>   optional: it defaults to the traceback of the exception that is currently
>   being handled (is mandatory to be in the middle of an exception, otherwise
>
> _______________________________________________
> Python-checkins mailing list
> Python-checkins at python.org
> http://mail.python.org/mailman/listinfo/python-checkins
>
>


More information about the Python-checkins mailing list