From 11bfd32881e9d57072d3ffee253f5c34535d5042 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Tue, 30 Jul 2013 14:42:40 -0400 Subject: #18584: s/testcleanup/testsetup/ until we switch to Sphinx 1.1. testcleanup directive is new as of 1.1, and we are currently running 1.0.7. But using testsetup works just as well, and avoids the unknown directive error when building the docs. --- Doc/library/email.iterators.rst | 2 +- Doc/library/email.policy.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/email.iterators.rst b/Doc/library/email.iterators.rst index 6c7200f..7882718 100644 --- a/Doc/library/email.iterators.rst +++ b/Doc/library/email.iterators.rst @@ -68,7 +68,7 @@ The following function has been added as a useful debugging tool. It should text/plain text/plain - .. testcleanup:: + .. testsetup:: >>> somefile.close() diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst index d85054a..54ebb1c 100644 --- a/Doc/library/email.policy.rst +++ b/Doc/library/email.policy.rst @@ -85,7 +85,7 @@ file on disk and pass it to the system ``sendmail`` program on a Unix system: >>> p.stdin.close() >>> rc = p.wait() -.. testcleanup:: +.. testsetup:: >>> mymsg.close() >>> mocker.stop() -- cgit v0.12 From 90262625075cdfc32e77340f907d3a47ab6b47f1 Mon Sep 17 00:00:00 2001 From: Ethan Furman Date: Tue, 30 Jul 2013 12:24:25 -0700 Subject: fixed examples to work with changed attribute names --- Doc/library/enum.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 1e464d7..6864705 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -483,7 +483,7 @@ Avoids having to specify the value for each enumeration member:: ... def __new__(cls): ... value = len(cls.__members__) + 1 ... obj = object.__new__(cls) - ... obj._value = value + ... obj._value_ = value ... return obj ... >>> class Color(AutoNumber): @@ -505,19 +505,19 @@ enumerations):: >>> class OrderedEnum(Enum): ... def __ge__(self, other): ... if self.__class__ is other.__class__: - ... return self._value >= other._value + ... return self.value >= other.value ... return NotImplemented ... def __gt__(self, other): ... if self.__class__ is other.__class__: - ... return self._value > other._value + ... return self.value > other.value ... return NotImplemented ... def __le__(self, other): ... if self.__class__ is other.__class__: - ... return self._value <= other._value + ... return self.value <= other.value ... return NotImplemented ... def __lt__(self, other): ... if self.__class__ is other.__class__: - ... return self._value < other._value + ... return self.value < other.value ... return NotImplemented ... >>> class Grade(OrderedEnum): -- cgit v0.12 From 96433f8e34fda64ce607187bda2eca1c2bde0ec3 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Tue, 30 Jul 2013 15:37:11 -0400 Subject: #18601: fix error made when difflib example was converted to use 'with'. --- Doc/library/difflib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index 836e240..ad1466e 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -752,7 +752,7 @@ It is also contained in the Python source distribution, as # we're passing these as arguments to the diff function fromdate = time.ctime(os.stat(fromfile).st_mtime) todate = time.ctime(os.stat(tofile).st_mtime) - with open(fromlines) as fromf, open(tofile) as tof: + with open(fromfile) as fromf, open(tofile) as tof: fromlines, tolines = list(fromf), list(tof) if options.u: -- cgit v0.12 From 1c4e443ea24e34713ae6957c36875cf983824693 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Tue, 30 Jul 2013 15:51:57 -0400 Subject: #16273: Fix tutorial discussion of seek/tell (opaque text-mode values). Patch by Sijin Joseph. --- Doc/tutorial/inputoutput.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 744abab..7daf89b 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -322,9 +322,11 @@ first:: >>> f.write(s) 18 -``f.tell()`` returns an integer giving the file object's current position in the -file, measured in bytes from the beginning of the file. To change the file -object's position, use ``f.seek(offset, from_what)``. The position is computed +``f.tell()`` returns an integer giving the file object's current position in the file +represented as number of bytes from the beginning of the file when in `binary mode` and +an opaque number when in `text mode`. + +To change the file object's position, use ``f.seek(offset, from_what)``. The position is computed from adding *offset* to a reference point; the reference point is selected by the *from_what* argument. A *from_what* value of 0 measures from the beginning of the file, 1 uses the current file position, and 2 uses the end of the file as @@ -345,7 +347,10 @@ beginning of the file as the reference point. :: In text files (those opened without a ``b`` in the mode string), only seeks relative to the beginning of the file are allowed (the exception being seeking -to the very file end with ``seek(0, 2)``). +to the very file end with ``seek(0, 2)``) and the only valid *offset* values are +those returned from the ``f.tell()``, or zero. Any other *offset* value produces +undefined behaviour. + When you're done with a file, call ``f.close()`` to close it and free up any system resources taken up by the open file. After calling ``f.close()``, -- cgit v0.12 From cdc75d967b777db0e4658bb6d500d4fcfca5fecb Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Tue, 30 Jul 2013 14:30:15 -0700 Subject: Issue #15494: Install new test/support directory. --- Makefile.pre.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index 0009802..73988b2 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1012,7 +1012,7 @@ LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ tkinter/test/test_ttk site-packages test \ test/capath test/data \ test/cjkencodings test/decimaltestdata test/xmltestdata \ - test/subprocessdata test/sndhdrdata \ + test/subprocessdata test/sndhdrdata test/support \ test/tracedmodules test/encoded_modules \ test/namespace_pkgs \ test/namespace_pkgs/both_portions \ -- cgit v0.12 From 49e52f9375c23d88023344a6fd441fd2a4124dc6 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 31 Jul 2013 00:55:18 +0200 Subject: Issue #18481: Add C coverage reporting with gcov and lcov. A new make target "coverage-report" creates an instrumented Python build, runs unit tests and creates a HTML. The report can be updated with "make coverage-lcov". --- .hgignore | 5 +++++ Makefile.pre.in | 47 ++++++++++++++++++++++++++++++++++++++++++++++- Misc/NEWS | 4 ++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/.hgignore b/.hgignore index 2c0ed63..73e1e56 100644 --- a/.hgignore +++ b/.hgignore @@ -36,6 +36,7 @@ Modules/Setup.local Modules/config.c Modules/ld_so_aix$ Parser/pgen$ +^lcov-report/ ^core ^python-gdb.py ^python.exe-gdb.py @@ -91,3 +92,7 @@ Modules/_testembed .coverage coverage/ htmlcov/ +*.gcda +*.gcno +*.gcov +coverage.info diff --git a/Makefile.pre.in b/Makefile.pre.in index bef7a25..ad4eb30 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -211,6 +211,12 @@ HOST_GNU_TYPE= @host@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py +# report files for gcov / lcov coverage report +COVERAGE_INFO= $(abs_builddir)/coverage.info +COVERAGE_REPORT=$(abs_builddir)/lcov-report +COVERAGE_REPORT_OPTIONS=--no-branch-coverage --title "CPython lcov report" + + # === Definitions added by makesetup === @@ -463,11 +469,48 @@ run_profile_task: build_all_use_profile: $(MAKE) all CFLAGS="$(CFLAGS) -fprofile-use -fprofile-correction" +# Compile and run with gcov +.PHONY=coverage coverage-lcov coverage-report coverage: @echo "Building with support for coverage checking:" - $(MAKE) clean + $(MAKE) clean profile-removal $(MAKE) all CFLAGS="$(CFLAGS) -O0 -pg -fprofile-arcs -ftest-coverage" LIBS="$(LIBS) -lgcov" +coverage-lcov: + @echo "Creating Coverage HTML report with LCOV:" + @rm -f $(COVERAGE_INFO) + @rm -rf $(COVERAGE_REPORT) + @lcov --capture --directory $(abs_builddir) \ + --base-directory $(realpath $(abs_builddir)) \ + --path $(realpath $(abs_srcdir)) \ + --output-file $(COVERAGE_INFO) + : # remove 3rd party modules and system headers + @lcov --remove $(COVERAGE_INFO) \ + '*/Modules/_ctypes/libffi*/*' \ + '*/Modules/_sha3/keccak/*' \ + '*/Modules/_decimal/libmpdec/*' \ + '*/Modules/expat/*' \ + '*/Modules/zlib/*' \ + '*/Include/*' \ + '/usr/include/*' \ + '/usr/local/include/*' \ + --output-file $(COVERAGE_INFO) + @genhtml $(COVERAGE_INFO) --output-directory $(COVERAGE_REPORT) \ + $(COVERAGE_REPORT_OPTIONS) + @echo + @echo "lcov report at $(COVERAGE_REPORT)/index.html" + @echo + +coverage-report: + : # force rebuilding of parser and importlib + @touch $(GRAMMAR_INPUT) + @touch $(srcdir)/Lib/importlib/_bootstrap.py + : # build with coverage info + $(MAKE) coverage + : # run tests, ignore failures + $(TESTRUNNER) $(TESTOPTS) || true + : # build lcov report + $(MAKE) coverage-lcov # Build the interpreter $(BUILDPYTHON): Modules/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) @@ -1396,6 +1439,8 @@ clean: pycremoval profile-removal: find . -name '*.gc??' -exec rm -f {} ';' + rm -f $(COVERAGE_INFO) + rm -rf $(COVERAGE_REPORT) clobber: clean profile-removal -rm -f $(BUILDPYTHON) $(PGEN) $(LIBRARY) $(LDLIBRARY) $(DLLLIBRARY) \ diff --git a/Misc/NEWS b/Misc/NEWS index c08193d..d44a043 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -725,6 +725,10 @@ IDLE Build ----- +- Issue #18481: Add C coverage reporting with gcov and lcov. A new make target + "coverage-report" creates an instrumented Python build, runs unit tests + and creates a HTML. The report can be updated with "make coverage-lcov". + - Issue #17845: Clarified the message printed when some module are not built. - Issue #18256: Compilation fix for recent AIX releases. Patch by -- cgit v0.12 From 72f455e96cba2ce446aeb1a07aafa0a549a4a90d Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 31 Jul 2013 01:33:50 +0200 Subject: Fix use of uninitialized scalar variable, see 3f994367a979 CID 1058763 --- Modules/_io/iobase.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index a4f2c0e..ae188dd 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -210,8 +210,10 @@ iobase_finalize(PyObject *self) /* If `closed` doesn't exist or can't be evaluated as bool, then the object is probably in an unusable state, so ignore. */ res = PyObject_GetAttr(self, _PyIO_str_closed); - if (res == NULL) + if (res == NULL) { PyErr_Clear(); + closed = -1; + } else { closed = PyObject_IsTrue(res); Py_DECREF(res); -- cgit v0.12 From 4efdb4177efcaf9f0fb577a95ede315a6b1c69c8 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 31 Jul 2013 02:36:43 +0200 Subject: Test Py_IncRef() and Py_DecRef() C functions --- Modules/_testcapimodule.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 6527a53..1ed5687 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2614,6 +2614,16 @@ test_decref_doesnt_leak(PyObject *ob) } static PyObject * +test_incref_decref_API(PyObject *ob) +{ + PyObject *obj = PyLong_FromLong(0); + Py_IncRef(ob); + Py_DecRef(obj); + Py_DecRef(obj); + Py_RETURN_NONE; +} + +static PyObject * test_pymem_alloc0(PyObject *self) { void *ptr; @@ -2781,6 +2791,7 @@ static PyMethodDef TestMethods[] = { {"test_incref_doesnt_leak", (PyCFunction)test_incref_doesnt_leak, METH_NOARGS}, {"test_xdecref_doesnt_leak",(PyCFunction)test_xdecref_doesnt_leak, METH_NOARGS}, {"test_decref_doesnt_leak", (PyCFunction)test_decref_doesnt_leak, METH_NOARGS}, + {"test_incref_decref_API", (PyCFunction)test_incref_decref_API, METH_NOARGS}, {"test_long_and_overflow", (PyCFunction)test_long_and_overflow, METH_NOARGS}, {"test_long_as_double", (PyCFunction)test_long_as_double,METH_NOARGS}, -- cgit v0.12 From 778cba7f29d26d44404bacd926480d8049e454d3 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 30 Jul 2013 22:31:06 -0400 Subject: Issue #18573: More copy-paste fixes to assertWarns entry. --- Doc/library/unittest.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 7671f65..845bf0a 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -897,12 +897,12 @@ Test cases Test that a warning is triggered when *callable* is called with any positional or keyword arguments that are also passed to :meth:`assertWarns`. The test passes if *warning* is triggered and - fails if it isn't. Also, any unexpected exception is an error. + fails if it isn't. Any exception is an error. To catch any of a group of warnings, a tuple containing the warning classes may be passed as *warnings*. If only the *warning* and possibly the *msg* arguments are given, - returns a context manager so that the code under test can be written + return a context manager so that the code under test can be written inline rather than as a function:: with self.assertWarns(SomeWarning): @@ -915,7 +915,7 @@ Test cases :attr:`warning` attribute, and the source line which triggered the warnings in the :attr:`filename` and :attr:`lineno` attributes. This can be useful if the intention is to perform additional checks - on the exception raised:: + on the warning caught:: with self.assertWarns(SomeWarning) as cm: do_something() -- cgit v0.12 From 6ffa5ce1f3daad9dc7beb5b74444f74d5c4a9538 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 31 Jul 2013 11:58:18 +0200 Subject: Fix _sha3 module to actually release the GIL around its update function. gcov is great. --- Modules/_sha3/sha3module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c index 32cd85a..0f47fc3 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -322,7 +322,7 @@ SHA3_update(SHA3object *self, PyObject *args) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); /* add new data, the function takes the length in bits not bytes */ -#ifdef WITH_THREADS +#ifdef WITH_THREAD if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { self->lock = PyThread_allocate_lock(); } -- cgit v0.12 From 0ce642ebca5f4d0e1b6875b845ad0eb8cb76bbb4 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 31 Jul 2013 13:32:40 +0200 Subject: yet another WITH_THREADS typo --- Modules/_sha3/sha3module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c index 0f47fc3..4e6352b 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -464,7 +464,7 @@ SHA3_factory(PyObject *args, PyObject *kwdict, const char *fmt, } if (data_obj) { -#ifdef WITH_THREADS +#ifdef WITH_THREAD if (buf.len >= HASHLIB_GIL_MINSIZE) { /* invariant: New objects can't be accessed by other code yet, * thus it's safe to release the GIL without locking the object. -- cgit v0.12 From c91d5eea106d191e931f953bdbdb1db25e051767 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Wed, 31 Jul 2013 13:46:08 -0400 Subject: #17616: wave.open now supports the 'with' statement. Feature and tests by ClClaudiu.Popa, I added the doc changes. --- Doc/library/aifc.rst | 3 ++- Doc/library/wave.rst | 5 +++++ Doc/whatsnew/3.4.rst | 5 ++++- Lib/test/test_wave.py | 29 +++++++++++++++++++---------- Lib/wave.py | 13 +++++++++++++ Misc/NEWS | 2 ++ 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Doc/library/aifc.rst b/Doc/library/aifc.rst index c1cd215..44a0a24 100644 --- a/Doc/library/aifc.rst +++ b/Doc/library/aifc.rst @@ -51,7 +51,8 @@ Module :mod:`aifc` defines the following function: used for writing, the file object should be seekable, unless you know ahead of time how many samples you are going to write in total and use :meth:`writeframesraw` and :meth:`setnframes`. - Objects returned by :func:`.open` also supports the :keyword:`with` statement. + The :func:`.open` function may be used in a :keyword:`with` statement. When + the :keyword:`with` block completes, the :meth:`~aifc.close` method is called. .. versionchanged:: 3.4 Support for the :keyword:`with` statement was added. diff --git a/Doc/library/wave.rst b/Doc/library/wave.rst index 2e64d00..c52af89 100644 --- a/Doc/library/wave.rst +++ b/Doc/library/wave.rst @@ -39,6 +39,11 @@ The :mod:`wave` module defines the following function and exception: :meth:`close` method is called; it is the caller's responsibility to close the file object. + The :func:`.open` function may be used in a :keyword:`with` statement. When + the :keyword:`with` block completes, the :meth:`Wave_read.close() + ` or :meth:`Wave_write.close() + ` method is called. + .. function:: openfp(file, mode) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index 17cec3f..2575170 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -239,8 +239,11 @@ wave The :meth:`~wave.getparams` method now returns a namedtuple rather than a plain tuple. (Contributed by Claudiu Popa in :issue:`17487`.) +:meth:`wave.open` now supports the context manager protocol. (Contributed +by Claudiu Popa in :issue:`17616`.) + stat ---- +---- The stat module is now backed by a C implementation in :mod:`_stat`. A C implementation is required as most of the values aren't standardized and diff --git a/Lib/test/test_wave.py b/Lib/test/test_wave.py index 581d973..e9ee15c 100644 --- a/Lib/test/test_wave.py +++ b/Lib/test/test_wave.py @@ -1,7 +1,5 @@ -from test.support import TESTFN, run_unittest -import os +from test.support import TESTFN, unlink import wave -import struct import unittest nchannels = 2 @@ -17,10 +15,7 @@ class TestWave(unittest.TestCase): def tearDown(self): if self.f is not None: self.f.close() - try: - os.remove(TESTFN) - except OSError: - pass + unlink(TESTFN) def test_it(self, test_rounding=False): self.f = wave.open(TESTFN, 'wb') @@ -74,9 +69,23 @@ class TestWave(unittest.TestCase): self.assertEqual(params.comptype, self.f.getcomptype()) self.assertEqual(params.compname, self.f.getcompname()) + def test_context_manager(self): + self.f = wave.open(TESTFN, 'wb') + self.f.setnchannels(nchannels) + self.f.setsampwidth(sampwidth) + self.f.setframerate(framerate) + self.f.close() + + with wave.open(TESTFN) as f: + self.assertFalse(f.getfp().closed) + self.assertIs(f.getfp(), None) + + with open(TESTFN, 'wb') as testfile: + with self.assertRaises(wave.Error): + with wave.open(testfile, 'wb'): + pass + self.assertEqual(testfile.closed, False) -def test_main(): - run_unittest(TestWave) if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/wave.py b/Lib/wave.py index ea410c1..695a4be 100644 --- a/Lib/wave.py +++ b/Lib/wave.py @@ -167,6 +167,13 @@ class Wave_read: def __del__(self): self.close() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + # # User visible methods. # @@ -323,6 +330,12 @@ class Wave_write: def __del__(self): self.close() + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + # # User visible methods. # diff --git a/Misc/NEWS b/Misc/NEWS index d44a043..a4aabbe 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -173,6 +173,8 @@ Core and Builtins Library ------- +- Issue #17616: wave.open now supports the context manager protocol. + - Issue #18599: Fix name attribute of _sha1.sha1() object. It now returns 'SHA1' instead of 'SHA'. -- cgit v0.12