diff -r b48991f426a7 -r 774933cf7775 Doc/howto/functional.rst --- a/Doc/howto/functional.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/howto/functional.rst Mon Dec 26 00:16:29 2011 -0500 @@ -44,14 +44,15 @@ functional languages include the ML family (Standard ML, OCaml, and other variants) and Haskell. -The designers of some computer languages choose to emphasize one particular -approach to programming. This often makes it difficult to write programs that -use a different approach. Other languages are multi-paradigm languages that -support several different approaches. Lisp, C++, and Python are -multi-paradigm; you can write programs or libraries that are largely -procedural, object-oriented, or functional in all of these languages. In a -large program, different sections might be written using different approaches; -the GUI might be object-oriented while the processing logic is procedural or +The designers of some computer languages choose to emphasize one +particular approach to programming. This often makes it difficult to +write programs that use a different approach. Other languages are +multi-paradigm languages that support several different approaches. +Lisp, C++, and Python are multi-paradigm; you can write programs or +libraries that are largely procedural, object-oriented, or functional +in all of these languages. In a large program, different sections +might be written using different approaches; the GUI might be +object-oriented while the processing logic is procedural or functional, for example. In a functional program, input flows through a set of functions. Each function @@ -1114,6 +1115,132 @@ Consult the operator module's documentation for a complete list. + +The functional module +--------------------- + +Collin Winter's `functional module `__ +provides a number of more advanced tools for functional programming. It also +reimplements several Python built-ins, trying to make them more intuitive to +those used to functional programming in other languages. + +This section contains an introduction to some of the most important functions in +``functional``; full documentation can be found at `the project's website +`__. + +``compose(outer, inner, unpack=False)`` + +The ``compose()`` function implements function composition. In other words, it +returns a wrapper around the ``outer`` and ``inner`` callables, such that the +return value from ``inner`` is fed directly to ``outer``. That is, :: + + >>> def add(a, b): + ... return a + b + ... + >>> def double(a): + ... return 2 * a + ... + >>> compose(double, add)(5, 6) + 22 + +is equivalent to :: + + >>> double(add(5, 6)) + 22 + +The ``unpack`` keyword is provided to work around the fact that Python functions +are not always `fully curried `__. By +default, it is expected that the ``inner`` function will return a single object +and that the ``outer`` function will take a single argument. Setting the +``unpack`` argument causes ``compose`` to expect a tuple from ``inner`` which +will be expanded before being passed to ``outer``. Put simply, :: + + compose(f, g)(5, 6) + +is equivalent to:: + + f(g(5, 6)) + +while :: + + compose(f, g, unpack=True)(5, 6) + +is equivalent to:: + + f(*g(5, 6)) + +Even though ``compose()`` only accepts two functions, it's trivial to build up a +version that will compose any number of functions. We'll use ``reduce()``, +``compose()`` and ``partial()`` (the last of which is provided by both +``functional`` and ``functools``). :: + + from functional import compose, partial + + multi_compose = partial(reduce, compose) + + +We can also use ``map()``, ``compose()`` and ``partial()`` to craft a version of +``"".join(...)`` that converts its arguments to string:: + + from functional import compose, partial + + join = compose("".join, partial(map, str)) + + +``flip(func)`` + +``flip()`` wraps the callable in ``func`` and causes it to receive its +non-keyword arguments in reverse order. :: + + >>> def triple(a, b, c): + ... return (a, b, c) + ... + >>> triple(5, 6, 7) + (5, 6, 7) + >>> + >>> flipped_triple = flip(triple) + >>> flipped_triple(5, 6, 7) + (7, 6, 5) + +``foldl(func, start, iterable)`` + +``foldl()`` takes a binary function, a starting value (usually some kind of +'zero'), and an iterable. The function is applied to the starting value and the +first element of the list, then the result of that and the second element of the +list, then the result of that and the third element of the list, and so on. + +This means that a call such as:: + + foldl(f, 0, [1, 2, 3]) + +is equivalent to:: + + f(f(f(0, 1), 2), 3) + + +``foldl()`` is roughly equivalent to the following recursive function:: + + def foldl(func, start, seq): + if len(seq) == 0: + return start + + return foldl(func, func(start, seq[0]), seq[1:]) + +Speaking of equivalence, the above ``foldl`` call can be expressed in terms of +the built-in ``reduce`` like so:: + + reduce(f, [1, 2, 3], 0) + + +We can use ``foldl()``, ``operator.concat()`` and ``partial()`` to write a +cleaner, more aesthetically-pleasing version of Python's ``"".join(...)`` +idiom:: + + from functional import foldl, partial from operator import concat + + join = partial(foldl, concat, "") + + Revision History and Acknowledgements ===================================== @@ -1169,10 +1296,9 @@ Mertz also wrote a 3-part series of articles on functional programming for IBM's DeveloperWorks site; see - -`part 1 `__, -`part 2 `__, and -`part 3 `__, +`part 1 `__, +`part 2 `__, and +`part 3 `__, Python documentation diff -r b48991f426a7 -r 774933cf7775 Doc/library/httplib.rst --- a/Doc/library/httplib.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/httplib.rst Mon Dec 26 00:16:29 2011 -0500 @@ -452,7 +452,7 @@ Set the host and the port for HTTP Connect Tunnelling. Normally used when it is required to do HTTPS Conection through a proxy server. - The headers argument should be a mapping of extra HTTP headers to send + The headers argument should be a mapping of extra HTTP headers to sent with the CONNECT request. .. versionadded:: 2.7 diff -r b48991f426a7 -r 774933cf7775 Doc/library/mimetypes.rst --- a/Doc/library/mimetypes.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/mimetypes.rst Mon Dec 26 00:16:29 2011 -0500 @@ -1,3 +1,4 @@ + :mod:`mimetypes` --- Map filenames to MIME types ================================================ @@ -26,31 +27,31 @@ the information :func:`init` sets up. -.. function:: guess_type(url, strict=True) +.. function:: guess_type(filename[, strict]) .. index:: pair: MIME; headers - Guess the type of a file based on its filename or URL, given by *url*. The + Guess the type of a file based on its filename or URL, given by *filename*. The return value is a tuple ``(type, encoding)`` where *type* is ``None`` if the type can't be guessed (missing or unknown suffix) or a string of the form ``'type/subtype'``, usable for a MIME :mailheader:`content-type` header. *encoding* is ``None`` for no encoding or the name of the program used to encode (e.g. :program:`compress` or :program:`gzip`). The encoding is suitable for use - as a :mailheader:`Content-Encoding` header, **not** as a + as a :mailheader:`Content-Encoding` header, *not* as a :mailheader:`Content-Transfer-Encoding` header. The mappings are table driven. Encoding suffixes are case sensitive; type suffixes are first tried case sensitively, then case insensitively. - The optional *strict* argument is a flag specifying whether the list of known MIME types + Optional *strict* is a flag specifying whether the list of known MIME types is limited to only the official types `registered with IANA - `_. - When *strict* is ``True`` (the default), only the IANA types are supported; when - *strict* is ``False``, some additional non-standard but commonly used MIME types + `_ are recognized. + When *strict* is true (the default), only the IANA types are supported; when + *strict* is false, some additional non-standard but commonly used MIME types are also recognized. -.. function:: guess_all_extensions(type, strict=True) +.. function:: guess_all_extensions(type[, strict]) Guess the extensions for a file based on its MIME type, given by *type*. The return value is a list of strings giving all possible filename extensions, @@ -58,25 +59,25 @@ been associated with any particular data stream, but would be mapped to the MIME type *type* by :func:`guess_type`. - The optional *strict* argument has the same meaning as with the :func:`guess_type` function. + Optional *strict* has the same meaning as with the :func:`guess_type` function. -.. function:: guess_extension(type, strict=True) +.. function:: guess_extension(type[, strict]) Guess the extension for a file based on its MIME type, given by *type*. The return value is a string giving a filename extension, including the leading dot (``'.'``). The extension is not guaranteed to have been associated with any - particular data stream, but would be mapped to the MIME type *type* by + particular data stream, but would be mapped to the MIME type *type* by :func:`guess_type`. If no extension can be guessed for *type*, ``None`` is returned. - The optional *strict* argument has the same meaning as with the :func:`guess_type` function. + Optional *strict* has the same meaning as with the :func:`guess_type` function. Some additional functions and data items are available for controlling the behavior of the module. -.. function:: init(files=None) +.. function:: init([files]) Initialize the internal data structures. If given, *files* must be a sequence of file names which should be used to augment the default type map. If omitted, @@ -91,26 +92,26 @@ .. function:: read_mime_types(filename) - Load the type map given in the file *filename*, if it exists. The type map is + Load the type map given in the file *filename*, if it exists. The type map is returned as a dictionary mapping filename extensions, including the leading dot (``'.'``), to strings of the form ``'type/subtype'``. If the file *filename* does not exist or cannot be read, ``None`` is returned. -.. function:: add_type(type, ext, strict=True) +.. function:: add_type(type, ext[, strict]) - Add a mapping from the MIME type *type* to the extension *ext*. When the + Add a mapping from the mimetype *type* to the extension *ext*. When the extension is already known, the new type will replace the old one. When the type is already known the extension will be added to the list of known extensions. - When *strict* is ``True`` (the default), the mapping will added to the official MIME + When *strict* is True (the default), the mapping will added to the official MIME types, otherwise to the non-standard ones. .. data:: inited Flag indicating whether or not the global data structures have been initialized. - This is set to ``True`` by :func:`init`. + This is set to true by :func:`init`. .. data:: knownfiles @@ -145,6 +146,23 @@ Dictionary mapping filename extensions to non-standard, but commonly found MIME types. +The :class:`MimeTypes` class may be useful for applications which may want more +than one MIME-type database: + + +.. class:: MimeTypes([filenames]) + + This class represents a MIME-types database. By default, it provides access to + the same database as the rest of this module. The initial database is a copy of + that provided by the module, and may be extended by loading additional + :file:`mime.types`\ -style files into the database using the :meth:`read` or + :meth:`readfp` methods. The mapping dictionaries may also be cleared before + loading additional data if the default data is not desired. + + The optional *filenames* parameter can be used to cause additional files to be + loaded "on top" of the default database. + + .. versionadded:: 2.2 An example usage of the module:: @@ -165,96 +183,70 @@ MimeTypes Objects ----------------- -The :class:`MimeTypes` class may be useful for applications which may want more -than one MIME-type database; it provides an interface similar to the one of the +:class:`MimeTypes` instances provide an interface which is very like that of the :mod:`mimetypes` module. -.. class:: MimeTypes(filenames=(), strict=True) - - This class represents a MIME-types database. By default, it provides access to - the same database as the rest of this module. The initial database is a copy of - that provided by the module, and may be extended by loading additional - :file:`mime.types`\ -style files into the database using the :meth:`read` or - :meth:`readfp` methods. The mapping dictionaries may also be cleared before - loading additional data if the default data is not desired. - - The optional *filenames* parameter can be used to cause additional files to be - loaded "on top" of the default database. - - .. attribute:: MimeTypes.suffix_map Dictionary mapping suffixes to suffixes. This is used to allow recognition of encoded files for which the encoding and the type are indicated by the same extension. For example, the :file:`.tgz` extension is mapped to :file:`.tar.gz` to allow the encoding and type to be recognized separately. This is initially a - copy of the global :data:`suffix_map` defined in the module. + copy of the global ``suffix_map`` defined in the module. .. attribute:: MimeTypes.encodings_map Dictionary mapping filename extensions to encoding types. This is initially a - copy of the global :data:`encodings_map` defined in the module. + copy of the global ``encodings_map`` defined in the module. .. attribute:: MimeTypes.types_map - Tuple containing two dictionaries, mapping filename extensions to MIME types: - the first dictionary is for the non-standards types and the second one is for - the standard types. They are initialized by :data:`common_types` and - :data:`types_map`. + Dictionary mapping filename extensions to MIME types. This is initially a copy + of the global ``types_map`` defined in the module. -.. attribute:: MimeTypes.types_map_inv +.. attribute:: MimeTypes.common_types - Tuple containing two dictionaries, mapping MIME types to a list of filename - extensions: the first dictionary is for the non-standards types and the - second one is for the standard types. They are initialized by - :data:`common_types` and :data:`types_map`. + Dictionary mapping filename extensions to non-standard, but commonly found MIME + types. This is initially a copy of the global ``common_types`` defined in the + module. -.. method:: MimeTypes.guess_extension(type, strict=True) +.. method:: MimeTypes.guess_extension(type[, strict]) Similar to the :func:`guess_extension` function, using the tables stored as part of the object. -.. method:: MimeTypes.guess_type(url, strict=True) +.. method:: MimeTypes.guess_all_extensions(type[, strict]) + + Similar to the :func:`guess_all_extensions` function, using the tables stored as part + of the object. + + +.. method:: MimeTypes.guess_type(url[, strict]) Similar to the :func:`guess_type` function, using the tables stored as part of the object. -.. method:: MimeTypes.guess_all_extensions(type, strict=True) +.. method:: MimeTypes.read(path) - Similar to the :func:`guess_all_extensions` function, using the tables stored - as part of the object. - - -.. method:: MimeTypes.read(filename, strict=True) - - Load MIME information from a file named *filename*. This uses :meth:`readfp` to + Load MIME information from a file named *path*. This uses :meth:`readfp` to parse the file. - If *strict* is ``True``, information will be added to list of standard types, - else to the list of non-standard types. +.. method:: MimeTypes.readfp(file) -.. method:: MimeTypes.readfp(fp, strict=True) - - Load MIME type information from an open file *fp*. The file must have the format of + Load MIME type information from an open file. The file must have the format of the standard :file:`mime.types` files. - If *strict* is ``True``, information will be added to the list of standard - types, else to the list of non-standard types. - -.. method:: MimeTypes.read_windows_registry(strict=True) +.. method:: MimeTypes.read_windows_registry() Load MIME type information from the Windows registry. Availability: Windows. - If *strict* is ``True``, information will be added to the list of standard - types, else to the list of non-standard types. - .. versionadded:: 2.7 diff -r b48991f426a7 -r 774933cf7775 Doc/library/operator.rst --- a/Doc/library/operator.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/operator.rst Mon Dec 26 00:16:29 2011 -0500 @@ -12,8 +12,8 @@ from operator import itemgetter -The :mod:`operator` module exports a set of efficient functions corresponding to -the intrinsic operators of Python. For example, ``operator.add(x, y)`` is +The :mod:`operator` module exports a set of functions corresponding to the +intrinsic operators of Python. For example, ``operator.add(x, y)`` is equivalent to the expression ``x+y``. The function names are those used for special class methods; variants without leading and trailing ``__`` are also provided for convenience. diff -r b48991f426a7 -r 774933cf7775 Doc/library/string.rst --- a/Doc/library/string.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/string.rst Mon Dec 26 00:16:29 2011 -0500 @@ -602,7 +602,7 @@ >>> points = 19.5 >>> total = 22 - >>> 'Correct answers: {:.2%}'.format(points/total) + >>> 'Correct answers: {:.2%}.'.format(points/total) 'Correct answers: 88.64%' Using type-specific formatting:: diff -r b48991f426a7 -r 774933cf7775 Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/subprocess.rst Mon Dec 26 00:16:29 2011 -0500 @@ -233,8 +233,8 @@ detail in the :class:`Popen` constructor documentation. -Popen Constructor -^^^^^^^^^^^^^^^^^ +Popen Constuctor +^^^^^^^^^^^^^^^^ The underlying process creation and management in this module is handled by the :class:`Popen` class. It offers a lot of flexibility so that developers diff -r b48991f426a7 -r 774933cf7775 Doc/library/syslog.rst --- a/Doc/library/syslog.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/syslog.rst Mon Dec 26 00:16:29 2011 -0500 @@ -30,7 +30,7 @@ ``openlog()`` will be called with no arguments. -.. function:: openlog([ident[, logoption[, facility]]]) +.. function:: openlog([ident[, logopt[, facility]]]) Logging options of subsequent :func:`syslog` calls can be set by calling :func:`openlog`. :func:`syslog` will call :func:`openlog` with no arguments @@ -38,7 +38,7 @@ The optional *ident* keyword argument is a string which is prepended to every message, and defaults to ``sys.argv[0]`` with leading path components - stripped. The optional *logoption* keyword argument (default is 0) is a bit + stripped. The optional *logopt* keyword argument (default is 0) is a bit field -- see below for possible values to combine. The optional *facility* keyword argument (default is :const:`LOG_USER`) sets the default facility for messages which do not have a facility explicitly encoded. @@ -98,5 +98,5 @@ logged messages, and write the messages to the destination facility used for mail logging:: - syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_MAIL) + syslog.openlog(logopt=syslog.LOG_PID, facility=syslog.LOG_MAIL) syslog.syslog('E-mail processing initiated...') diff -r b48991f426a7 -r 774933cf7775 Doc/library/ttk.rst --- a/Doc/library/ttk.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/library/ttk.rst Mon Dec 26 00:16:29 2011 -0500 @@ -1294,7 +1294,7 @@ * sticky=spec Specifies how the image is placed within the final parcel. spec - contains zero or more characters "n", "s", "w", or "e". + contains zero or more characters “n”, “s”, “w”, or “e”. * width=width Specifies a minimum width for the element. If less than zero, the diff -r b48991f426a7 -r 774933cf7775 Doc/reference/introduction.rst --- a/Doc/reference/introduction.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/reference/introduction.rst Mon Dec 26 00:16:29 2011 -0500 @@ -65,7 +65,7 @@ An alternate Python for .NET. Unlike Python.NET, this is a complete Python implementation that generates IL, and compiles Python code directly to .NET assemblies. It was created by Jim Hugunin, the original creator of Jython. For - more information, see `the IronPython website `_. + more information, see `the IronPython website `_. PyPy An implementation of Python written completely in Python. It supports several diff -r b48991f426a7 -r 774933cf7775 Doc/reference/simple_stmts.rst --- a/Doc/reference/simple_stmts.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/reference/simple_stmts.rst Mon Dec 26 00:16:29 2011 -0500 @@ -352,7 +352,7 @@ del_stmt: "del" `target_list` Deletion is recursively defined very similar to the way assignment is defined. -Rather than spelling it out in full details, here are some hints. +Rather that spelling it out in full details, here are some hints. Deletion of a target list recursively deletes each target, from left to right. diff -r b48991f426a7 -r 774933cf7775 Doc/tutorial/introduction.rst --- a/Doc/tutorial/introduction.rst Sun Dec 25 19:03:07 2011 +0100 +++ b/Doc/tutorial/introduction.rst Mon Dec 26 00:16:29 2011 -0500 @@ -630,13 +630,13 @@ and ``!=`` (not equal to). * The *body* of the loop is *indented*: indentation is Python's way of grouping - statements. At the interactive prompt, you have to type a tab or space(s) for - each indented line. In practice you will prepare more complicated input - for Python with a text editor; all decent text editors have an auto-indent - facility. When a compound statement is entered interactively, it must be - followed by a blank line to indicate completion (since the parser cannot - guess when you have typed the last line). Note that each line within a basic - block must be indented by the same amount. + statements. Python does not (yet!) provide an intelligent input line editing + facility, so you have to type a tab or space(s) for each indented line. In + practice you will prepare more complicated input for Python with a text editor; + most text editors have an auto-indent facility. When a compound statement is + entered interactively, it must be followed by a blank line to indicate + completion (since the parser cannot guess when you have typed the last line). + Note that each line within a basic block must be indented by the same amount. * The :keyword:`print` statement writes the value of the expression(s) it is given. It differs from just writing the expression you want to write (as we did diff -r b48991f426a7 -r 774933cf7775 Lib/BaseHTTPServer.py --- a/Lib/BaseHTTPServer.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/BaseHTTPServer.py Mon Dec 26 00:16:29 2011 -0500 @@ -244,11 +244,14 @@ self.request_version = version = self.default_request_version self.close_connection = 1 requestline = self.raw_requestline - requestline = requestline.rstrip('\r\n') + if requestline[-2:] == '\r\n': + requestline = requestline[:-2] + elif requestline[-1:] == '\n': + requestline = requestline[:-1] self.requestline = requestline words = requestline.split() if len(words) == 3: - command, path, version = words + [command, path, version] = words if version[:5] != 'HTTP/': self.send_error(400, "Bad request version (%r)" % version) return False @@ -274,7 +277,7 @@ "Invalid HTTP Version (%s)" % base_version_number) return False elif len(words) == 2: - command, path = words + [command, path] = words self.close_connection = 1 if command != 'GET': self.send_error(400, diff -r b48991f426a7 -r 774933cf7775 Lib/distutils/archive_util.py --- a/Lib/distutils/archive_util.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/distutils/archive_util.py Mon Dec 26 00:16:29 2011 -0500 @@ -98,7 +98,7 @@ return tarinfo if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) + tar = tarfile.open(archive_name, 'w:%s' % tar_compression[compress]) try: tar.add(base_dir, filter=_set_uid_gid) finally: diff -r b48991f426a7 -r 774933cf7775 Lib/distutils/tests/test_archive_util.py --- a/Lib/distutils/tests/test_archive_util.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/distutils/tests/test_archive_util.py Mon Dec 26 00:16:29 2011 -0500 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """Tests for distutils.archive_util.""" __revision__ = "$Id$" @@ -40,6 +41,9 @@ @unittest.skipUnless(zlib, "requires zlib") def test_make_tarball(self): + self._make_tarball('archive') + + def _make_tarball(self, target_name): # creating something to tar tmpdir = self.mkdtemp() self.write_file([tmpdir, 'file1'], 'xxx') @@ -51,7 +55,7 @@ unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0], "source and target should be on same drive") - base_name = os.path.join(tmpdir2, 'archive') + base_name = os.path.join(tmpdir2, target_name) # working with relative paths to avoid tar warnings old_dir = os.getcwd() @@ -66,7 +70,7 @@ self.assertTrue(os.path.exists(tarball)) # trying an uncompressed one - base_name = os.path.join(tmpdir2, 'archive') + base_name = os.path.join(tmpdir2, target_name) old_dir = os.getcwd() os.chdir(tmpdir) try: @@ -277,6 +281,29 @@ finally: del ARCHIVE_FORMATS['xxx'] + @unittest.skipUnless(zlib, "requires zlib") + def test_make_tarball_unicode(self): + """ + Mirror test_make_tarball, except filename is unicode. + """ + self._make_tarball(u'archive') + + @unittest.skipUnless(zlib, "requires zlib") + def test_make_tarball_unicode_latin1(self): + """ + Mirror test_make_tarball, except filename is unicode and contains + latin characters. + """ + self._make_tarball(u'årchiv') # note this isn't a real word + + @unittest.skipUnless(zlib, "requires zlib") + def test_make_tarball_unicode_extended(self): + """ + Mirror test_make_tarball, except filename is unicode and contains + characters outside the latin charset. + """ + self._make_tarball(u'のアーカイブ') # japanese for archive + def test_suite(): return unittest.makeSuite(ArchiveUtilTestCase) diff -r b48991f426a7 -r 774933cf7775 Lib/distutils/tests/test_sdist.py --- a/Lib/distutils/tests/test_sdist.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/distutils/tests/test_sdist.py Mon Dec 26 00:16:29 2011 -0500 @@ -166,6 +166,28 @@ self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz']) @unittest.skipUnless(zlib, "requires zlib") + def test_unicode_metadata_tgz(self): + """ + Unicode name or version should not break building to tar.gz format. + Reference issue #11638. + """ + + # create the sdist command with unicode parameters + dist, cmd = self.get_cmd({'name': u'fake', 'version': u'1.0'}) + + # create the sdist as gztar and run the command + cmd.formats = ['gztar'] + cmd.ensure_finalized() + cmd.run() + + # The command should have created the .tar.gz file + dist_folder = join(self.tmp_dir, 'dist') + result = os.listdir(dist_folder) + self.assertEqual(result, ['fake-1.0.tar.gz']) + + os.remove(join(dist_folder, 'fake-1.0.tar.gz')) + + @unittest.skipUnless(zlib, "requires zlib") def test_add_defaults(self): # http://bugs.python.org/issue2279 diff -r b48991f426a7 -r 774933cf7775 Lib/inspect.py --- a/Lib/inspect.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/inspect.py Mon Dec 26 00:16:29 2011 -0500 @@ -247,23 +247,12 @@ def getmembers(object, predicate=None): """Return all members of an object as (name, value) pairs sorted by name. Optionally, only return members that satisfy a given predicate.""" - if isclass(object): - mro = (object,) + getmro(object) - else: - mro = () results = [] for key in dir(object): - # First try to get the value via __dict__. Some descriptors don't - # like calling their __get__ (see bug #1785). - for base in mro: - if key in base.__dict__: - value = base.__dict__[key] - break - else: - try: - value = getattr(object, key) - except AttributeError: - continue + try: + value = getattr(object, key) + except AttributeError: + continue if not predicate or predicate(value): results.append((key, value)) results.sort() @@ -299,21 +288,30 @@ names = dir(cls) result = [] for name in names: - # Get the object associated with the name, and where it was defined. + # Get the object associated with the name. # Getting an obj from the __dict__ sometimes reveals more than # using getattr. Static and class methods are dramatic examples. - # Furthermore, some objects may raise an Exception when fetched with - # getattr(). This is the case with some descriptors (bug #1785). - # Thus, we only use getattr() as a last resort. - homecls = None - for base in (cls,) + mro: - if name in base.__dict__: - obj = base.__dict__[name] - homecls = base - break + if name in cls.__dict__: + obj = cls.__dict__[name] else: obj = getattr(cls, name) - homecls = getattr(obj, "__objclass__", homecls) + + # Figure out where it was defined. + homecls = getattr(obj, "__objclass__", None) + if homecls is None: + # search the dicts. + for base in mro: + if name in base.__dict__: + homecls = base + break + + # Get the object again, in order to get it from the defining + # __dict__ instead of via getattr (if possible). + if homecls is not None and name in homecls.__dict__: + obj = homecls.__dict__[name] + + # Also get the object via getattr. + obj_via_getattr = getattr(cls, name) # Classify the object. if isinstance(obj, staticmethod): @@ -322,18 +320,11 @@ kind = "class method" elif isinstance(obj, property): kind = "property" - elif ismethoddescriptor(obj): + elif (ismethod(obj_via_getattr) or + ismethoddescriptor(obj_via_getattr)): kind = "method" - elif isdatadescriptor(obj): + else: kind = "data" - else: - obj_via_getattr = getattr(cls, name) - if (ismethod(obj_via_getattr) or - ismethoddescriptor(obj_via_getattr)): - kind = "method" - else: - kind = "data" - obj = obj_via_getattr result.append(Attribute(name, kind, homecls, obj)) diff -r b48991f426a7 -r 774933cf7775 Lib/multiprocessing/managers.py --- a/Lib/multiprocessing/managers.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/multiprocessing/managers.py Mon Dec 26 00:16:29 2011 -0500 @@ -159,7 +159,7 @@ Listener, Client = listener_client[serializer] # do authentication later - self.listener = Listener(address=address, backlog=16) + self.listener = Listener(address=address, backlog=5) self.address = self.listener.address self.id_to_obj = {'0': (None, ())} diff -r b48991f426a7 -r 774933cf7775 Lib/pydoc.py --- a/Lib/pydoc.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/pydoc.py Mon Dec 26 00:16:29 2011 -0500 @@ -740,15 +740,8 @@ hr.maybe() push(msg) for name, kind, homecls, value in ok: - try: - value = getattr(object, name) - except Exception: - # Some descriptors may meet a failure in their __get__. - # (bug #1785) - push(self._docdescriptor(name, value, mod)) - else: - push(self.document(value, name, mod, - funcs, classes, mdict, object)) + push(self.document(getattr(object, name), name, mod, + funcs, classes, mdict, object)) push('\n') return attrs @@ -788,12 +781,7 @@ mdict = {} for key, kind, homecls, value in attrs: mdict[key] = anchor = '#' + name + '-' + key - try: - value = getattr(object, name) - except Exception: - # Some descriptors may meet a failure in their __get__. - # (bug #1785) - pass + value = getattr(object, key) try: # The value may not be hashable (e.g., a data attr with # a dict or list value). @@ -1173,15 +1161,8 @@ hr.maybe() push(msg) for name, kind, homecls, value in ok: - try: - value = getattr(object, name) - except Exception: - # Some descriptors may meet a failure in their __get__. - # (bug #1785) - push(self._docdescriptor(name, value, mod)) - else: - push(self.document(value, - name, mod, object)) + push(self.document(getattr(object, name), + name, mod, object)) return attrs def spilldescriptors(msg, attrs, predicate): diff -r b48991f426a7 -r 774933cf7775 Lib/tarfile.py --- a/Lib/tarfile.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/tarfile.py Mon Dec 26 00:16:29 2011 -0500 @@ -454,8 +454,6 @@ 0) timestamp = struct.pack("" % (self.__class__.__name__, self.server) - def __enter__(self): - self.start(threading.Event()) - self.flag.wait() - - def __exit__(self, *args): - if test_support.verbose: - sys.stdout.write(" cleanup: stopping server.\n") - self.stop() - if test_support.verbose: - sys.stdout.write(" cleanup: joining server thread.\n") - self.join() - if test_support.verbose: - sys.stdout.write(" cleanup: successfully joined.\n") - def start(self, flag=None): self.flag = flag threading.Thread.start(self) @@ -774,7 +752,12 @@ server = ThreadedEchoServer(CERTFILE, certreqs=ssl.CERT_REQUIRED, cacerts=CERTFILE, chatty=False) - with server: + flag = threading.Event() + server.start(flag) + # wait for it to start + flag.wait() + # try to connect + try: try: s = ssl.wrap_socket(socket.socket(), certfile=certfile, @@ -788,6 +771,9 @@ sys.stdout.write("\nsocket.error is %s\n" % x[1]) else: raise AssertionError("Use of invalid cert should have failed!") + finally: + server.stop() + server.join() def server_params_test(certfile, protocol, certreqs, cacertsfile, client_certfile, client_protocol=None, indata="FOO\n", @@ -805,10 +791,14 @@ chatty=chatty, connectionchatty=connectionchatty, wrap_accepting_socket=wrap_accepting_socket) - with server: - # try to connect - if client_protocol is None: - client_protocol = protocol + flag = threading.Event() + server.start(flag) + # wait for it to start + flag.wait() + # try to connect + if client_protocol is None: + client_protocol = protocol + try: s = ssl.wrap_socket(socket.socket(), certfile=client_certfile, ca_certs=cacertsfile, @@ -836,6 +826,9 @@ if test_support.verbose: sys.stdout.write(" client: closing connection.\n") s.close() + finally: + server.stop() + server.join() def try_protocol_combo(server_protocol, client_protocol, @@ -937,7 +930,12 @@ ssl_version=ssl.PROTOCOL_SSLv23, cacerts=CERTFILE, chatty=False) - with server: + flag = threading.Event() + server.start(flag) + # wait for it to start + flag.wait() + # try to connect + try: s = ssl.wrap_socket(socket.socket(), certfile=CERTFILE, ca_certs=CERTFILE, @@ -959,6 +957,9 @@ "Missing or invalid 'organizationName' field in certificate subject; " "should be 'Python Software Foundation'.") s.close() + finally: + server.stop() + server.join() def test_empty_cert(self): """Connecting with an empty cert file""" @@ -1041,8 +1042,13 @@ starttls_server=True, chatty=True, connectionchatty=True) + flag = threading.Event() + server.start(flag) + # wait for it to start + flag.wait() + # try to connect wrapped = False - with server: + try: s = socket.socket() s.setblocking(1) s.connect((HOST, server.port)) @@ -1087,6 +1093,9 @@ else: s.send("over\n") s.close() + finally: + server.stop() + server.join() def test_socketserver(self): """Using a SocketServer to create and manage SSL connections.""" @@ -1136,7 +1145,12 @@ if test_support.verbose: sys.stdout.write("\n") server = AsyncoreEchoServer(CERTFILE) - with server: + flag = threading.Event() + server.start(flag) + # wait for it to start + flag.wait() + # try to connect + try: s = ssl.wrap_socket(socket.socket()) s.connect(('127.0.0.1', server.port)) if test_support.verbose: @@ -1155,6 +1169,10 @@ if test_support.verbose: sys.stdout.write(" client: closing connection.\n") s.close() + finally: + server.stop() + # wait for server thread to end + server.join() def test_recv_send(self): """Test recv(), send() and friends.""" @@ -1167,14 +1185,19 @@ cacerts=CERTFILE, chatty=True, connectionchatty=False) - with server: - s = ssl.wrap_socket(socket.socket(), - server_side=False, - certfile=CERTFILE, - ca_certs=CERTFILE, - cert_reqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLSv1) - s.connect((HOST, server.port)) + flag = threading.Event() + server.start(flag) + # wait for it to start + flag.wait() + # try to connect + s = ssl.wrap_socket(socket.socket(), + server_side=False, + certfile=CERTFILE, + ca_certs=CERTFILE, + cert_reqs=ssl.CERT_NONE, + ssl_version=ssl.PROTOCOL_TLSv1) + s.connect((HOST, server.port)) + try: # helper methods for standardising recv* method signatures def _recv_into(): b = bytearray("\0"*100) @@ -1262,6 +1285,9 @@ s.write("over\n".encode("ASCII", "strict")) s.close() + finally: + server.stop() + server.join() def test_handshake_timeout(self): # Issue #5103: SSL handshake must respect the socket timeout diff -r b48991f426a7 -r 774933cf7775 Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py Sun Dec 25 19:03:07 2011 +0100 +++ b/Lib/test/test_tarfile.py Mon Dec 26 00:16:29 2011 -0500 @@ -994,13 +994,6 @@ finally: os.umask(original_umask) - def test_issue13639(self): - try: - with tarfile.open(unicode(tmpname, sys.getfilesystemencoding()), self.mode): - pass - except UnicodeDecodeError: - self.fail("_Stream failed to write unicode filename") - class GNUWriteTest(unittest.TestCase): # This testcase checks for correct creation of GNU Longname diff -r b48991f426a7 -r 774933cf7775 Misc/NEWS --- a/Misc/NEWS Sun Dec 25 19:03:07 2011 +0100 +++ b/Misc/NEWS Mon Dec 26 00:16:29 2011 -0500 @@ -86,12 +86,6 @@ Library ------- -- Issue #12798: Updated the mimetypes documentation. - -- Issue #13639: Accept unicode filenames in tarfile.open(mode="w|gz"). - -- Issue #1785: Fix inspect and pydoc with misbehaving descriptors. - - Issue #7502: Fix equality comparison for DocTestCase instances. Patch by Cédric Krier.