diff options
-rw-r--r-- | Doc/library/io.rst | 7 | ||||
-rw-r--r-- | Doc/whatsnew/3.3.rst | 12 | ||||
-rw-r--r-- | Lib/_pyio.py | 22 | ||||
-rw-r--r-- | Lib/argparse.py | 37 | ||||
-rw-r--r-- | Lib/ipaddress.py | 136 | ||||
-rw-r--r-- | Lib/test/test_argparse.py | 79 | ||||
-rw-r--r-- | Lib/test/test_io.py | 10 | ||||
-rw-r--r-- | Lib/test/test_ipaddress.py | 158 | ||||
-rw-r--r-- | Lib/test/test_xmlrpc.py | 16 | ||||
-rw-r--r-- | Lib/trace.py | 3 | ||||
-rw-r--r-- | Misc/NEWS | 8 | ||||
-rw-r--r-- | Modules/_io/bufferedio.c | 42 | ||||
-rw-r--r-- | Tools/ccbench/ccbench.py | 1 | ||||
-rwxr-xr-x | Tools/demo/life.py | 89 | ||||
-rwxr-xr-x | Tools/demo/ss1.py | 1 | ||||
-rwxr-xr-x | Tools/i18n/pygettext.py | 1 | ||||
-rw-r--r-- | Tools/iobench/iobench.py | 2 | ||||
-rw-r--r-- | Tools/parser/unparse.py | 1 | ||||
-rwxr-xr-x | Tools/pybench/pybench.py | 6 | ||||
-rw-r--r-- | Tools/unicode/makeunicodedata.py | 1 |
20 files changed, 310 insertions, 322 deletions
diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 1d3d702..dd98a46 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -604,8 +604,6 @@ than raw I/O does. *raw* stream. If the *buffer_size* is not given, it defaults to :data:`DEFAULT_BUFFER_SIZE`. - A third argument, *max_buffer_size*, is supported, but unused and deprecated. - :class:`BufferedWriter` provides or overrides these methods in addition to those from :class:`BufferedIOBase` and :class:`IOBase`: @@ -631,8 +629,6 @@ than raw I/O does. in the first argument. If the *buffer_size* is omitted it defaults to :data:`DEFAULT_BUFFER_SIZE`. - A third argument, *max_buffer_size*, is supported, but unused and deprecated. - :class:`BufferedRandom` is capable of anything :class:`BufferedReader` or :class:`BufferedWriter` can do. @@ -647,9 +643,6 @@ than raw I/O does. writeable respectively. If the *buffer_size* is omitted it defaults to :data:`DEFAULT_BUFFER_SIZE`. - A fourth argument, *max_buffer_size*, is supported, but unused and - deprecated. - :class:`BufferedRWPair` implements all of :class:`BufferedIOBase`\'s methods except for :meth:`~BufferedIOBase.detach`, which raises :exc:`UnsupportedOperation`. diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index 38a9f35..e3eddc4 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -477,6 +477,18 @@ new, more precise information:: '<function C.D.meth at 0x7f46b9fe31e0>' +PEP 412: Key-Sharing Dictionary +=============================== + +:pep:`412` - Key-Sharing Dictionary + PEP written and implemented by Mark Shannon. + +Dictionaries used for the storage of objects' attributes are now able to +share part of their internal storage between each other (namely, the part +which stores the keys and their respective hashes). This reduces the memory +consumption of programs creating many instances of non-builtin types. + + Using importlib as the Implementation of Import =============================================== :issue:`2377` - Replace __import__ w/ importlib.__import__ diff --git a/Lib/_pyio.py b/Lib/_pyio.py index c06f4b8..1ce61e9 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -5,7 +5,6 @@ Python implementation of the io module. import os import abc import codecs -import warnings import errno # Import _thread instead of threading to reduce startup cost try: @@ -1065,19 +1064,13 @@ class BufferedWriter(_BufferedIOMixin): DEFAULT_BUFFER_SIZE. """ - _warning_stack_offset = 2 - - def __init__(self, raw, - buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): if not raw.writable(): raise IOError('"raw" argument must be writable.') _BufferedIOMixin.__init__(self, raw) if buffer_size <= 0: raise ValueError("invalid buffer size") - if max_buffer_size is not None: - warnings.warn("max_buffer_size is deprecated", DeprecationWarning, - self._warning_stack_offset) self.buffer_size = buffer_size self._write_buf = bytearray() self._write_lock = Lock() @@ -1167,15 +1160,11 @@ class BufferedRWPair(BufferedIOBase): # XXX The usefulness of this (compared to having two separate IO # objects) is questionable. - def __init__(self, reader, writer, - buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + def __init__(self, reader, writer, buffer_size=DEFAULT_BUFFER_SIZE): """Constructor. The arguments are two RawIO instances. """ - if max_buffer_size is not None: - warnings.warn("max_buffer_size is deprecated", DeprecationWarning, 2) - if not reader.readable(): raise IOError('"reader" argument must be readable.') @@ -1232,13 +1221,10 @@ class BufferedRandom(BufferedWriter, BufferedReader): defaults to DEFAULT_BUFFER_SIZE. """ - _warning_stack_offset = 3 - - def __init__(self, raw, - buffer_size=DEFAULT_BUFFER_SIZE, max_buffer_size=None): + def __init__(self, raw, buffer_size=DEFAULT_BUFFER_SIZE): raw._checkSeekable() BufferedReader.__init__(self, raw, buffer_size) - BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) + BufferedWriter.__init__(self, raw, buffer_size) def seek(self, pos, whence=0): if whence not in valid_seek_flags: diff --git a/Lib/argparse.py b/Lib/argparse.py index 87d0cef..ab3ec4b 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1579,7 +1579,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): usage=None, description=None, epilog=None, - version=None, parents=[], formatter_class=HelpFormatter, prefix_chars='-', @@ -1588,14 +1587,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): conflict_handler='error', add_help=True): - if version is not None: - import warnings - warnings.warn( - """The "version" argument to ArgumentParser is deprecated. """ - """Please use """ - """"add_argument(..., action='version', version="N", ...)" """ - """instead""", DeprecationWarning) - superinit = super(ArgumentParser, self).__init__ superinit(description=description, prefix_chars=prefix_chars, @@ -1609,7 +1600,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): self.prog = prog self.usage = usage self.epilog = epilog - self.version = version self.formatter_class = formatter_class self.fromfile_prefix_chars = fromfile_prefix_chars self.add_help = add_help @@ -1624,7 +1614,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): return string self.register('type', None, identity) - # add help and version arguments if necessary + # add help argument if necessary # (using explicit default to override global argument_default) default_prefix = '-' if '-' in prefix_chars else prefix_chars[0] if self.add_help: @@ -1632,12 +1622,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): default_prefix+'h', default_prefix*2+'help', action='help', default=SUPPRESS, help=_('show this help message and exit')) - if self.version: - self.add_argument( - default_prefix+'v', default_prefix*2+'version', - action='version', default=SUPPRESS, - version=self.version, - help=_("show program's version number and exit")) # add parent arguments and defaults for parent in parents: @@ -1657,7 +1641,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): 'prog', 'usage', 'description', - 'version', 'formatter_class', 'conflict_handler', 'add_help', @@ -2320,16 +2303,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # determine help from format above return formatter.format_help() - def format_version(self): - import warnings - warnings.warn( - 'The format_version method is deprecated -- the "version" ' - 'argument to ArgumentParser is no longer supported.', - DeprecationWarning) - formatter = self._get_formatter() - formatter.add_text(self.version) - return formatter.format_help() - def _get_formatter(self): return self.formatter_class(prog=self.prog) @@ -2346,14 +2319,6 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): file = _sys.stdout self._print_message(self.format_help(), file) - def print_version(self, file=None): - import warnings - warnings.warn( - 'The print_version method is deprecated -- the "version" ' - 'argument to ArgumentParser is no longer supported.', - DeprecationWarning) - self._print_message(self.format_version(), file) - def _print_message(self, message, file=None): if message: if file is None: diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index b1e07fc..2019009 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -12,7 +12,7 @@ __version__ = '1.0' import struct - +import functools IPV4LENGTH = 32 IPV6LENGTH = 128 @@ -405,7 +405,38 @@ def get_mixed_type_key(obj): return NotImplemented -class _IPAddressBase: +class _TotalOrderingMixin: + # Helper that derives the other comparison operations from + # __lt__ and __eq__ + def __eq__(self, other): + raise NotImplementedError + def __ne__(self, other): + equal = self.__eq__(other) + if equal is NotImplemented: + return NotImplemented + return not equal + def __lt__(self, other): + raise NotImplementedError + def __le__(self, other): + less = self.__lt__(other) + if less is NotImplemented or not less: + return self.__eq__(other) + return less + def __gt__(self, other): + less = self.__lt__(other) + if less is NotImplemented: + return NotImplemented + equal = self.__eq__(other) + if equal is NotImplemented: + return NotImplemented + return not (less or equal) + def __ge__(self, other): + less = self.__lt__(other) + if less is NotImplemented: + return NotImplemented + return not less + +class _IPAddressBase(_TotalOrderingMixin): """The mother class.""" @@ -465,7 +496,6 @@ class _IPAddressBase: prefixlen = self._prefixlen return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) - class _BaseAddress(_IPAddressBase): """A generic IP object. @@ -493,24 +523,6 @@ class _BaseAddress(_IPAddressBase): except AttributeError: return NotImplemented - def __ne__(self, other): - eq = self.__eq__(other) - if eq is NotImplemented: - return NotImplemented - return not eq - - def __le__(self, other): - gt = self.__gt__(other) - if gt is NotImplemented: - return NotImplemented - return not gt - - def __ge__(self, other): - lt = self.__lt__(other) - if lt is NotImplemented: - return NotImplemented - return not lt - def __lt__(self, other): if self._version != other._version: raise TypeError('%s and %s are not of the same version' % ( @@ -522,17 +534,6 @@ class _BaseAddress(_IPAddressBase): return self._ip < other._ip return False - def __gt__(self, other): - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - self, other)) - if not isinstance(other, _BaseAddress): - raise TypeError('%s and %s are not of the same type' % ( - self, other)) - if self._ip != other._ip: - return self._ip > other._ip - return False - # Shorthand for Integer addition and subtraction. This is not # meant to ever support addition/subtraction of addresses. def __add__(self, other): @@ -625,31 +626,6 @@ class _BaseNetwork(_IPAddressBase): return self.netmask < other.netmask return False - def __gt__(self, other): - if self._version != other._version: - raise TypeError('%s and %s are not of the same version' % ( - self, other)) - if not isinstance(other, _BaseNetwork): - raise TypeError('%s and %s are not of the same type' % ( - self, other)) - if self.network_address != other.network_address: - return self.network_address > other.network_address - if self.netmask != other.netmask: - return self.netmask > other.netmask - return False - - def __le__(self, other): - gt = self.__gt__(other) - if gt is NotImplemented: - return NotImplemented - return not gt - - def __ge__(self, other): - lt = self.__lt__(other) - if lt is NotImplemented: - return NotImplemented - return not lt - def __eq__(self, other): try: return (self._version == other._version and @@ -658,12 +634,6 @@ class _BaseNetwork(_IPAddressBase): except AttributeError: return NotImplemented - def __ne__(self, other): - eq = self.__eq__(other) - if eq is NotImplemented: - return NotImplemented - return not eq - def __hash__(self): return hash(int(self.network_address) ^ int(self.netmask)) @@ -1292,11 +1262,27 @@ class IPv4Interface(IPv4Address): self.network.prefixlen) def __eq__(self, other): + address_equal = IPv4Address.__eq__(self, other) + if not address_equal or address_equal is NotImplemented: + return address_equal try: - return (IPv4Address.__eq__(self, other) and - self.network == other.network) + return self.network == other.network except AttributeError: + # An interface with an associated network is NOT the + # same as an unassociated address. That's why the hash + # takes the extra info into account. + return False + + def __lt__(self, other): + address_less = IPv4Address.__lt__(self, other) + if address_less is NotImplemented: return NotImplemented + try: + return self.network < other.network + except AttributeError: + # We *do* allow addresses and interfaces to be sorted. The + # unassociated address is considered less than all interfaces. + return False def __hash__(self): return self._ip ^ self._prefixlen ^ int(self.network.network_address) @@ -1928,11 +1914,27 @@ class IPv6Interface(IPv6Address): self.network.prefixlen) def __eq__(self, other): + address_equal = IPv6Address.__eq__(self, other) + if not address_equal or address_equal is NotImplemented: + return address_equal try: - return (IPv6Address.__eq__(self, other) and - self.network == other.network) + return self.network == other.network except AttributeError: + # An interface with an associated network is NOT the + # same as an unassociated address. That's why the hash + # takes the extra info into account. + return False + + def __lt__(self, other): + address_less = IPv6Address.__lt__(self, other) + if address_less is NotImplemented: return NotImplemented + try: + return self.network < other.network + except AttributeError: + # We *do* allow addresses and interfaces to be sorted. The + # unassociated address is considered less than all interfaces. + return False def __hash__(self): return self._ip ^ self._prefixlen ^ int(self.network.network_address) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index f456709..e69cc40 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1323,20 +1323,21 @@ class TestParserDefaultSuppress(ParserTestCase): class TestParserDefault42(ParserTestCase): """Test actions with a parser-level default of 42""" - parser_signature = Sig(argument_default=42, version='1.0') + parser_signature = Sig(argument_default=42) argument_signatures = [ + Sig('--version', action='version', version='1.0'), Sig('foo', nargs='?'), Sig('bar', nargs='*'), Sig('--baz', action='store_true'), ] failures = ['-x'] successes = [ - ('', NS(foo=42, bar=42, baz=42)), - ('a', NS(foo='a', bar=42, baz=42)), - ('a b', NS(foo='a', bar=['b'], baz=42)), - ('--baz', NS(foo=42, bar=42, baz=True)), - ('a --baz', NS(foo='a', bar=42, baz=True)), - ('--baz a b', NS(foo='a', bar=['b'], baz=True)), + ('', NS(foo=42, bar=42, baz=42, version=42)), + ('a', NS(foo='a', bar=42, baz=42, version=42)), + ('a b', NS(foo='a', bar=['b'], baz=42, version=42)), + ('--baz', NS(foo=42, bar=42, baz=True, version=42)), + ('a --baz', NS(foo='a', bar=42, baz=True, version=42)), + ('--baz a b', NS(foo='a', bar=['b'], baz=True, version=42)), ] @@ -2896,10 +2897,9 @@ class TestHelpFormattingMetaclass(type): parser_text = sfile.getvalue() self._test(tester, parser_text) - # add tests for {format,print}_{usage,help,version} + # add tests for {format,print}_{usage,help} for func_suffix, std_name in [('usage', 'stdout'), - ('help', 'stdout'), - ('version', 'stderr')]: + ('help', 'stdout')]: AddTests(cls, func_suffix, std_name) bases = TestCase, @@ -2910,8 +2910,9 @@ class TestHelpBiggerOptionals(HelpTestCase): """Make sure that argument help aligns when options are longer""" parser_signature = Sig(prog='PROG', description='DESCRIPTION', - epilog='EPILOG', version='0.1') + epilog='EPILOG') argument_signatures = [ + Sig('-v', '--version', action='version', version='0.1'), Sig('-x', action='store_true', help='X HELP'), Sig('--y', help='Y HELP'), Sig('foo', help='FOO HELP'), @@ -2946,8 +2947,9 @@ class TestHelpBiggerOptionalGroups(HelpTestCase): """Make sure that argument help aligns when options are longer""" parser_signature = Sig(prog='PROG', description='DESCRIPTION', - epilog='EPILOG', version='0.1') + epilog='EPILOG') argument_signatures = [ + Sig('-v', '--version', action='version', version='0.1'), Sig('-x', action='store_true', help='X HELP'), Sig('--y', help='Y HELP'), Sig('foo', help='FOO HELP'), @@ -3114,9 +3116,9 @@ HHAAHHH class TestHelpWrappingLongNames(HelpTestCase): """Make sure that text after long names starts on the next line""" - parser_signature = Sig(usage='USAGE', description= 'D D' * 30, - version='V V'*30) + parser_signature = Sig(usage='USAGE', description= 'D D' * 30) argument_signatures = [ + Sig('-v', '--version', action='version', version='V V' * 30), Sig('-x', metavar='X' * 25, help='XH XH' * 20), Sig('y', metavar='y' * 25, help='YH YH' * 20), ] @@ -3719,8 +3721,9 @@ class TestHelpNoHelpOptional(HelpTestCase): class TestHelpVersionOptional(HelpTestCase): """Test that the --version argument can be suppressed help messages""" - parser_signature = Sig(prog='PROG', version='1.0') + parser_signature = Sig(prog='PROG') argument_signatures = [ + Sig('-v', '--version', action='version', version='1.0'), Sig('--foo', help='foo help'), Sig('spam', help='spam help'), ] @@ -3953,8 +3956,8 @@ class TestHelpVersionAction(HelpTestCase): class TestHelpSubparsersOrdering(HelpTestCase): """Test ordering of subcommands in help matches the code""" parser_signature = Sig(prog='PROG', - description='display some subcommands', - version='0.1') + description='display some subcommands') + argument_signatures = [Sig('-v', '--version', action='version', version='0.1')] subparsers_signatures = [Sig(name=name) for name in ('a', 'b', 'c', 'd', 'e')] @@ -3982,8 +3985,8 @@ class TestHelpSubparsersOrdering(HelpTestCase): class TestHelpSubparsersWithHelpOrdering(HelpTestCase): """Test ordering of subcommands in help matches the code""" parser_signature = Sig(prog='PROG', - description='display some subcommands', - version='0.1') + description='display some subcommands') + argument_signatures = [Sig('-v', '--version', action='version', version='0.1')] subcommand_data = (('a', 'a subcommand help'), ('b', 'b subcommand help'), @@ -4280,32 +4283,28 @@ class TestOptionalsHelpVersionActions(TestCase): parser.format_help(), self._get_error(parser.parse_args, args_str.split()).stdout) - def assertPrintVersionExit(self, parser, args_str): - self.assertEqual( - parser.format_version(), - self._get_error(parser.parse_args, args_str.split()).stderr) - def assertArgumentParserError(self, parser, *args): self.assertRaises(ArgumentParserError, parser.parse_args, args) def test_version(self): - parser = ErrorRaisingArgumentParser(version='1.0') + parser = ErrorRaisingArgumentParser() + parser.add_argument('-v', '--version', action='version', version='1.0') self.assertPrintHelpExit(parser, '-h') self.assertPrintHelpExit(parser, '--help') - self.assertPrintVersionExit(parser, '-v') - self.assertPrintVersionExit(parser, '--version') + self.assertRaises(AttributeError, getattr, parser, 'format_version') def test_version_format(self): - parser = ErrorRaisingArgumentParser(prog='PPP', version='%(prog)s 3.5') + parser = ErrorRaisingArgumentParser(prog='PPP') + parser.add_argument('-v', '--version', action='version', version='%(prog)s 3.5') msg = self._get_error(parser.parse_args, ['-v']).stderr self.assertEqual('PPP 3.5\n', msg) def test_version_no_help(self): - parser = ErrorRaisingArgumentParser(add_help=False, version='1.0') + parser = ErrorRaisingArgumentParser(add_help=False) + parser.add_argument('-v', '--version', action='version', version='1.0') self.assertArgumentParserError(parser, '-h') self.assertArgumentParserError(parser, '--help') - self.assertPrintVersionExit(parser, '-v') - self.assertPrintVersionExit(parser, '--version') + self.assertRaises(AttributeError, getattr, parser, 'format_version') def test_version_action(self): parser = ErrorRaisingArgumentParser(prog='XXX') @@ -4325,12 +4324,13 @@ class TestOptionalsHelpVersionActions(TestCase): parser.add_argument('-x', action='help') parser.add_argument('-y', action='version') self.assertPrintHelpExit(parser, '-x') - self.assertPrintVersionExit(parser, '-y') self.assertArgumentParserError(parser, '-v') self.assertArgumentParserError(parser, '--version') + self.assertRaises(AttributeError, getattr, parser, 'format_version') def test_help_version_extra_arguments(self): - parser = ErrorRaisingArgumentParser(version='1.0') + parser = ErrorRaisingArgumentParser() + parser.add_argument('--version', action='version', version='1.0') parser.add_argument('-x', action='store_true') parser.add_argument('y') @@ -4342,8 +4342,7 @@ class TestOptionalsHelpVersionActions(TestCase): format = '%s %%s %s' % (prefix, suffix) self.assertPrintHelpExit(parser, format % '-h') self.assertPrintHelpExit(parser, format % '--help') - self.assertPrintVersionExit(parser, format % '-v') - self.assertPrintVersionExit(parser, format % '--version') + self.assertRaises(AttributeError, getattr, parser, 'format_version') # ====================== @@ -4398,7 +4397,7 @@ class TestStrings(TestCase): parser = argparse.ArgumentParser(prog='PROG') string = ( "ArgumentParser(prog='PROG', usage=None, description=None, " - "version=None, formatter_class=%r, conflict_handler='error', " + "formatter_class=%r, conflict_handler='error', " "add_help=True)" % argparse.HelpFormatter) self.assertStringEqual(parser, string) @@ -4760,13 +4759,7 @@ class TestImportStar(TestCase): self.assertEqual(sorted(items), sorted(argparse.__all__)) def test_main(): - # silence warnings about version argument - these are expected - with support.check_warnings( - ('The "version" argument to ArgumentParser is deprecated.', - DeprecationWarning), - ('The (format|print)_version method is deprecated', - DeprecationWarning)): - support.run_unittest(__name__) + support.run_unittest(__name__) # Remove global references to avoid looking like we have refleaks. RFile.seen = {} WFile.seen = set() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 54ba179..ed8564c 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1255,9 +1255,8 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests): self.assertRaises(IOError, bufio.tell) self.assertRaises(IOError, bufio.write, b"abcdef") - def test_max_buffer_size_deprecation(self): - with support.check_warnings(("max_buffer_size is deprecated", - DeprecationWarning)): + def test_max_buffer_size_removal(self): + with self.assertRaises(TypeError): self.tp(self.MockRawIO(), 8, 12) @@ -1313,9 +1312,8 @@ class BufferedRWPairTest(unittest.TestCase): pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertRaises(self.UnsupportedOperation, pair.detach) - def test_constructor_max_buffer_size_deprecation(self): - with support.check_warnings(("max_buffer_size is deprecated", - DeprecationWarning)): + def test_constructor_max_buffer_size_removal(self): + with self.assertRaises(TypeError): self.tp(self.MockRawIO(), self.MockRawIO(), 8, 12) def test_constructor_with_not_readable(self): diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 417c986..5aaf736 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -415,6 +415,93 @@ class FactoryFunctionErrors(ErrorReporting): self.assertFactoryError(ipaddress.ip_network, "network") +class ComparisonTests(unittest.TestCase): + + v4addr = ipaddress.IPv4Address(1) + v4net = ipaddress.IPv4Network(1) + v4intf = ipaddress.IPv4Interface(1) + v6addr = ipaddress.IPv6Address(1) + v6net = ipaddress.IPv6Network(1) + v6intf = ipaddress.IPv6Interface(1) + + v4_addresses = [v4addr, v4intf] + v4_objects = v4_addresses + [v4net] + v6_addresses = [v6addr, v6intf] + v6_objects = v6_addresses + [v6net] + objects = v4_objects + v6_objects + + def test_foreign_type_equality(self): + # __eq__ should never raise TypeError directly + other = object() + for obj in self.objects: + self.assertNotEqual(obj, other) + self.assertFalse(obj == other) + self.assertEqual(obj.__eq__(other), NotImplemented) + self.assertEqual(obj.__ne__(other), NotImplemented) + + def test_mixed_type_equality(self): + # Ensure none of the internal objects accidentally + # expose the right set of attributes to become "equal" + for lhs in self.objects: + for rhs in self.objects: + if lhs is rhs: + continue + self.assertNotEqual(lhs, rhs) + + def test_containment(self): + for obj in self.v4_addresses: + self.assertIn(obj, self.v4net) + for obj in self.v6_addresses: + self.assertIn(obj, self.v6net) + for obj in self.v4_objects + [self.v6net]: + self.assertNotIn(obj, self.v6net) + for obj in self.v6_objects + [self.v4net]: + self.assertNotIn(obj, self.v4net) + + def test_mixed_type_ordering(self): + for lhs in self.objects: + for rhs in self.objects: + if isinstance(lhs, type(rhs)) or isinstance(rhs, type(lhs)): + continue + self.assertRaises(TypeError, lambda: lhs < rhs) + self.assertRaises(TypeError, lambda: lhs > rhs) + self.assertRaises(TypeError, lambda: lhs <= rhs) + self.assertRaises(TypeError, lambda: lhs >= rhs) + + def test_mixed_type_key(self): + # with get_mixed_type_key, you can sort addresses and network. + v4_ordered = [self.v4addr, self.v4net, self.v4intf] + v6_ordered = [self.v6addr, self.v6net, self.v6intf] + self.assertEqual(v4_ordered, + sorted(self.v4_objects, + key=ipaddress.get_mixed_type_key)) + self.assertEqual(v6_ordered, + sorted(self.v6_objects, + key=ipaddress.get_mixed_type_key)) + self.assertEqual(v4_ordered + v6_ordered, + sorted(self.objects, + key=ipaddress.get_mixed_type_key)) + self.assertEqual(NotImplemented, ipaddress.get_mixed_type_key(object)) + + def test_incompatible_versions(self): + # These should always raise TypeError + v4addr = ipaddress.ip_address('1.1.1.1') + v4net = ipaddress.ip_network('1.1.1.1') + v6addr = ipaddress.ip_address('::1') + v6net = ipaddress.ip_address('::1') + + self.assertRaises(TypeError, v4addr.__lt__, v6addr) + self.assertRaises(TypeError, v4addr.__gt__, v6addr) + self.assertRaises(TypeError, v4net.__lt__, v6net) + self.assertRaises(TypeError, v4net.__gt__, v6net) + + self.assertRaises(TypeError, v6addr.__lt__, v4addr) + self.assertRaises(TypeError, v6addr.__gt__, v4addr) + self.assertRaises(TypeError, v6net.__lt__, v4net) + self.assertRaises(TypeError, v6net.__gt__, v4net) + + + class IpaddrUnitTest(unittest.TestCase): def setUp(self): @@ -495,67 +582,6 @@ class IpaddrUnitTest(unittest.TestCase): self.assertEqual(str(self.ipv6_network.hostmask), '::ffff:ffff:ffff:ffff') - def testEqualityChecks(self): - # __eq__ should never raise TypeError directly - other = object() - def assertEqualityNotImplemented(instance): - self.assertEqual(instance.__eq__(other), NotImplemented) - self.assertEqual(instance.__ne__(other), NotImplemented) - self.assertFalse(instance == other) - self.assertTrue(instance != other) - - assertEqualityNotImplemented(self.ipv4_address) - assertEqualityNotImplemented(self.ipv4_network) - assertEqualityNotImplemented(self.ipv4_interface) - assertEqualityNotImplemented(self.ipv6_address) - assertEqualityNotImplemented(self.ipv6_network) - assertEqualityNotImplemented(self.ipv6_interface) - - def testBadVersionComparison(self): - # These should always raise TypeError - v4addr = ipaddress.ip_address('1.1.1.1') - v4net = ipaddress.ip_network('1.1.1.1') - v6addr = ipaddress.ip_address('::1') - v6net = ipaddress.ip_address('::1') - - self.assertRaises(TypeError, v4addr.__lt__, v6addr) - self.assertRaises(TypeError, v4addr.__gt__, v6addr) - self.assertRaises(TypeError, v4net.__lt__, v6net) - self.assertRaises(TypeError, v4net.__gt__, v6net) - - self.assertRaises(TypeError, v6addr.__lt__, v4addr) - self.assertRaises(TypeError, v6addr.__gt__, v4addr) - self.assertRaises(TypeError, v6net.__lt__, v4net) - self.assertRaises(TypeError, v6net.__gt__, v4net) - - def testMixedTypeComparison(self): - v4addr = ipaddress.ip_address('1.1.1.1') - v4net = ipaddress.ip_network('1.1.1.1/32') - v6addr = ipaddress.ip_address('::1') - v6net = ipaddress.ip_network('::1/128') - - self.assertFalse(v4net.__contains__(v6net)) - self.assertFalse(v6net.__contains__(v4net)) - - self.assertRaises(TypeError, lambda: v4addr < v4net) - self.assertRaises(TypeError, lambda: v4addr > v4net) - self.assertRaises(TypeError, lambda: v4net < v4addr) - self.assertRaises(TypeError, lambda: v4net > v4addr) - - self.assertRaises(TypeError, lambda: v6addr < v6net) - self.assertRaises(TypeError, lambda: v6addr > v6net) - self.assertRaises(TypeError, lambda: v6net < v6addr) - self.assertRaises(TypeError, lambda: v6net > v6addr) - - # with get_mixed_type_key, you can sort addresses and network. - self.assertEqual([v4addr, v4net], - sorted([v4net, v4addr], - key=ipaddress.get_mixed_type_key)) - self.assertEqual([v6addr, v6net], - sorted([v6net, v6addr], - key=ipaddress.get_mixed_type_key)) - self.assertEqual(NotImplemented, ipaddress.get_mixed_type_key(object)) - def testIpFromInt(self): self.assertEqual(self.ipv4_interface._ip, ipaddress.IPv4Interface(16909060)._ip) @@ -1049,6 +1075,16 @@ class IpaddrUnitTest(unittest.TestCase): self.assertTrue(ipaddress.ip_address('::1') <= ipaddress.ip_address('::2')) + def testInterfaceComparison(self): + self.assertTrue(ipaddress.ip_interface('1.1.1.1') <= + ipaddress.ip_interface('1.1.1.1')) + self.assertTrue(ipaddress.ip_interface('1.1.1.1') <= + ipaddress.ip_interface('1.1.1.2')) + self.assertTrue(ipaddress.ip_interface('::1') <= + ipaddress.ip_interface('::1')) + self.assertTrue(ipaddress.ip_interface('::1') <= + ipaddress.ip_interface('::2')) + def testNetworkComparison(self): # ip1 and ip2 have the same network address ip1 = ipaddress.IPv4Network('1.1.1.0/24') diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index afd8c51..16f85c5 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -154,6 +154,22 @@ class XMLRPCTestCase(unittest.TestCase): self.assertRaises(OverflowError, m.dump_int, xmlrpclib.MININT-1, dummy_write) + def test_dump_double(self): + xmlrpclib.dumps((float(2 ** 34),)) + xmlrpclib.dumps((float(xmlrpclib.MAXINT), + float(xmlrpclib.MININT))) + xmlrpclib.dumps((float(xmlrpclib.MAXINT + 42), + float(xmlrpclib.MININT - 42))) + + def dummy_write(s): + pass + + m = xmlrpclib.Marshaller() + m.dump_double(xmlrpclib.MAXINT, dummy_write) + m.dump_double(xmlrpclib.MININT, dummy_write) + m.dump_double(xmlrpclib.MAXINT + 42, dummy_write) + m.dump_double(xmlrpclib.MININT - 42, dummy_write) + def test_dump_none(self): value = alist + [None] arg1 = (alist + [None],) diff --git a/Lib/trace.py b/Lib/trace.py index 41c2f5f..317b5fd 100644 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -48,19 +48,16 @@ Sample use, programmatically r.write_results(show_missing=True, coverdir="/tmp") """ __all__ = ['Trace', 'CoverageResults'] -import io import linecache import os import re import sys -import time import token import tokenize import inspect import gc import dis import pickle -from warnings import warn as _warn try: from time import monotonic as _time except ImportError: @@ -23,6 +23,14 @@ Core and Builtins Library ------- +- Issue #13248: Remove obsolete argument "max_buffer_size" of BufferedWriter + and BufferedRWPair, from the io module. + +- Issue #13248: Remove obsolete argument "version" of argparse.ArgumentParser. + +- Issue #14814: implement more consistent ordering and sorting behaviour + for ipaddress objects + - Issue #14814: ipaddress network objects correctly return NotImplemented when compared to arbitrary objects instead of raising TypeError diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 21393a3..f717817 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1759,15 +1759,6 @@ PyTypeObject PyBufferedReader_Type = { -static int -complain_about_max_buffer_size(void) -{ - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "max_buffer_size is deprecated", 1) < 0) - return 0; - return 1; -} - /* * class BufferedWriter */ @@ -1776,7 +1767,7 @@ PyDoc_STRVAR(bufferedwriter_doc, "\n" "The constructor creates a BufferedWriter for the given writeable raw\n" "stream. If the buffer_size is not given, it defaults to\n" - "DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n" + "DEFAULT_BUFFER_SIZE.\n" ); static void @@ -1789,23 +1780,18 @@ _bufferedwriter_reset_buf(buffered *self) static int bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds) { - /* TODO: properly deprecate max_buffer_size */ - char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL}; + char *kwlist[] = {"raw", "buffer_size", NULL}; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - Py_ssize_t max_buffer_size = -234; PyObject *raw; self->ok = 0; self->detached = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist, - &raw, &buffer_size, &max_buffer_size)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist, + &raw, &buffer_size)) { return -1; } - if (max_buffer_size != -234 && !complain_about_max_buffer_size()) - return -1; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) return -1; @@ -2186,16 +2172,12 @@ bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds) { PyObject *reader, *writer; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - Py_ssize_t max_buffer_size = -234; - if (!PyArg_ParseTuple(args, "OO|nn:BufferedRWPair", &reader, &writer, - &buffer_size, &max_buffer_size)) { + if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer, + &buffer_size)) { return -1; } - if (max_buffer_size != -234 && !complain_about_max_buffer_size()) - return -1; - if (_PyIOBase_check_readable(reader, Py_True) == NULL) return -1; if (_PyIOBase_check_writable(writer, Py_True) == NULL) @@ -2420,28 +2402,24 @@ PyDoc_STRVAR(bufferedrandom_doc, "\n" "The constructor creates a reader and writer for a seekable stream,\n" "raw, given in the first argument. If the buffer_size is omitted it\n" - "defaults to DEFAULT_BUFFER_SIZE. max_buffer_size isn't used anymore.\n" + "defaults to DEFAULT_BUFFER_SIZE.\n" ); static int bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds) { - char *kwlist[] = {"raw", "buffer_size", "max_buffer_size", NULL}; + char *kwlist[] = {"raw", "buffer_size", NULL}; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - Py_ssize_t max_buffer_size = -234; PyObject *raw; self->ok = 0; self->detached = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|nn:BufferedReader", kwlist, - &raw, &buffer_size, &max_buffer_size)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist, + &raw, &buffer_size)) { return -1; } - if (max_buffer_size != -234 && !complain_about_max_buffer_size()) - return -1; - if (_PyIOBase_check_seekable(raw, Py_True) == NULL) return -1; if (_PyIOBase_check_readable(raw, Py_True) == NULL) diff --git a/Tools/ccbench/ccbench.py b/Tools/ccbench/ccbench.py index c705521..60cec3e 100644 --- a/Tools/ccbench/ccbench.py +++ b/Tools/ccbench/ccbench.py @@ -10,7 +10,6 @@ ccbench, a Python concurrency benchmark. import time import os import sys -import functools import itertools import threading import subprocess diff --git a/Tools/demo/life.py b/Tools/demo/life.py index dfb9ab8..fc4cb49 100755 --- a/Tools/demo/life.py +++ b/Tools/demo/life.py @@ -46,38 +46,38 @@ class LifeBoard: self.state = {} self.scr = scr Y, X = self.scr.getmaxyx() - self.X, self.Y = X-2, Y-2-1 + self.X, self.Y = X - 2, Y - 2 - 1 self.char = char self.scr.clear() # Draw a border around the board - border_line = '+'+(self.X*'-')+'+' + border_line = '+' + (self.X * '-') + '+' self.scr.addstr(0, 0, border_line) - self.scr.addstr(self.Y+1, 0, border_line) + self.scr.addstr(self.Y + 1, 0, border_line) for y in range(0, self.Y): - self.scr.addstr(1+y, 0, '|') - self.scr.addstr(1+y, self.X+1, '|') + self.scr.addstr(1 + y, 0, '|') + self.scr.addstr(1 + y, self.X + 1, '|') self.scr.refresh() def set(self, y, x): """Set a cell to the live state""" - if x<0 or self.X<=x or y<0 or self.Y<=y: - raise ValueError("Coordinates out of range %i,%i"% (y, x)) - self.state[x,y] = 1 + if x < 0 or self.X <= x or y < 0 or self.Y <= y: + raise ValueError("Coordinates out of range %i,%i" % (y, x)) + self.state[x, y] = 1 def toggle(self, y, x): """Toggle a cell's state between live and dead""" if x < 0 or self.X <= x or y < 0 or self.Y <= y: - raise ValueError("Coordinates out of range %i,%i"% (y, x)) + raise ValueError("Coordinates out of range %i,%i" % (y, x)) if (x, y) in self.state: del self.state[x, y] - self.scr.addch(y+1, x+1, ' ') + self.scr.addch(y + 1, x + 1, ' ') else: self.state[x, y] = 1 if curses.has_colors(): # Let's pick a random color! self.scr.attrset(curses.color_pair(random.randrange(1, 7))) - self.scr.addch(y+1, x+1, self.char) + self.scr.addch(y + 1, x + 1, self.char) self.scr.attrset(0) self.scr.refresh() @@ -88,43 +88,46 @@ class LifeBoard: def display(self, update_board=True): """Display the whole board, optionally computing one generation""" - M,N = self.X, self.Y + M, N = self.X, self.Y if not update_board: for i in range(0, M): for j in range(0, N): - if (i,j) in self.state: - self.scr.addch(j+1, i+1, self.char) + if (i, j) in self.state: + self.scr.addch(j + 1, i + 1, self.char) else: - self.scr.addch(j+1, i+1, ' ') + self.scr.addch(j + 1, i + 1, ' ') self.scr.refresh() return d = {} self.boring = 1 for i in range(0, M): - L = range( max(0, i-1), min(M, i+2) ) + L = range(max(0, i - 1), min(M, i + 2)) for j in range(0, N): s = 0 - live = (i,j) in self.state - for k in range( max(0, j-1), min(N, j+2) ): + live = (i, j) in self.state + for k in range(max(0, j - 1), min(N, j + 2)): for l in L: - if (l,k) in self.state: + if (l, k) in self.state: s += 1 s -= live if s == 3: # Birth - d[i,j] = 1 + d[i, j] = 1 if curses.has_colors(): # Let's pick a random color! self.scr.attrset(curses.color_pair( random.randrange(1, 7))) - self.scr.addch(j+1, i+1, self.char) + self.scr.addch(j + 1, i + 1, self.char) self.scr.attrset(0) - if not live: self.boring = 0 - elif s == 2 and live: d[i,j] = 1 # Survival + if not live: + self.boring = 0 + elif s == 2 and live: + # Survival + d[i, j] = 1 elif live: # Death - self.scr.addch(j+1, i+1, ' ') + self.scr.addch(j + 1, i + 1, ' ') self.boring = 0 self.state = d self.scr.refresh() @@ -135,16 +138,17 @@ class LifeBoard: for i in range(0, self.X): for j in range(0, self.Y): if random.random() > 0.5: - self.set(j,i) + self.set(j, i) def erase_menu(stdscr, menu_y): "Clear the space where the menu resides" stdscr.move(menu_y, 0) stdscr.clrtoeol() - stdscr.move(menu_y+1, 0) + stdscr.move(menu_y + 1, 0) stdscr.clrtoeol() + def display_menu(stdscr, menu_y): "Display the menu of possible keystroke commands" erase_menu(stdscr, menu_y) @@ -154,15 +158,16 @@ def display_menu(stdscr, menu_y): stdscr.attrset(curses.color_pair(1)) stdscr.addstr(menu_y, 4, 'Use the cursor keys to move, and space or Enter to toggle a cell.') - stdscr.addstr(menu_y+1, 4, + stdscr.addstr(menu_y + 1, 4, 'E)rase the board, R)andom fill, S)tep once or C)ontinuously, Q)uit') stdscr.attrset(0) + def keyloop(stdscr): # Clear the screen and display the menu of keys stdscr.clear() stdscr_y, stdscr_x = stdscr.getmaxyx() - menu_y = (stdscr_y-3)-1 + menu_y = (stdscr_y - 3) - 1 display_menu(stdscr, menu_y) # If color, then initialize the color pairs @@ -179,16 +184,16 @@ def keyloop(stdscr): curses.mousemask(curses.BUTTON1_CLICKED) # Allocate a subwindow for the Life board and create the board object - subwin = stdscr.subwin(stdscr_y-3, stdscr_x, 0, 0) + subwin = stdscr.subwin(stdscr_y - 3, stdscr_x, 0, 0) board = LifeBoard(subwin, char=ord('*')) board.display(update_board=False) # xpos, ypos are the cursor's position - xpos, ypos = board.X//2, board.Y//2 + xpos, ypos = board.X // 2, board.Y // 2 # Main loop: while True: - stdscr.move(1+ypos, 1+xpos) # Move the cursor + stdscr.move(1 + ypos, 1 + xpos) # Move the cursor c = stdscr.getch() # Get a keystroke if 0 < c < 256: c = chr(c) @@ -224,15 +229,21 @@ def keyloop(stdscr): board.display(update_board=False) elif c in 'Ss': board.display() - else: pass # Ignore incorrect keys - elif c == curses.KEY_UP and ypos > 0: ypos -= 1 - elif c == curses.KEY_DOWN and ypos < board.Y-1: ypos += 1 - elif c == curses.KEY_LEFT and xpos > 0: xpos -= 1 - elif c == curses.KEY_RIGHT and xpos < board.X-1: xpos += 1 + else: + # Ignore incorrect keys + pass + elif c == curses.KEY_UP and ypos > 0: + ypos -= 1 + elif c == curses.KEY_DOWN and ypos + 1 < board.Y: + ypos += 1 + elif c == curses.KEY_LEFT and xpos > 0: + xpos -= 1 + elif c == curses.KEY_RIGHT and xpos + 1 < board.X: + xpos += 1 elif c == curses.KEY_MOUSE: mouse_id, mouse_x, mouse_y, mouse_z, button_state = curses.getmouse() - if (mouse_x > 0 and mouse_x < board.X+1 and - mouse_y > 0 and mouse_y < board.Y+1): + if (mouse_x > 0 and mouse_x < board.X + 1 and + mouse_y > 0 and mouse_y < board.Y + 1): xpos = mouse_x - 1 ypos = mouse_y - 1 board.toggle(ypos, xpos) @@ -245,7 +256,7 @@ def keyloop(stdscr): def main(stdscr): - keyloop(stdscr) # Enter the main loop + keyloop(stdscr) # Enter the main loop if __name__ == '__main__': curses.wrapper(main) diff --git a/Tools/demo/ss1.py b/Tools/demo/ss1.py index 4cea667..71c9be8 100755 --- a/Tools/demo/ss1.py +++ b/Tools/demo/ss1.py @@ -812,7 +812,6 @@ class SheetGUI: def test_basic(): "Basic non-gui self-test." - import os a = Sheet() for x in range(1, 11): for y in range(1, 11): diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 67a960f..93b2b79 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -163,7 +163,6 @@ import time import getopt import token import tokenize -import operator __version__ = '1.5' diff --git a/Tools/iobench/iobench.py b/Tools/iobench/iobench.py index 408be7b..530bc79 100644 --- a/Tools/iobench/iobench.py +++ b/Tools/iobench/iobench.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # This file should be kept compatible with both Python 2.6 and Python >= 3.0. -import functools -import hashlib import itertools import os import platform diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 9ae5b46..b55e2c6 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -1,6 +1,5 @@ "Usage: unparse.py <path to source file>" import sys -import math import ast import tokenize import io diff --git a/Tools/pybench/pybench.py b/Tools/pybench/pybench.py index cac2ddf..942f56d 100755 --- a/Tools/pybench/pybench.py +++ b/Tools/pybench/pybench.py @@ -35,7 +35,9 @@ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE ! """ -import sys, time, operator, platform +import sys +import time +import platform from CommandLine import * try: @@ -963,8 +965,6 @@ python pybench.py -s p25.pybench -c p21.pybench pickle.dump(bench,f) f.close() except IOError as reason: - print('* Error opening/writing reportfile') - except IOError as reason: print('* Error opening/writing reportfile %s: %s' % ( reportfile, reason)) diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index db0f8ec..d83cf63 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -32,7 +32,6 @@ import sys import zipfile from textwrap import dedent -from operator import itemgetter SCRIPT = sys.argv[0] VERSION = "3.2" |