Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60568-60598,60600-60616 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r60568 | christian.heimes | 2008-02-04 19:48:38 +0100 (Mon, 04 Feb 2008) | 1 line Increase debugging to investige failing tests on some build bots ........ r60570 | christian.heimes | 2008-02-04 20:30:05 +0100 (Mon, 04 Feb 2008) | 1 line Small adjustments for test compact freelist test. It's no passing on Windows as well. ........ r60573 | amaury.forgeotdarc | 2008-02-04 21:53:14 +0100 (Mon, 04 Feb 2008) | 2 lines Correct quotes in NEWS file ........ r60575 | amaury.forgeotdarc | 2008-02-04 22:45:05 +0100 (Mon, 04 Feb 2008) | 13 lines #1750076: Debugger did not step on every iteration of a while statement. The mapping between bytecode offsets and source lines (lnotab) did not contain an entry for the beginning of the loop. Now it does, and the lnotab can be a bit larger: in particular, several statements on the same line generate several entries. However, this does not bother the settrace function, which will trigger only one 'line' event. The lnotab seems to be exactly the same as with python2.4. ........ r60584 | amaury.forgeotdarc | 2008-02-05 01:26:21 +0100 (Tue, 05 Feb 2008) | 3 lines Change r60575 broke test_compile: there is no need to emit co_lnotab item when both offsets are zeros. ........ r60587 | skip.montanaro | 2008-02-05 03:32:16 +0100 (Tue, 05 Feb 2008) | 1 line sync with most recent version from python-mode sf project ........ r60588 | lars.gustaebel | 2008-02-05 12:51:40 +0100 (Tue, 05 Feb 2008) | 5 lines Issue #2004: Use mode 0700 for temporary directories and default permissions for missing directories. (will backport to 2.5) ........ r60590 | georg.brandl | 2008-02-05 13:01:24 +0100 (Tue, 05 Feb 2008) | 2 lines Convert external links to internal links. Fixes #2010. ........ r60592 | marc-andre.lemburg | 2008-02-05 15:50:40 +0100 (Tue, 05 Feb 2008) | 3 lines Keep distutils Python 2.1 compatible (or even Python 2.4 in this case). ........ r60593 | andrew.kuchling | 2008-02-05 17:06:57 +0100 (Tue, 05 Feb 2008) | 5 lines Update PEP URL. (This code is duplicated between pydoc and DocXMLRPCServer; maybe it should be refactored as a GHOP project.) 2.5.2 backport candidate. ........ r60596 | guido.van.rossum | 2008-02-05 18:32:15 +0100 (Tue, 05 Feb 2008) | 2 lines In the experimental 'Scanner' feature, the group count was set wrong. ........ r60602 | facundo.batista | 2008-02-05 20:03:32 +0100 (Tue, 05 Feb 2008) | 3 lines Issue 1951. Converts wave test cases to unittest. ........ r60603 | georg.brandl | 2008-02-05 20:07:10 +0100 (Tue, 05 Feb 2008) | 2 lines Actually run the test. ........ r60604 | skip.montanaro | 2008-02-05 20:24:30 +0100 (Tue, 05 Feb 2008) | 2 lines correct object name ........ r60605 | georg.brandl | 2008-02-05 20:58:17 +0100 (Tue, 05 Feb 2008) | 7 lines * Use the same code to profile for test_profile and test_cprofile. * Convert both to unittest. * Use the same unit testing code. * Include the expected output in both test files. * Make it possible to regenerate the expected output by running the file as a script with an '-r' argument. ........ r60613 | raymond.hettinger | 2008-02-06 02:49:00 +0100 (Wed, 06 Feb 2008) | 1 line Sync-up with Py3k work. ........ r60614 | christian.heimes | 2008-02-06 13:44:34 +0100 (Wed, 06 Feb 2008) | 1 line Limit free list of method and builtin function objects to 256 entries each. ........ r60616 | christian.heimes | 2008-02-06 14:33:44 +0100 (Wed, 06 Feb 2008) | 7 lines Unified naming convention for free lists and their limits. All free lists in Object/ are named ``free_list``, the counter ``numfree`` and the upper limit is a macro ``PyName_MAXFREELIST`` inside an #ifndef block. The chances should make it easier to adjust Python for platforms with less memory, e.g. mobile phones. ........
This commit is contained in:
parent
8f2d006115
commit
2202f877b1
|
@ -265,7 +265,7 @@ the organizations that use Python.
|
||||||
**What are the restrictions on Python's use?**
|
**What are the restrictions on Python's use?**
|
||||||
|
|
||||||
They're practically nonexistent. Consult the :file:`Misc/COPYRIGHT` file in the
|
They're practically nonexistent. Consult the :file:`Misc/COPYRIGHT` file in the
|
||||||
source distribution, or http://www.python.org/doc/Copyright.html for the full
|
source distribution, or the section :ref:`history-and-license` for the full
|
||||||
language, but it boils down to three conditions.
|
language, but it boils down to three conditions.
|
||||||
|
|
||||||
* You have to leave the copyright notice on the software; if you don't include
|
* You have to leave the copyright notice on the software; if you don't include
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _curses-howto:
|
||||||
|
|
||||||
**********************************
|
**********************************
|
||||||
Curses Programming with Python
|
Curses Programming with Python
|
||||||
**********************************
|
**********************************
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _regex-howto:
|
||||||
|
|
||||||
****************************
|
****************************
|
||||||
Regular Expression HOWTO
|
Regular Expression HOWTO
|
||||||
****************************
|
****************************
|
||||||
|
|
|
@ -276,7 +276,7 @@ Unicode result). The following examples show the differences::
|
||||||
|
|
||||||
Encodings are specified as strings containing the encoding's name. Python
|
Encodings are specified as strings containing the encoding's name. Python
|
||||||
comes with roughly 100 different encodings; see the Python Library Reference at
|
comes with roughly 100 different encodings; see the Python Library Reference at
|
||||||
<http://docs.python.org/lib/standard-encodings.html> for a list. Some encodings
|
:ref:`standard-encodings` for a list. Some encodings
|
||||||
have multiple names; for example, 'latin-1', 'iso_8859_1' and '8859' are all
|
have multiple names; for example, 'latin-1', 'iso_8859_1' and '8859' are all
|
||||||
synonyms for the same encoding.
|
synonyms for the same encoding.
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,9 @@ Linux and the BSD variants of Unix.
|
||||||
Convenience function to ensure proper terminal setup and resetting on
|
Convenience function to ensure proper terminal setup and resetting on
|
||||||
application entry and exit.
|
application entry and exit.
|
||||||
|
|
||||||
`Curses Programming with Python <http://www.python.org/doc/howto/curses/curses.html>`_
|
:ref:`curses-howto`
|
||||||
Tutorial material on using curses with Python, by Andrew Kuchling and Eric
|
Tutorial material on using curses with Python, by Andrew Kuchling and Eric
|
||||||
Raymond, is available on the Python Web site.
|
Raymond.
|
||||||
|
|
||||||
The :file:`Demo/curses/` directory in the Python source distribution contains
|
The :file:`Demo/curses/` directory in the Python source distribution contains
|
||||||
some example programs using the curses bindings provided by this module.
|
some example programs using the curses bindings provided by this module.
|
||||||
|
|
|
@ -65,8 +65,7 @@ and implementation of regular expressions, consult the Friedl book referenced
|
||||||
above, or almost any textbook about compiler construction.
|
above, or almost any textbook about compiler construction.
|
||||||
|
|
||||||
A brief explanation of the format of regular expressions follows. For further
|
A brief explanation of the format of regular expressions follows. For further
|
||||||
information and a gentler presentation, consult the Regular Expression HOWTO,
|
information and a gentler presentation, consult the :ref:`regex-howto`.
|
||||||
accessible from http://www.python.org/doc/howto/.
|
|
||||||
|
|
||||||
Regular expressions can contain both special and ordinary characters. Most
|
Regular expressions can contain both special and ordinary characters. Most
|
||||||
ordinary characters, like ``'A'``, ``'a'``, or ``'0'``, are the simplest regular
|
ordinary characters, like ``'A'``, ``'a'``, or ``'0'``, are the simplest regular
|
||||||
|
|
|
@ -30,7 +30,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc):
|
||||||
results = []
|
results = []
|
||||||
here = 0
|
here = 0
|
||||||
|
|
||||||
# XXX Note that this regular expressions does not allow for the
|
# XXX Note that this regular expression does not allow for the
|
||||||
# hyperlinking of arbitrary strings being used as method
|
# hyperlinking of arbitrary strings being used as method
|
||||||
# names. Only methods with names consisting of word characters
|
# names. Only methods with names consisting of word characters
|
||||||
# and '.'s are hyperlinked.
|
# and '.'s are hyperlinked.
|
||||||
|
@ -52,7 +52,7 @@ class ServerHTMLDoc(pydoc.HTMLDoc):
|
||||||
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
|
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
|
||||||
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
||||||
elif pep:
|
elif pep:
|
||||||
url = 'http://www.python.org/peps/pep-%04d.html' % int(pep)
|
url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
|
||||||
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
||||||
elif text[end:end+1] == '(':
|
elif text[end:end+1] == '(':
|
||||||
results.append(self.namelink(name, methods, funcs, classes))
|
results.append(self.namelink(name, methods, funcs, classes))
|
||||||
|
|
|
@ -385,6 +385,7 @@ class Mapping(metaclass=ABCMeta):
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not (self == other)
|
return not (self == other)
|
||||||
|
|
||||||
|
|
||||||
class MappingView(metaclass=ABCMeta):
|
class MappingView(metaclass=ABCMeta):
|
||||||
|
|
||||||
def __init__(self, mapping):
|
def __init__(self, mapping):
|
||||||
|
|
|
@ -37,8 +37,12 @@ if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower():
|
||||||
# different (hard-wired) directories.
|
# different (hard-wired) directories.
|
||||||
# Setup.local is available for Makefile builds including VPATH builds,
|
# Setup.local is available for Makefile builds including VPATH builds,
|
||||||
# Setup.dist is available on Windows
|
# Setup.dist is available on Windows
|
||||||
python_build = any(os.path.isfile(os.path.join(project_base, "Modules", fn))
|
def _python_build():
|
||||||
for fn in ("Setup.dist", "Setup.local"))
|
for fn in ("Setup.dist", "Setup.local"):
|
||||||
|
if os.path.isfile(os.path.join(project_base, "Modules", fn)):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
python_build = _python_build()
|
||||||
|
|
||||||
def get_python_version():
|
def get_python_version():
|
||||||
"""Return a string containing the major and minor Python version,
|
"""Return a string containing the major and minor Python version,
|
||||||
|
|
|
@ -536,7 +536,7 @@ class HTMLDoc(Doc):
|
||||||
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
|
url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
|
||||||
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
||||||
elif pep:
|
elif pep:
|
||||||
url = 'http://www.python.org/peps/pep-%04d' % int(pep)
|
url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
|
||||||
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
||||||
elif text[end:end+1] == '(':
|
elif text[end:end+1] == '(':
|
||||||
results.append(self.namelink(name, methods, funcs, classes))
|
results.append(self.namelink(name, methods, funcs, classes))
|
||||||
|
|
|
@ -294,8 +294,8 @@ class Scanner:
|
||||||
p.append(sre_parse.SubPattern(s, [
|
p.append(sre_parse.SubPattern(s, [
|
||||||
(SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))),
|
(SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))),
|
||||||
]))
|
]))
|
||||||
|
s.groups = len(p)+1
|
||||||
p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
|
p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
|
||||||
s.groups = len(p)
|
|
||||||
self.scanner = sre_compile.compile(p)
|
self.scanner = sre_compile.compile(p)
|
||||||
def scan(self, string):
|
def scan(self, string):
|
||||||
result = []
|
result = []
|
||||||
|
|
|
@ -2005,15 +2005,11 @@ class TarFile(object):
|
||||||
|
|
||||||
for tarinfo in members:
|
for tarinfo in members:
|
||||||
if tarinfo.isdir():
|
if tarinfo.isdir():
|
||||||
# Extract directory with a safe mode, so that
|
# Extract directories with a safe mode.
|
||||||
# all files below can be extracted as well.
|
|
||||||
try:
|
|
||||||
os.makedirs(os.path.join(path, tarinfo.name), 0o700)
|
|
||||||
except EnvironmentError:
|
|
||||||
pass
|
|
||||||
directories.append(tarinfo)
|
directories.append(tarinfo)
|
||||||
else:
|
tarinfo = copy.copy(tarinfo)
|
||||||
self.extract(tarinfo, path)
|
tarinfo.mode = 0o700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
# Reverse sort directories.
|
# Reverse sort directories.
|
||||||
directories.sort(key=lambda a: a.name)
|
directories.sort(key=lambda a: a.name)
|
||||||
|
@ -2118,6 +2114,8 @@ class TarFile(object):
|
||||||
# Create all upper directories.
|
# Create all upper directories.
|
||||||
upperdirs = os.path.dirname(targetpath)
|
upperdirs = os.path.dirname(targetpath)
|
||||||
if upperdirs and not os.path.exists(upperdirs):
|
if upperdirs and not os.path.exists(upperdirs):
|
||||||
|
# Create directories that are not part of the archive with
|
||||||
|
# default permissions.
|
||||||
os.makedirs(upperdirs)
|
os.makedirs(upperdirs)
|
||||||
|
|
||||||
if tarinfo.islnk() or tarinfo.issym():
|
if tarinfo.islnk() or tarinfo.issym():
|
||||||
|
@ -2154,7 +2152,9 @@ class TarFile(object):
|
||||||
"""Make a directory called targetpath.
|
"""Make a directory called targetpath.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
os.mkdir(targetpath)
|
# Use a safe mode for the directory, the real mode is set
|
||||||
|
# later in _extract_member().
|
||||||
|
os.mkdir(targetpath, 0o700)
|
||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
if e.errno != errno.EEXIST:
|
if e.errno != errno.EEXIST:
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
test_profile
|
|
||||||
125 function calls (105 primitive calls) in 1.000 CPU seconds
|
|
||||||
|
|
||||||
Ordered by: standard name
|
|
||||||
|
|
||||||
ncalls tottime percall cumtime percall filename:lineno(function)
|
|
||||||
4 0.000 0.000 0.000 0.000 :0(append)
|
|
||||||
4 0.000 0.000 0.000 0.000 :0(exc_info)
|
|
||||||
1 0.000 0.000 1.000 1.000 :0(exec)
|
|
||||||
12 0.000 0.000 0.012 0.001 :0(hasattr)
|
|
||||||
1 0.000 0.000 0.000 0.000 :0(setprofile)
|
|
||||||
1 0.000 0.000 1.000 1.000 <string>:1(<module>)
|
|
||||||
2 0.000 0.000 0.000 0.000 io.py:1213(flush)
|
|
||||||
1 0.000 0.000 0.000 0.000 io.py:269(flush)
|
|
||||||
1 0.000 0.000 0.000 0.000 io.py:656(closed)
|
|
||||||
1 0.000 0.000 0.000 0.000 io.py:874(flush)
|
|
||||||
0 0.000 0.000 profile:0(profiler)
|
|
||||||
1 0.000 0.000 1.000 1.000 profile:0(testfunc())
|
|
||||||
8 0.064 0.008 0.080 0.010 test_profile.py:103(subhelper)
|
|
||||||
28 0.028 0.001 0.028 0.001 test_profile.py:115(__getattr__)
|
|
||||||
1 0.270 0.270 1.000 1.000 test_profile.py:30(testfunc)
|
|
||||||
23/3 0.150 0.007 0.170 0.057 test_profile.py:40(factorial)
|
|
||||||
20 0.020 0.001 0.020 0.001 test_profile.py:53(mul)
|
|
||||||
2 0.040 0.020 0.600 0.300 test_profile.py:60(helper)
|
|
||||||
4 0.116 0.029 0.120 0.030 test_profile.py:78(helper1)
|
|
||||||
2 0.000 0.000 0.140 0.070 test_profile.py:89(helper2_indirect)
|
|
||||||
8 0.312 0.039 0.400 0.050 test_profile.py:93(helper2)
|
|
||||||
|
|
||||||
|
|
||||||
Ordered by: standard name
|
|
||||||
|
|
||||||
Function called...
|
|
||||||
:0(append) ->
|
|
||||||
:0(exc_info) ->
|
|
||||||
:0(exec) -> <string>:1(<module>)(1) 1.000
|
|
||||||
io.py:1213(flush)(2) 0.000
|
|
||||||
:0(hasattr) -> test_profile.py:115(__getattr__)(12) 0.028
|
|
||||||
:0(setprofile) ->
|
|
||||||
<string>:1(<module>) -> test_profile.py:30(testfunc)(1) 1.000
|
|
||||||
io.py:1213(flush) -> io.py:269(flush)(1) 0.000
|
|
||||||
io.py:874(flush)(1) 0.000
|
|
||||||
io.py:269(flush) ->
|
|
||||||
io.py:656(closed) ->
|
|
||||||
io.py:874(flush) -> io.py:656(closed)(1) 0.000
|
|
||||||
profile:0(profiler) -> profile:0(testfunc())(1) 1.000
|
|
||||||
profile:0(testfunc()) -> :0(exec)(1) 1.000
|
|
||||||
:0(setprofile)(1) 0.000
|
|
||||||
test_profile.py:103(subhelper) -> test_profile.py:115(__getattr__)(16) 0.028
|
|
||||||
test_profile.py:115(__getattr__) ->
|
|
||||||
test_profile.py:30(testfunc) -> test_profile.py:40(factorial)(1) 0.170
|
|
||||||
test_profile.py:60(helper)(2) 0.600
|
|
||||||
test_profile.py:40(factorial) -> test_profile.py:40(factorial)(20) 0.170
|
|
||||||
test_profile.py:53(mul)(20) 0.020
|
|
||||||
test_profile.py:53(mul) ->
|
|
||||||
test_profile.py:60(helper) -> test_profile.py:78(helper1)(4) 0.120
|
|
||||||
test_profile.py:89(helper2_indirect)(2) 0.140
|
|
||||||
test_profile.py:93(helper2)(6) 0.400
|
|
||||||
test_profile.py:78(helper1) -> :0(append)(4) 0.000
|
|
||||||
:0(exc_info)(4) 0.000
|
|
||||||
:0(hasattr)(4) 0.012
|
|
||||||
test_profile.py:89(helper2_indirect) -> test_profile.py:40(factorial)(2) 0.170
|
|
||||||
test_profile.py:93(helper2)(2) 0.400
|
|
||||||
test_profile.py:93(helper2) -> :0(hasattr)(8) 0.012
|
|
||||||
test_profile.py:103(subhelper)(8) 0.080
|
|
||||||
|
|
||||||
|
|
||||||
Ordered by: standard name
|
|
||||||
|
|
||||||
Function was called by...
|
|
||||||
:0(append) <- test_profile.py:78(helper1)(4) 0.120
|
|
||||||
:0(exc_info) <- test_profile.py:78(helper1)(4) 0.120
|
|
||||||
:0(exec) <- profile:0(testfunc())(1) 1.000
|
|
||||||
:0(hasattr) <- test_profile.py:78(helper1)(4) 0.120
|
|
||||||
test_profile.py:93(helper2)(8) 0.400
|
|
||||||
:0(setprofile) <- profile:0(testfunc())(1) 1.000
|
|
||||||
<string>:1(<module>) <- :0(exec)(1) 1.000
|
|
||||||
io.py:1213(flush) <- :0(exec)(2) 1.000
|
|
||||||
io.py:269(flush) <- io.py:1213(flush)(1) 0.000
|
|
||||||
io.py:656(closed) <- io.py:874(flush)(1) 0.000
|
|
||||||
io.py:874(flush) <- io.py:1213(flush)(1) 0.000
|
|
||||||
profile:0(profiler) <-
|
|
||||||
profile:0(testfunc()) <- profile:0(profiler)(1) 0.000
|
|
||||||
test_profile.py:103(subhelper) <- test_profile.py:93(helper2)(8) 0.400
|
|
||||||
test_profile.py:115(__getattr__) <- :0(hasattr)(12) 0.012
|
|
||||||
test_profile.py:103(subhelper)(16) 0.080
|
|
||||||
test_profile.py:30(testfunc) <- <string>:1(<module>)(1) 1.000
|
|
||||||
test_profile.py:40(factorial) <- test_profile.py:30(testfunc)(1) 1.000
|
|
||||||
test_profile.py:40(factorial)(20) 0.170
|
|
||||||
test_profile.py:89(helper2_indirect)(2) 0.140
|
|
||||||
test_profile.py:53(mul) <- test_profile.py:40(factorial)(20) 0.170
|
|
||||||
test_profile.py:60(helper) <- test_profile.py:30(testfunc)(2) 1.000
|
|
||||||
test_profile.py:78(helper1) <- test_profile.py:60(helper)(4) 0.600
|
|
||||||
test_profile.py:89(helper2_indirect) <- test_profile.py:60(helper)(2) 0.600
|
|
||||||
test_profile.py:93(helper2) <- test_profile.py:60(helper)(6) 0.600
|
|
||||||
test_profile.py:89(helper2_indirect)(2) 0.140
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
"""
|
||||||
|
Input for test_profile.py and test_cprofile.py.
|
||||||
|
|
||||||
|
IMPORTANT: This stuff is touchy. If you modify anything above the
|
||||||
|
test class you'll have to regenerate the stats by running the two
|
||||||
|
test files.
|
||||||
|
|
||||||
|
*ALL* NUMBERS in the expected output are relevant. If you change
|
||||||
|
the formatting of pstats, please don't just regenerate the expected
|
||||||
|
output without checking very carefully that not a single number has
|
||||||
|
changed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# In order to have reproducible time, we simulate a timer in the global
|
||||||
|
# variable 'TICKS', which represents simulated time in milliseconds.
|
||||||
|
# (We can't use a helper function increment the timer since it would be
|
||||||
|
# included in the profile and would appear to consume all the time.)
|
||||||
|
TICKS = 42000
|
||||||
|
|
||||||
|
def timer():
|
||||||
|
return TICKS
|
||||||
|
|
||||||
|
def testfunc():
|
||||||
|
# 1 call
|
||||||
|
# 1000 ticks total: 270 ticks local, 730 ticks in subfunctions
|
||||||
|
global TICKS
|
||||||
|
TICKS += 99
|
||||||
|
helper() # 300
|
||||||
|
helper() # 300
|
||||||
|
TICKS += 171
|
||||||
|
factorial(14) # 130
|
||||||
|
|
||||||
|
def factorial(n):
|
||||||
|
# 23 calls total
|
||||||
|
# 170 ticks total, 150 ticks local
|
||||||
|
# 3 primitive calls, 130, 20 and 20 ticks total
|
||||||
|
# including 116, 17, 17 ticks local
|
||||||
|
global TICKS
|
||||||
|
if n > 0:
|
||||||
|
TICKS += n
|
||||||
|
return mul(n, factorial(n-1))
|
||||||
|
else:
|
||||||
|
TICKS += 11
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def mul(a, b):
|
||||||
|
# 20 calls
|
||||||
|
# 1 tick, local
|
||||||
|
global TICKS
|
||||||
|
TICKS += 1
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
def helper():
|
||||||
|
# 2 calls
|
||||||
|
# 300 ticks total: 20 ticks local, 260 ticks in subfunctions
|
||||||
|
global TICKS
|
||||||
|
TICKS += 1
|
||||||
|
helper1() # 30
|
||||||
|
TICKS += 2
|
||||||
|
helper1() # 30
|
||||||
|
TICKS += 6
|
||||||
|
helper2() # 50
|
||||||
|
TICKS += 3
|
||||||
|
helper2() # 50
|
||||||
|
TICKS += 2
|
||||||
|
helper2() # 50
|
||||||
|
TICKS += 5
|
||||||
|
helper2_indirect() # 70
|
||||||
|
TICKS += 1
|
||||||
|
|
||||||
|
def helper1():
|
||||||
|
# 4 calls
|
||||||
|
# 30 ticks total: 29 ticks local, 1 tick in subfunctions
|
||||||
|
global TICKS
|
||||||
|
TICKS += 10
|
||||||
|
hasattr(C(), "foo") # 1
|
||||||
|
TICKS += 19
|
||||||
|
lst = []
|
||||||
|
lst.append(42) # 0
|
||||||
|
sys.exc_info() # 0
|
||||||
|
|
||||||
|
def helper2_indirect():
|
||||||
|
helper2() # 50
|
||||||
|
factorial(3) # 20
|
||||||
|
|
||||||
|
def helper2():
|
||||||
|
# 8 calls
|
||||||
|
# 50 ticks local: 39 ticks local, 11 ticks in subfunctions
|
||||||
|
global TICKS
|
||||||
|
TICKS += 11
|
||||||
|
hasattr(C(), "bar") # 1
|
||||||
|
TICKS += 13
|
||||||
|
subhelper() # 10
|
||||||
|
TICKS += 15
|
||||||
|
|
||||||
|
def subhelper():
|
||||||
|
# 8 calls
|
||||||
|
# 10 ticks total: 8 ticks local, 2 ticks in subfunctions
|
||||||
|
global TICKS
|
||||||
|
TICKS += 2
|
||||||
|
for i in range(2): # 0
|
||||||
|
try:
|
||||||
|
C().foo # 1 x 2
|
||||||
|
except AttributeError:
|
||||||
|
TICKS += 3 # 3 x 2
|
||||||
|
|
||||||
|
class C:
|
||||||
|
def __getattr__(self, name):
|
||||||
|
# 28 calls
|
||||||
|
# 1 tick, local
|
||||||
|
global TICKS
|
||||||
|
TICKS += 1
|
||||||
|
raise AttributeError
|
|
@ -117,11 +117,11 @@ b"""<dl><dt><a name="-<lambda>"><strong><lambda></strong></a>(x, y)<
|
||||||
The documentation for the "add" method contains the test material.
|
The documentation for the "add" method contains the test material.
|
||||||
"""
|
"""
|
||||||
self.client.request("GET", "/")
|
self.client.request("GET", "/")
|
||||||
response = self.client.getresponse()
|
response = self.client.getresponse().read()
|
||||||
|
|
||||||
self.assert_( # This is ugly ... how can it be made better?
|
self.assert_( # This is ugly ... how can it be made better?
|
||||||
b"""<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd><tt>Add two instances together. This follows <a href="http://www.python.org/peps/pep-0008.html">PEP008</a>, but has nothing<br>\nto do with <a href="http://www.rfc-editor.org/rfc/rfc1952.txt">RFC1952</a>. Case should matter: pEp008 and rFC1952. Things<br>\nthat start with http and ftp should be auto-linked, too:<br>\n<a href="http://google.com">http://google.com</a>.</tt></dd></dl>"""
|
b"""<dl><dt><a name="-add"><strong>add</strong></a>(x, y)</dt><dd><tt>Add two instances together. This follows <a href="http://www.python.org/dev/peps/pep-0008/">PEP008</a>, but has nothing<br>\nto do with <a href="http://www.rfc-editor.org/rfc/rfc1952.txt">RFC1952</a>. Case should matter: pEp008 and rFC1952. Things<br>\nthat start with http and ftp should be auto-linked, too:<br>\n<a href="http://google.com">http://google.com</a>.</tt></dd></dl>"""
|
||||||
in response.read())
|
in response, response)
|
||||||
|
|
||||||
def test_system_methods(self):
|
def test_system_methods(self):
|
||||||
"""Test the precense of three consecutive system.* methods.
|
"""Test the precense of three consecutive system.* methods.
|
||||||
|
|
|
@ -1,123 +1,179 @@
|
||||||
"""Test suite for the profile module."""
|
"""Test suite for the profile module."""
|
||||||
|
|
||||||
import profile, pstats, sys
|
import os
|
||||||
|
import sys
|
||||||
|
import pstats
|
||||||
|
import unittest
|
||||||
|
from difflib import unified_diff
|
||||||
|
from io import StringIO
|
||||||
|
from test.test_support import run_unittest
|
||||||
|
|
||||||
# In order to have reproducible time, we simulate a timer in the global
|
import profile
|
||||||
# variable 'ticks', which represents simulated time in milliseconds.
|
from test.profilee import testfunc, timer
|
||||||
# (We can't use a helper function increment the timer since it would be
|
|
||||||
# included in the profile and would appear to consume all the time.)
|
|
||||||
ticks = 0
|
class ProfileTest(unittest.TestCase):
|
||||||
|
|
||||||
|
profilerclass = profile.Profile
|
||||||
|
methodnames = ['print_stats', 'print_callers', 'print_callees']
|
||||||
|
expected_output = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def do_profiling(cls):
|
||||||
|
results = []
|
||||||
|
prof = cls.profilerclass(timer, 0.001)
|
||||||
|
prof.runctx("testfunc()", globals(), locals())
|
||||||
|
results.append(timer())
|
||||||
|
for methodname in cls.methodnames:
|
||||||
|
s = StringIO()
|
||||||
|
stats = pstats.Stats(prof, stream=s)
|
||||||
|
stats.strip_dirs().sort_stats("stdname")
|
||||||
|
getattr(stats, methodname)()
|
||||||
|
results.append(s.getvalue())
|
||||||
|
return results
|
||||||
|
|
||||||
|
def test_cprofile(self):
|
||||||
|
results = self.do_profiling()
|
||||||
|
self.assertEqual(results[0], 43000)
|
||||||
|
for i, method in enumerate(self.methodnames):
|
||||||
|
if results[i+1] != self.expected_output[method]:
|
||||||
|
print("Stats.%s output for %s doesn't fit expectation!" %
|
||||||
|
(method, self.profilerclass.__name__))
|
||||||
|
print('\n'.join(unified_diff(
|
||||||
|
results[i+1].split('\n'),
|
||||||
|
self.expected_output[method].split('\n'))))
|
||||||
|
|
||||||
|
|
||||||
|
def regenerate_expected_output(filename, cls):
|
||||||
|
filename = filename.rstrip('co')
|
||||||
|
print('Regenerating %s...' % filename)
|
||||||
|
results = cls.do_profiling()
|
||||||
|
|
||||||
|
newfile = []
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
newfile.append(line)
|
||||||
|
if line[:6] == '#--cut':
|
||||||
|
break
|
||||||
|
|
||||||
|
with open(filename, 'w') as f:
|
||||||
|
f.writelines(newfile)
|
||||||
|
for i, method in enumerate(cls.methodnames):
|
||||||
|
f.write('%s.expected_output[%r] = """\\\n%s"""\n' % (
|
||||||
|
cls.__name__, method, results[i+1]))
|
||||||
|
f.write('\nif __name__ == "__main__":\n main()\n')
|
||||||
|
|
||||||
# IMPORTANT: this is an output test. *ALL* NUMBERS in the expected
|
|
||||||
# output are relevant. If you change the formatting of pstats,
|
|
||||||
# please don't just regenerate output/test_profile without checking
|
|
||||||
# very carefully that not a single number has changed.
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
global ticks
|
run_unittest(ProfileTest)
|
||||||
ticks = 42000
|
|
||||||
prof = profile.Profile(timer)
|
|
||||||
prof.runctx("testfunc()", globals(), locals())
|
|
||||||
assert ticks == 43000, ticks
|
|
||||||
st = pstats.Stats(prof)
|
|
||||||
st.strip_dirs().sort_stats('stdname').print_stats()
|
|
||||||
st.print_callees()
|
|
||||||
st.print_callers()
|
|
||||||
|
|
||||||
def timer():
|
def main():
|
||||||
return ticks*0.001
|
if '-r' not in sys.argv:
|
||||||
|
test_main()
|
||||||
def testfunc():
|
|
||||||
# 1 call
|
|
||||||
# 1000 ticks total: 270 ticks local, 730 ticks in subfunctions
|
|
||||||
global ticks
|
|
||||||
ticks += 99
|
|
||||||
helper() # 300
|
|
||||||
helper() # 300
|
|
||||||
ticks += 171
|
|
||||||
factorial(14) # 130
|
|
||||||
|
|
||||||
def factorial(n):
|
|
||||||
# 23 calls total
|
|
||||||
# 170 ticks total, 150 ticks local
|
|
||||||
# 3 primitive calls, 130, 20 and 20 ticks total
|
|
||||||
# including 116, 17, 17 ticks local
|
|
||||||
global ticks
|
|
||||||
if n > 0:
|
|
||||||
ticks += n
|
|
||||||
return mul(n, factorial(n-1))
|
|
||||||
else:
|
else:
|
||||||
ticks += 11
|
regenerate_expected_output(__file__, ProfileTest)
|
||||||
return 1
|
|
||||||
|
|
||||||
def mul(a, b):
|
|
||||||
# 20 calls
|
|
||||||
# 1 tick, local
|
|
||||||
global ticks
|
|
||||||
ticks += 1
|
|
||||||
return a * b
|
|
||||||
|
|
||||||
def helper():
|
# Don't remove this comment. Everything below it is auto-generated.
|
||||||
# 2 calls
|
#--cut--------------------------------------------------------------------------
|
||||||
# 300 ticks total: 20 ticks local, 260 ticks in subfunctions
|
ProfileTest.expected_output['print_stats'] = """\
|
||||||
global ticks
|
126 function calls (106 primitive calls) in 999.751 CPU seconds
|
||||||
ticks += 1
|
|
||||||
helper1() # 30
|
|
||||||
ticks += 2
|
|
||||||
helper1() # 30
|
|
||||||
ticks += 6
|
|
||||||
helper2() # 50
|
|
||||||
ticks += 3
|
|
||||||
helper2() # 50
|
|
||||||
ticks += 2
|
|
||||||
helper2() # 50
|
|
||||||
ticks += 5
|
|
||||||
helper2_indirect() # 70
|
|
||||||
ticks += 1
|
|
||||||
|
|
||||||
def helper1():
|
Ordered by: standard name
|
||||||
# 4 calls
|
|
||||||
# 30 ticks total: 29 ticks local, 1 tick in subfunctions
|
|
||||||
global ticks
|
|
||||||
ticks += 10
|
|
||||||
hasattr(C(), "foo") # 1
|
|
||||||
ticks += 19
|
|
||||||
lst = []
|
|
||||||
lst.append(42) # 0
|
|
||||||
sys.exc_info() # 0
|
|
||||||
|
|
||||||
def helper2_indirect():
|
ncalls tottime percall cumtime percall filename:lineno(function)
|
||||||
helper2() # 50
|
4 -0.004 -0.001 -0.004 -0.001 :0(append)
|
||||||
factorial(3) # 20
|
4 -0.004 -0.001 -0.004 -0.001 :0(exc_info)
|
||||||
|
1 -0.004 -0.004 999.753 999.753 :0(exec)
|
||||||
|
12 -0.024 -0.002 11.964 0.997 :0(hasattr)
|
||||||
|
1 0.000 0.000 0.000 0.000 :0(setprofile)
|
||||||
|
1 -0.002 -0.002 999.767 999.767 <string>:1(<module>)
|
||||||
|
2 -0.004 -0.002 -0.010 -0.005 io.py:1213(flush)
|
||||||
|
2 -0.002 -0.001 -0.002 -0.001 io.py:656(closed)
|
||||||
|
2 -0.004 -0.002 -0.006 -0.003 io.py:874(flush)
|
||||||
|
0 0.000 0.000 profile:0(profiler)
|
||||||
|
1 -0.002 -0.002 999.751 999.751 profile:0(testfunc())
|
||||||
|
28 27.972 0.999 27.972 0.999 profilee.py:110(__getattr__)
|
||||||
|
1 269.996 269.996 999.769 999.769 profilee.py:25(testfunc)
|
||||||
|
23/3 149.937 6.519 169.917 56.639 profilee.py:35(factorial)
|
||||||
|
20 19.980 0.999 19.980 0.999 profilee.py:48(mul)
|
||||||
|
2 39.986 19.993 599.830 299.915 profilee.py:55(helper)
|
||||||
|
4 115.984 28.996 119.964 29.991 profilee.py:73(helper1)
|
||||||
|
2 -0.006 -0.003 139.946 69.973 profilee.py:84(helper2_indirect)
|
||||||
|
8 311.976 38.997 399.912 49.989 profilee.py:88(helper2)
|
||||||
|
8 63.976 7.997 79.960 9.995 profilee.py:98(subhelper)
|
||||||
|
|
||||||
def helper2():
|
|
||||||
# 8 calls
|
|
||||||
# 50 ticks local: 39 ticks local, 11 ticks in subfunctions
|
|
||||||
global ticks
|
|
||||||
ticks += 11
|
|
||||||
hasattr(C(), "bar") # 1
|
|
||||||
ticks += 13
|
|
||||||
subhelper() # 10
|
|
||||||
ticks += 15
|
|
||||||
|
|
||||||
def subhelper():
|
"""
|
||||||
# 8 calls
|
ProfileTest.expected_output['print_callers'] = """\
|
||||||
# 10 ticks total: 8 ticks local, 2 ticks in subfunctions
|
Ordered by: standard name
|
||||||
global ticks
|
|
||||||
ticks += 2
|
|
||||||
for i in range(2): # 0
|
|
||||||
try:
|
|
||||||
C().foo # 1 x 2
|
|
||||||
except AttributeError:
|
|
||||||
ticks += 3 # 3 x 2
|
|
||||||
|
|
||||||
class C:
|
Function was called by...
|
||||||
def __getattr__(self, name):
|
:0(append) <- profilee.py:73(helper1)(4) 119.964
|
||||||
# 28 calls
|
:0(exc_info) <- profilee.py:73(helper1)(4) 119.964
|
||||||
# 1 tick, local
|
:0(exec) <- profile:0(testfunc())(1) 999.751
|
||||||
global ticks
|
:0(hasattr) <- profilee.py:73(helper1)(4) 119.964
|
||||||
ticks += 1
|
profilee.py:88(helper2)(8) 399.912
|
||||||
raise AttributeError
|
:0(setprofile) <- profile:0(testfunc())(1) 999.751
|
||||||
|
<string>:1(<module>) <- :0(exec)(1) 999.753
|
||||||
|
io.py:1213(flush) <- :0(exec)(2) 999.753
|
||||||
|
io.py:656(closed) <- io.py:874(flush)(2) -0.006
|
||||||
|
io.py:874(flush) <- io.py:1213(flush)(2) -0.010
|
||||||
|
profile:0(profiler) <-
|
||||||
|
profile:0(testfunc()) <- profile:0(profiler)(1) 0.000
|
||||||
|
profilee.py:110(__getattr__) <- :0(hasattr)(12) 11.964
|
||||||
|
profilee.py:98(subhelper)(16) 79.960
|
||||||
|
profilee.py:25(testfunc) <- <string>:1(<module>)(1) 999.767
|
||||||
|
profilee.py:35(factorial) <- profilee.py:25(testfunc)(1) 999.769
|
||||||
|
profilee.py:35(factorial)(20) 169.917
|
||||||
|
profilee.py:84(helper2_indirect)(2) 139.946
|
||||||
|
profilee.py:48(mul) <- profilee.py:35(factorial)(20) 169.917
|
||||||
|
profilee.py:55(helper) <- profilee.py:25(testfunc)(2) 999.769
|
||||||
|
profilee.py:73(helper1) <- profilee.py:55(helper)(4) 599.830
|
||||||
|
profilee.py:84(helper2_indirect) <- profilee.py:55(helper)(2) 599.830
|
||||||
|
profilee.py:88(helper2) <- profilee.py:55(helper)(6) 599.830
|
||||||
|
profilee.py:84(helper2_indirect)(2) 139.946
|
||||||
|
profilee.py:98(subhelper) <- profilee.py:88(helper2)(8) 399.912
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
ProfileTest.expected_output['print_callees'] = """\
|
||||||
|
Ordered by: standard name
|
||||||
|
|
||||||
|
Function called...
|
||||||
|
:0(append) ->
|
||||||
|
:0(exc_info) ->
|
||||||
|
:0(exec) -> <string>:1(<module>)(1) 999.767
|
||||||
|
io.py:1213(flush)(2) -0.010
|
||||||
|
:0(hasattr) -> profilee.py:110(__getattr__)(12) 27.972
|
||||||
|
:0(setprofile) ->
|
||||||
|
<string>:1(<module>) -> profilee.py:25(testfunc)(1) 999.769
|
||||||
|
io.py:1213(flush) -> io.py:874(flush)(2) -0.006
|
||||||
|
io.py:656(closed) ->
|
||||||
|
io.py:874(flush) -> io.py:656(closed)(2) -0.002
|
||||||
|
profile:0(profiler) -> profile:0(testfunc())(1) 999.751
|
||||||
|
profile:0(testfunc()) -> :0(exec)(1) 999.753
|
||||||
|
:0(setprofile)(1) 0.000
|
||||||
|
profilee.py:110(__getattr__) ->
|
||||||
|
profilee.py:25(testfunc) -> profilee.py:35(factorial)(1) 169.917
|
||||||
|
profilee.py:55(helper)(2) 599.830
|
||||||
|
profilee.py:35(factorial) -> profilee.py:35(factorial)(20) 169.917
|
||||||
|
profilee.py:48(mul)(20) 19.980
|
||||||
|
profilee.py:48(mul) ->
|
||||||
|
profilee.py:55(helper) -> profilee.py:73(helper1)(4) 119.964
|
||||||
|
profilee.py:84(helper2_indirect)(2) 139.946
|
||||||
|
profilee.py:88(helper2)(6) 399.912
|
||||||
|
profilee.py:73(helper1) -> :0(append)(4) -0.004
|
||||||
|
:0(exc_info)(4) -0.004
|
||||||
|
:0(hasattr)(4) 11.964
|
||||||
|
profilee.py:84(helper2_indirect) -> profilee.py:35(factorial)(2) 169.917
|
||||||
|
profilee.py:88(helper2)(2) 399.912
|
||||||
|
profilee.py:88(helper2) -> :0(hasattr)(8) 11.964
|
||||||
|
profilee.py:98(subhelper)(8) 79.960
|
||||||
|
profilee.py:98(subhelper) -> profilee.py:110(__getattr__)(16) 27.972
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
main()
|
||||||
|
|
|
@ -339,11 +339,14 @@ class SysModuleTest(unittest.TestCase):
|
||||||
# freed blocks shouldn't change
|
# freed blocks shouldn't change
|
||||||
self.assertEqual(r[0][2], 0)
|
self.assertEqual(r[0][2], 0)
|
||||||
# fill freelists
|
# fill freelists
|
||||||
floats = [float(i) for i in range(12000)]
|
ints = list(range(10000))
|
||||||
|
floats = [float(i) for i in ints]
|
||||||
|
del ints
|
||||||
del floats
|
del floats
|
||||||
# should free more than 200 blocks
|
# should free more than 100 blocks
|
||||||
r = sys._compact_freelists()
|
r = sys._compact_freelists()
|
||||||
self.assert_(r[0][2] > 200, r[0][2])
|
self.assert_(r[0][1] > 100, r[0][1])
|
||||||
|
self.assert_(r[0][2] > 100, r[0][2])
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test.test_support.run_unittest(SysModuleTest)
|
test.test_support.run_unittest(SysModuleTest)
|
||||||
|
|
|
@ -252,14 +252,16 @@ class TraceTestCase(unittest.TestCase):
|
||||||
"\n".join(difflib.ndiff([str(x) for x in expected_events],
|
"\n".join(difflib.ndiff([str(x) for x in expected_events],
|
||||||
[str(x) for x in events])))
|
[str(x) for x in events])))
|
||||||
|
|
||||||
|
def run_and_compare(self, func, events):
|
||||||
def run_test(self, func):
|
|
||||||
tracer = Tracer()
|
tracer = Tracer()
|
||||||
sys.settrace(tracer.trace)
|
sys.settrace(tracer.trace)
|
||||||
func()
|
func()
|
||||||
sys.settrace(None)
|
sys.settrace(None)
|
||||||
self.compare_events(func.__code__.co_firstlineno,
|
self.compare_events(func.__code__.co_firstlineno,
|
||||||
tracer.events, func.events)
|
tracer.events, events)
|
||||||
|
|
||||||
|
def run_test(self, func):
|
||||||
|
self.run_and_compare(func, func.events)
|
||||||
|
|
||||||
def run_test2(self, func):
|
def run_test2(self, func):
|
||||||
tracer = Tracer()
|
tracer = Tracer()
|
||||||
|
@ -321,6 +323,59 @@ class TraceTestCase(unittest.TestCase):
|
||||||
self.compare_events(generator_example.__code__.co_firstlineno,
|
self.compare_events(generator_example.__code__.co_firstlineno,
|
||||||
tracer.events, generator_example.events)
|
tracer.events, generator_example.events)
|
||||||
|
|
||||||
|
def test_14_onliner_if(self):
|
||||||
|
def onliners():
|
||||||
|
if True: False
|
||||||
|
else: True
|
||||||
|
return 0
|
||||||
|
self.run_and_compare(
|
||||||
|
onliners,
|
||||||
|
[(0, 'call'),
|
||||||
|
(1, 'line'),
|
||||||
|
(3, 'line'),
|
||||||
|
(3, 'return')])
|
||||||
|
|
||||||
|
def test_15_loops(self):
|
||||||
|
# issue1750076: "while" expression is skipped by debugger
|
||||||
|
def for_example():
|
||||||
|
for x in range(2):
|
||||||
|
pass
|
||||||
|
self.run_and_compare(
|
||||||
|
for_example,
|
||||||
|
[(0, 'call'),
|
||||||
|
(1, 'line'),
|
||||||
|
(2, 'line'),
|
||||||
|
(1, 'line'),
|
||||||
|
(2, 'line'),
|
||||||
|
(1, 'line'),
|
||||||
|
(1, 'return')])
|
||||||
|
|
||||||
|
def while_example():
|
||||||
|
# While expression should be traced on every loop
|
||||||
|
x = 2
|
||||||
|
while x > 0:
|
||||||
|
x -= 1
|
||||||
|
self.run_and_compare(
|
||||||
|
while_example,
|
||||||
|
[(0, 'call'),
|
||||||
|
(2, 'line'),
|
||||||
|
(3, 'line'),
|
||||||
|
(4, 'line'),
|
||||||
|
(3, 'line'),
|
||||||
|
(4, 'line'),
|
||||||
|
(3, 'line'),
|
||||||
|
(3, 'return')])
|
||||||
|
|
||||||
|
def test_16_blank_lines(self):
|
||||||
|
namespace = {}
|
||||||
|
exec("def f():\n" + "\n" * 256 + " pass", namespace)
|
||||||
|
self.run_and_compare(
|
||||||
|
namespace["f"],
|
||||||
|
[(0, 'call'),
|
||||||
|
(257, 'line'),
|
||||||
|
(257, 'return')])
|
||||||
|
|
||||||
|
|
||||||
class RaisingTraceFuncTestCase(unittest.TestCase):
|
class RaisingTraceFuncTestCase(unittest.TestCase):
|
||||||
def trace(self, frame, event, arg):
|
def trace(self, frame, event, arg):
|
||||||
"""A trace function that raises an exception in response to a
|
"""A trace function that raises an exception in response to a
|
||||||
|
|
|
@ -1,32 +1,45 @@
|
||||||
from test.test_support import TestFailed, TESTFN
|
from test.test_support import TESTFN, run_unittest
|
||||||
import os
|
import os
|
||||||
import wave
|
import wave
|
||||||
|
import unittest
|
||||||
def check(t, msg=None):
|
|
||||||
if not t:
|
|
||||||
raise TestFailed(msg)
|
|
||||||
|
|
||||||
nchannels = 2
|
nchannels = 2
|
||||||
sampwidth = 2
|
sampwidth = 2
|
||||||
framerate = 8000
|
framerate = 8000
|
||||||
nframes = 100
|
nframes = 100
|
||||||
|
|
||||||
f = wave.open(TESTFN, 'wb')
|
class TestWave(unittest.TestCase):
|
||||||
f.setnchannels(nchannels)
|
|
||||||
f.setsampwidth(sampwidth)
|
|
||||||
f.setframerate(framerate)
|
|
||||||
f.setnframes(nframes)
|
|
||||||
output = b'\0' * nframes * nchannels * sampwidth
|
|
||||||
f.writeframes(output)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
f = wave.open(TESTFN, 'rb')
|
def setUp(self):
|
||||||
check(nchannels == f.getnchannels(), "nchannels")
|
self.f = None
|
||||||
check(sampwidth == f.getsampwidth(), "sampwidth")
|
|
||||||
check(framerate == f.getframerate(), "framerate")
|
|
||||||
check(nframes == f.getnframes(), "nframes")
|
|
||||||
input = f.readframes(nframes)
|
|
||||||
check(input == output, "data")
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
os.remove(TESTFN)
|
def tearDown(self):
|
||||||
|
if self.f is not None:
|
||||||
|
self.f.close()
|
||||||
|
try:
|
||||||
|
os.remove(TESTFN)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_it(self):
|
||||||
|
self.f = wave.open(TESTFN, 'wb')
|
||||||
|
self.f.setnchannels(nchannels)
|
||||||
|
self.f.setsampwidth(sampwidth)
|
||||||
|
self.f.setframerate(framerate)
|
||||||
|
self.f.setnframes(nframes)
|
||||||
|
output = b'\0' * nframes * nchannels * sampwidth
|
||||||
|
self.f.writeframes(output)
|
||||||
|
self.f.close()
|
||||||
|
|
||||||
|
self.f = wave.open(TESTFN, 'rb')
|
||||||
|
self.assertEqual(nchannels, self.f.getnchannels())
|
||||||
|
self.assertEqual(sampwidth, self.f.getsampwidth())
|
||||||
|
self.assertEqual(framerate, self.f.getframerate())
|
||||||
|
self.assertEqual(nframes, self.f.getnframes())
|
||||||
|
self.assertEqual(self.f.readframes(nframes), output)
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
run_unittest(TestWave)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_main()
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
;; Copyright (C) 1992,1993,1994 Tim Peters
|
;; Copyright (C) 1992,1993,1994 Tim Peters
|
||||||
|
|
||||||
;; Author: 1995-2002 Barry A. Warsaw
|
;; Author: 2003-2007 http://sf.net/projects/python-mode
|
||||||
|
;; 1995-2002 Barry A. Warsaw
|
||||||
;; 1992-1994 Tim Peters
|
;; 1992-1994 Tim Peters
|
||||||
;; Maintainer: python-mode@python.org
|
;; Maintainer: python-mode@python.org
|
||||||
;; Created: Feb 1992
|
;; Created: Feb 1992
|
||||||
|
@ -19,19 +20,38 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; This is a major mode for editing Python programs. It was developed
|
;; This is a major mode for editing Python programs. It was developed by Tim
|
||||||
;; by Tim Peters after an original idea by Michael A. Guravage. Tim
|
;; Peters after an original idea by Michael A. Guravage. Tim subsequently
|
||||||
;; subsequently left the net; in 1995, Barry Warsaw inherited the mode
|
;; left the net and in 1995, Barry Warsaw inherited the mode. Tim's now back
|
||||||
;; and is the current maintainer. Tim's now back but disavows all
|
;; but disavows all responsibility for the mode. In fact, we suspect he
|
||||||
;; responsibility for the mode. Smart Tim :-)
|
;; doesn't even use Emacs any more. In 2003, python-mode.el was moved to its
|
||||||
|
;; own SourceForge project apart from the Python project, and now is
|
||||||
|
;; maintained by the volunteers at the python-mode@python.org mailing list.
|
||||||
|
|
||||||
;; pdbtrack support contributed by Ken Manheimer, April 2001.
|
;; pdbtrack support contributed by Ken Manheimer, April 2001. Skip Montanaro
|
||||||
|
;; has also contributed significantly to python-mode's development.
|
||||||
|
|
||||||
;; Please use the SourceForge Python project to submit bugs or
|
;; Please use the SourceForge Python project to submit bugs or
|
||||||
;; patches:
|
;; patches:
|
||||||
;;
|
;;
|
||||||
;; http://sourceforge.net/projects/python
|
;; http://sourceforge.net/projects/python
|
||||||
|
|
||||||
|
;; INSTALLATION:
|
||||||
|
|
||||||
|
;; To install, just drop this file into a directory on your load-path and
|
||||||
|
;; byte-compile it. To set up Emacs to automatically edit files ending in
|
||||||
|
;; ".py" using python-mode add the following to your ~/.emacs file (GNU
|
||||||
|
;; Emacs) or ~/.xemacs/init.el file (XEmacs):
|
||||||
|
;; (setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
|
||||||
|
;; (setq interpreter-mode-alist (cons '("python" . python-mode)
|
||||||
|
;; interpreter-mode-alist))
|
||||||
|
;; (autoload 'python-mode "python-mode" "Python editing mode." t)
|
||||||
|
;;
|
||||||
|
;; In XEmacs syntax highlighting should be enabled automatically. In GNU
|
||||||
|
;; Emacs you may have to add these lines to your ~/.emacs file:
|
||||||
|
;; (global-font-lock-mode t)
|
||||||
|
;; (setq font-lock-maximum-decoration t)
|
||||||
|
|
||||||
;; FOR MORE INFORMATION:
|
;; FOR MORE INFORMATION:
|
||||||
|
|
||||||
;; There is some information on python-mode.el at
|
;; There is some information on python-mode.el at
|
||||||
|
@ -60,6 +80,7 @@
|
||||||
(require 'custom)
|
(require 'custom)
|
||||||
(require 'cl)
|
(require 'cl)
|
||||||
(require 'compile)
|
(require 'compile)
|
||||||
|
(require 'ansi-color)
|
||||||
|
|
||||||
|
|
||||||
;; user definable variables
|
;; user definable variables
|
||||||
|
@ -70,34 +91,41 @@
|
||||||
:group 'languages
|
:group 'languages
|
||||||
:prefix "py-")
|
:prefix "py-")
|
||||||
|
|
||||||
|
(defcustom py-tab-always-indent t
|
||||||
|
"*Non-nil means TAB in Python mode should always reindent the current line,
|
||||||
|
regardless of where in the line point is when the TAB command is used."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'python)
|
||||||
|
|
||||||
(defcustom py-python-command "python"
|
(defcustom py-python-command "python"
|
||||||
"*Shell command used to start Python interpreter."
|
"*Shell command used to start Python interpreter."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'python)
|
:group 'python)
|
||||||
|
|
||||||
(defcustom py-jpython-command "jpython"
|
(make-obsolete-variable 'py-jpython-command 'py-jython-command)
|
||||||
"*Shell command used to start the JPython interpreter."
|
(defcustom py-jython-command "jython"
|
||||||
|
"*Shell command used to start the Jython interpreter."
|
||||||
:type 'string
|
:type 'string
|
||||||
:group 'python
|
:group 'python
|
||||||
:tag "JPython Command")
|
:tag "Jython Command")
|
||||||
|
|
||||||
(defcustom py-default-interpreter 'cpython
|
(defcustom py-default-interpreter 'cpython
|
||||||
"*Which Python interpreter is used by default.
|
"*Which Python interpreter is used by default.
|
||||||
The value for this variable can be either `cpython' or `jpython'.
|
The value for this variable can be either `cpython' or `jython'.
|
||||||
|
|
||||||
When the value is `cpython', the variables `py-python-command' and
|
When the value is `cpython', the variables `py-python-command' and
|
||||||
`py-python-command-args' are consulted to determine the interpreter
|
`py-python-command-args' are consulted to determine the interpreter
|
||||||
and arguments to use.
|
and arguments to use.
|
||||||
|
|
||||||
When the value is `jpython', the variables `py-jpython-command' and
|
When the value is `jython', the variables `py-jython-command' and
|
||||||
`py-jpython-command-args' are consulted to determine the interpreter
|
`py-jython-command-args' are consulted to determine the interpreter
|
||||||
and arguments to use.
|
and arguments to use.
|
||||||
|
|
||||||
Note that this variable is consulted only the first time that a Python
|
Note that this variable is consulted only the first time that a Python
|
||||||
mode buffer is visited during an Emacs session. After that, use
|
mode buffer is visited during an Emacs session. After that, use
|
||||||
\\[py-toggle-shells] to change the interpreter shell."
|
\\[py-toggle-shells] to change the interpreter shell."
|
||||||
:type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
|
:type '(choice (const :tag "Python (a.k.a. CPython)" cpython)
|
||||||
(const :tag "JPython" jpython))
|
(const :tag "Jython" jython))
|
||||||
:group 'python)
|
:group 'python)
|
||||||
|
|
||||||
(defcustom py-python-command-args '("-i")
|
(defcustom py-python-command-args '("-i")
|
||||||
|
@ -105,11 +133,12 @@ mode buffer is visited during an Emacs session. After that, use
|
||||||
:type '(repeat string)
|
:type '(repeat string)
|
||||||
:group 'python)
|
:group 'python)
|
||||||
|
|
||||||
(defcustom py-jpython-command-args '("-i")
|
(make-obsolete-variable 'py-jpython-command-args 'py-jython-command-args)
|
||||||
"*List of string arguments to be used when starting a JPython shell."
|
(defcustom py-jython-command-args '("-i")
|
||||||
|
"*List of string arguments to be used when starting a Jython shell."
|
||||||
:type '(repeat string)
|
:type '(repeat string)
|
||||||
:group 'python
|
:group 'python
|
||||||
:tag "JPython Command Args")
|
:tag "Jython Command Args")
|
||||||
|
|
||||||
(defcustom py-indent-offset 4
|
(defcustom py-indent-offset 4
|
||||||
"*Amount of offset per level of indentation.
|
"*Amount of offset per level of indentation.
|
||||||
|
@ -248,7 +277,7 @@ Otherwise, all modified buffers are saved without asking."
|
||||||
:type 'function
|
:type 'function
|
||||||
:group 'python)
|
:group 'python)
|
||||||
|
|
||||||
(defcustom py-imenu-show-method-args-p nil
|
(defcustom py-imenu-show-method-args-p nil
|
||||||
"*Controls echoing of arguments of functions & methods in the Imenu buffer.
|
"*Controls echoing of arguments of functions & methods in the Imenu buffer.
|
||||||
When non-nil, arguments are printed."
|
When non-nil, arguments are printed."
|
||||||
:type 'boolean
|
:type 'boolean
|
||||||
|
@ -275,19 +304,20 @@ as gud-mode does for debugging C programs with gdb."
|
||||||
20000
|
20000
|
||||||
"Maximum number of characters to search for a Java-ish import statement.
|
"Maximum number of characters to search for a Java-ish import statement.
|
||||||
When `python-mode' tries to calculate the shell to use (either a
|
When `python-mode' tries to calculate the shell to use (either a
|
||||||
CPython or a JPython shell), it looks at the so-called `shebang' line
|
CPython or a Jython shell), it looks at the so-called `shebang' line
|
||||||
-- i.e. #! line. If that's not available, it looks at some of the
|
-- i.e. #! line. If that's not available, it looks at some of the
|
||||||
file heading imports to see if they look Java-like."
|
file heading imports to see if they look Java-like."
|
||||||
:type 'integer
|
:type 'integer
|
||||||
:group 'python
|
:group 'python
|
||||||
)
|
)
|
||||||
|
|
||||||
(defcustom py-jpython-packages
|
(make-obsolete-variable 'py-jpython-packages 'py-jython-packages)
|
||||||
|
(defcustom py-jython-packages
|
||||||
'("java" "javax" "org" "com")
|
'("java" "javax" "org" "com")
|
||||||
"Imported packages that imply `jpython-mode'."
|
"Imported packages that imply `jython-mode'."
|
||||||
:type '(repeat string)
|
:type '(repeat string)
|
||||||
:group 'python)
|
:group 'python)
|
||||||
|
|
||||||
;; Not customizable
|
;; Not customizable
|
||||||
(defvar py-master-file nil
|
(defvar py-master-file nil
|
||||||
"If non-nil, execute the named file instead of the buffer's file.
|
"If non-nil, execute the named file instead of the buffer's file.
|
||||||
|
@ -317,16 +347,39 @@ buffer is prepended to come up with a file name.")
|
||||||
:tag "Pychecker Command Args")
|
:tag "Pychecker Command Args")
|
||||||
|
|
||||||
(defvar py-shell-alist
|
(defvar py-shell-alist
|
||||||
'(("jpython" . 'jpython)
|
'(("jython" . 'jython)
|
||||||
("jython" . 'jpython)
|
|
||||||
("python" . 'cpython))
|
("python" . 'cpython))
|
||||||
"*Alist of interpreters and python shells. Used by `py-choose-shell'
|
"*Alist of interpreters and python shells. Used by `py-choose-shell'
|
||||||
to select the appropriate python interpreter mode for a file.")
|
to select the appropriate python interpreter mode for a file.")
|
||||||
|
|
||||||
|
(defcustom py-shell-input-prompt-1-regexp "^>>> "
|
||||||
|
"*A regular expression to match the input prompt of the shell."
|
||||||
|
:type 'string
|
||||||
|
:group 'python)
|
||||||
|
|
||||||
|
(defcustom py-shell-input-prompt-2-regexp "^[.][.][.] "
|
||||||
|
"*A regular expression to match the input prompt of the shell after the
|
||||||
|
first line of input."
|
||||||
|
:type 'string
|
||||||
|
:group 'python)
|
||||||
|
|
||||||
|
(defcustom py-shell-switch-buffers-on-execute t
|
||||||
|
"*Controls switching to the Python buffer where commands are
|
||||||
|
executed. When non-nil the buffer switches to the Python buffer, if
|
||||||
|
not no switching occurs."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'python)
|
||||||
|
|
||||||
|
|
||||||
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
|
;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
|
||||||
|
|
||||||
|
(defvar py-line-number-offset 0
|
||||||
|
"When an exception occurs as a result of py-execute-region, a
|
||||||
|
subsequent py-up-exception needs the line number where the region
|
||||||
|
started, in order to jump to the correct file line. This variable is
|
||||||
|
set in py-execute-region and used in py-jump-to-exception.")
|
||||||
|
|
||||||
(defconst py-emacs-features
|
(defconst py-emacs-features
|
||||||
(let (features)
|
(let (features)
|
||||||
features)
|
features)
|
||||||
|
@ -339,9 +392,31 @@ support for features needed by `python-mode'.")
|
||||||
"Face for pseudo keywords in Python mode, like self, True, False, Ellipsis.")
|
"Face for pseudo keywords in Python mode, like self, True, False, Ellipsis.")
|
||||||
(make-face 'py-pseudo-keyword-face)
|
(make-face 'py-pseudo-keyword-face)
|
||||||
|
|
||||||
|
;; PEP 318 decorators
|
||||||
|
(defvar py-decorators-face 'py-decorators-face
|
||||||
|
"Face method decorators.")
|
||||||
|
(make-face 'py-decorators-face)
|
||||||
|
|
||||||
|
;; Face for builtins
|
||||||
|
(defvar py-builtins-face 'py-builtins-face
|
||||||
|
"Face for builtins like TypeError, object, open, and exec.")
|
||||||
|
(make-face 'py-builtins-face)
|
||||||
|
|
||||||
|
;; XXX, TODO, and FIXME comments and such
|
||||||
|
(defvar py-XXX-tag-face 'py-XXX-tag-face
|
||||||
|
"Face for XXX, TODO, and FIXME tags")
|
||||||
|
(make-face 'py-XXX-tag-face)
|
||||||
|
|
||||||
(defun py-font-lock-mode-hook ()
|
(defun py-font-lock-mode-hook ()
|
||||||
(or (face-differs-from-default-p 'py-pseudo-keyword-face)
|
(or (face-differs-from-default-p 'py-pseudo-keyword-face)
|
||||||
(copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face)))
|
(copy-face 'font-lock-keyword-face 'py-pseudo-keyword-face))
|
||||||
|
(or (face-differs-from-default-p 'py-builtins-face)
|
||||||
|
(copy-face 'font-lock-keyword-face 'py-builtins-face))
|
||||||
|
(or (face-differs-from-default-p 'py-decorators-face)
|
||||||
|
(copy-face 'py-pseudo-keyword-face 'py-decorators-face))
|
||||||
|
(or (face-differs-from-default-p 'py-XXX-tag-face)
|
||||||
|
(copy-face 'font-lock-comment-face 'py-XXX-tag-face))
|
||||||
|
)
|
||||||
(add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook)
|
(add-hook 'font-lock-mode-hook 'py-font-lock-mode-hook)
|
||||||
|
|
||||||
(defvar python-font-lock-keywords
|
(defvar python-font-lock-keywords
|
||||||
|
@ -352,7 +427,7 @@ support for features needed by `python-mode'.")
|
||||||
"from" "global" "if" "import"
|
"from" "global" "if" "import"
|
||||||
"in" "is" "lambda" "not"
|
"in" "is" "lambda" "not"
|
||||||
"or" "pass" "print" "raise"
|
"or" "pass" "print" "raise"
|
||||||
"return" "while" "yield"
|
"return" "while" "with" "yield"
|
||||||
)
|
)
|
||||||
"\\|"))
|
"\\|"))
|
||||||
(kw2 (mapconcat 'identity
|
(kw2 (mapconcat 'identity
|
||||||
|
@ -391,26 +466,52 @@ support for features needed by `python-mode'.")
|
||||||
"super" "tuple" "type" "unichr" "unicode" "vars"
|
"super" "tuple" "type" "unichr" "unicode" "vars"
|
||||||
"zip")
|
"zip")
|
||||||
"\\|"))
|
"\\|"))
|
||||||
|
(kw4 (mapconcat 'identity
|
||||||
|
;; Exceptions and warnings
|
||||||
|
'("ArithmeticError" "AssertionError"
|
||||||
|
"AttributeError" "DeprecationWarning" "EOFError"
|
||||||
|
"EnvironmentError" "Exception"
|
||||||
|
"FloatingPointError" "FutureWarning" "IOError"
|
||||||
|
"ImportError" "IndentationError" "IndexError"
|
||||||
|
"KeyError" "KeyboardInterrupt" "LookupError"
|
||||||
|
"MemoryError" "NameError" "NotImplemented"
|
||||||
|
"NotImplementedError" "OSError" "OverflowError"
|
||||||
|
"OverflowWarning" "PendingDeprecationWarning"
|
||||||
|
"ReferenceError" "RuntimeError" "RuntimeWarning"
|
||||||
|
"StandardError" "StopIteration" "SyntaxError"
|
||||||
|
"SyntaxWarning" "SystemError" "SystemExit"
|
||||||
|
"TabError" "TypeError" "UnboundLocalError"
|
||||||
|
"UnicodeDecodeError" "UnicodeEncodeError"
|
||||||
|
"UnicodeError" "UnicodeTranslateError"
|
||||||
|
"UserWarning" "ValueError" "Warning"
|
||||||
|
"ZeroDivisionError")
|
||||||
|
"\\|"))
|
||||||
)
|
)
|
||||||
(list
|
(list
|
||||||
|
'("^[ \t]*\\(@.+\\)" 1 'py-decorators-face)
|
||||||
;; keywords
|
;; keywords
|
||||||
(cons (concat "\\b\\(" kw1 "\\)\\b[ \n\t(]") 1)
|
(cons (concat "\\<\\(" kw1 "\\)\\>[ \n\t(]") 1)
|
||||||
;; builtins when they don't appear as object attributes
|
;; builtins when they don't appear as object attributes
|
||||||
(cons (concat "\\(\\b\\|[.]\\)\\(" kw3 "\\)\\b[ \n\t(]") 2)
|
(list (concat "\\([^. \t]\\|^\\)[ \t]*\\<\\(" kw3 "\\)\\>[ \n\t(]") 2
|
||||||
|
'py-builtins-face)
|
||||||
;; block introducing keywords with immediately following colons.
|
;; block introducing keywords with immediately following colons.
|
||||||
;; Yes "except" is in both lists.
|
;; Yes "except" is in both lists.
|
||||||
(cons (concat "\\b\\(" kw2 "\\)[ \n\t(]") 1)
|
(cons (concat "\\<\\(" kw2 "\\)[ \n\t(]") 1)
|
||||||
;; `as' but only in "import foo as bar"
|
;; Exceptions
|
||||||
'("[ \t]*\\(\\bfrom\\b.*\\)?\\bimport\\b.*\\b\\(as\\)\\b" . 2)
|
(list (concat "\\<\\(" kw4 "\\)[ \n\t:,(]") 1 'py-builtins-face)
|
||||||
|
;; `as' but only in "import foo as bar" or "with foo as bar"
|
||||||
|
'("[ \t]*\\(\\<from\\>.*\\)?\\<import\\>.*\\<\\(as\\)\\>" . 2)
|
||||||
|
'("[ \t]*\\<with\\>.*\\<\\(as\\)\\>" . 1)
|
||||||
;; classes
|
;; classes
|
||||||
'("\\bclass[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
|
'("\\<class[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)" 1 font-lock-type-face)
|
||||||
1 font-lock-type-face)
|
|
||||||
;; functions
|
;; functions
|
||||||
'("\\bdef[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
|
'("\\<def[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*\\)"
|
||||||
1 font-lock-function-name-face)
|
1 font-lock-function-name-face)
|
||||||
;; pseudo-keywords
|
;; pseudo-keywords
|
||||||
'("\\b\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\b"
|
'("\\<\\(self\\|None\\|True\\|False\\|Ellipsis\\)\\>"
|
||||||
1 py-pseudo-keyword-face)
|
1 py-pseudo-keyword-face)
|
||||||
|
;; XXX, TODO, and FIXME tags
|
||||||
|
'("XXX\\|TODO\\|FIXME" 0 py-XXX-tag-face t)
|
||||||
))
|
))
|
||||||
"Additional expressions to highlight in Python mode.")
|
"Additional expressions to highlight in Python mode.")
|
||||||
(put 'python-mode 'font-lock-defaults '(python-font-lock-keywords))
|
(put 'python-mode 'font-lock-defaults '(python-font-lock-keywords))
|
||||||
|
@ -421,13 +522,7 @@ support for features needed by `python-mode'.")
|
||||||
Currently-active file is at the head of the list.")
|
Currently-active file is at the head of the list.")
|
||||||
|
|
||||||
(defvar py-pdbtrack-is-tracking-p nil)
|
(defvar py-pdbtrack-is-tracking-p nil)
|
||||||
(defvar py-pdbtrack-last-grubbed-buffer nil
|
|
||||||
"Record of the last buffer used when the source path was invalid.
|
|
||||||
|
|
||||||
This buffer is consulted before the buffer-list history for satisfying
|
|
||||||
`py-pdbtrack-grub-for-buffer', since it's the most often the likely
|
|
||||||
prospect as debugging continues.")
|
|
||||||
(make-variable-buffer-local 'py-pdbtrack-last-grubbed-buffer)
|
|
||||||
(defvar py-pychecker-history nil)
|
(defvar py-pychecker-history nil)
|
||||||
|
|
||||||
|
|
||||||
|
@ -461,7 +556,7 @@ prospect as debugging continues.")
|
||||||
"\\(" "[^#'\"\n\\]" "\\|" py-stringlit-re "\\)*"
|
"\\(" "[^#'\"\n\\]" "\\|" py-stringlit-re "\\)*"
|
||||||
"\\\\$")
|
"\\\\$")
|
||||||
"Regular expression matching Python backslash continuation lines.")
|
"Regular expression matching Python backslash continuation lines.")
|
||||||
|
|
||||||
(defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
|
(defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
|
||||||
"Regular expression matching a blank or comment line.")
|
"Regular expression matching a blank or comment line.")
|
||||||
|
|
||||||
|
@ -474,7 +569,7 @@ prospect as debugging continues.")
|
||||||
"\\|")
|
"\\|")
|
||||||
"\\)")
|
"\\)")
|
||||||
"Regular expression matching statements to be dedented one level.")
|
"Regular expression matching statements to be dedented one level.")
|
||||||
|
|
||||||
(defconst py-block-closing-keywords-re
|
(defconst py-block-closing-keywords-re
|
||||||
"\\(return\\|raise\\|break\\|continue\\|pass\\)"
|
"\\(return\\|raise\\|break\\|continue\\|pass\\)"
|
||||||
"Regular expression matching keywords which typically close a block.")
|
"Regular expression matching keywords which typically close a block.")
|
||||||
|
@ -495,30 +590,17 @@ prospect as debugging continues.")
|
||||||
"\\)")
|
"\\)")
|
||||||
"Regular expression matching lines not to dedent after.")
|
"Regular expression matching lines not to dedent after.")
|
||||||
|
|
||||||
(defconst py-defun-start-re
|
(defvar py-traceback-line-re
|
||||||
"^\\([ \t]*\\)def[ \t]+\\([a-zA-Z_0-9]+\\)\\|\\(^[a-zA-Z_0-9]+\\)[ \t]*="
|
|
||||||
;; If you change this, you probably have to change py-current-defun
|
|
||||||
;; as well. This is only used by py-current-defun to find the name
|
|
||||||
;; for add-log.el.
|
|
||||||
"Regular expression matching a function, method, or variable assignment.")
|
|
||||||
|
|
||||||
(defconst py-class-start-re "^class[ \t]*\\([a-zA-Z_0-9]+\\)"
|
|
||||||
;; If you change this, you probably have to change py-current-defun
|
|
||||||
;; as well. This is only used by py-current-defun to find the name
|
|
||||||
;; for add-log.el.
|
|
||||||
"Regular expression for finding a class name.")
|
|
||||||
|
|
||||||
(defconst py-traceback-line-re
|
|
||||||
"[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)"
|
"[ \t]+File \"\\([^\"]+\\)\", line \\([0-9]+\\)"
|
||||||
"Regular expression that describes tracebacks.")
|
"Regular expression that describes tracebacks.")
|
||||||
|
|
||||||
;; pdbtrack contants
|
;; pdbtrack constants
|
||||||
(defconst py-pdbtrack-stack-entry-regexp
|
(defconst py-pdbtrack-stack-entry-regexp
|
||||||
; "^> \\([^(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
|
; "^> \\([^(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
|
||||||
"^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
|
"^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
|
||||||
"Regular expression pdbtrack uses to find a stack trace entry.")
|
"Regular expression pdbtrack uses to find a stack trace entry.")
|
||||||
|
|
||||||
(defconst py-pdbtrack-input-prompt "\n[(<]*pdb[>)]+ "
|
(defconst py-pdbtrack-input-prompt "\n[(<]*[Pp]db[>)]+ "
|
||||||
"Regular expression pdbtrack uses to recognize a pdb prompt.")
|
"Regular expression pdbtrack uses to recognize a pdb prompt.")
|
||||||
|
|
||||||
(defconst py-pdbtrack-track-range 10000
|
(defconst py-pdbtrack-track-range 10000
|
||||||
|
@ -536,8 +618,9 @@ prospect as debugging continues.")
|
||||||
(defvar python-mode-hook nil
|
(defvar python-mode-hook nil
|
||||||
"*Hook called by `python-mode'.")
|
"*Hook called by `python-mode'.")
|
||||||
|
|
||||||
(defvar jpython-mode-hook nil
|
(make-obsolete-variable 'jpython-mode-hook 'jython-mode-hook)
|
||||||
"*Hook called by `jpython-mode'. `jpython-mode' also calls
|
(defvar jython-mode-hook nil
|
||||||
|
"*Hook called by `jython-mode'. `jython-mode' also calls
|
||||||
`python-mode-hook'.")
|
`python-mode-hook'.")
|
||||||
|
|
||||||
(defvar py-shell-hook nil
|
(defvar py-shell-hook nil
|
||||||
|
@ -560,8 +643,6 @@ prospect as debugging continues.")
|
||||||
(define-key py-mode-map "\C-c\C-r" 'py-shift-region-right)
|
(define-key py-mode-map "\C-c\C-r" 'py-shift-region-right)
|
||||||
(define-key py-mode-map "\C-c<" 'py-shift-region-left)
|
(define-key py-mode-map "\C-c<" 'py-shift-region-left)
|
||||||
(define-key py-mode-map "\C-c>" 'py-shift-region-right)
|
(define-key py-mode-map "\C-c>" 'py-shift-region-right)
|
||||||
;; paragraph and string filling
|
|
||||||
(define-key py-mode-map "\eq" 'py-fill-paragraph)
|
|
||||||
;; subprocess commands
|
;; subprocess commands
|
||||||
(define-key py-mode-map "\C-c\C-c" 'py-execute-buffer)
|
(define-key py-mode-map "\C-c\C-c" 'py-execute-buffer)
|
||||||
(define-key py-mode-map "\C-c\C-m" 'py-execute-import-or-reload)
|
(define-key py-mode-map "\C-c\C-m" 'py-execute-import-or-reload)
|
||||||
|
@ -624,7 +705,7 @@ prospect as debugging continues.")
|
||||||
;; expect RET to do a `py-newline-and-indent' and any Emacsers who
|
;; expect RET to do a `py-newline-and-indent' and any Emacsers who
|
||||||
;; dislike this are probably knowledgeable enough to do a rebind.
|
;; dislike this are probably knowledgeable enough to do a rebind.
|
||||||
;; However, we do *not* change C-j since many Emacsers have already
|
;; However, we do *not* change C-j since many Emacsers have already
|
||||||
;; swapped RET and C-j and they don't want C-j bound to `newline' to
|
;; swapped RET and C-j and they don't want C-j bound to `newline' to
|
||||||
;; change.
|
;; change.
|
||||||
(define-key py-mode-map "\C-m" 'py-newline-and-indent)
|
(define-key py-mode-map "\C-m" 'py-newline-and-indent)
|
||||||
)
|
)
|
||||||
|
@ -740,8 +821,8 @@ This function does not modify point or mark."
|
||||||
(cond
|
(cond
|
||||||
((eq position 'bol) (beginning-of-line))
|
((eq position 'bol) (beginning-of-line))
|
||||||
((eq position 'eol) (end-of-line))
|
((eq position 'eol) (end-of-line))
|
||||||
((eq position 'bod) (py-beginning-of-def-or-class))
|
((eq position 'bod) (py-beginning-of-def-or-class 'either))
|
||||||
((eq position 'eod) (py-end-of-def-or-class))
|
((eq position 'eod) (py-end-of-def-or-class 'either))
|
||||||
;; Kind of funny, I know, but useful for py-up-exception.
|
;; Kind of funny, I know, but useful for py-up-exception.
|
||||||
((eq position 'bob) (beginning-of-buffer))
|
((eq position 'bob) (beginning-of-buffer))
|
||||||
((eq position 'eob) (end-of-buffer))
|
((eq position 'eob) (end-of-buffer))
|
||||||
|
@ -849,7 +930,7 @@ package. Note that the latest X/Emacs releases contain this package.")
|
||||||
|
|
||||||
(defvar py-imenu-method-regexp
|
(defvar py-imenu-method-regexp
|
||||||
(concat ; <<methods and functions>>
|
(concat ; <<methods and functions>>
|
||||||
"\\(" ;
|
"\\(" ;
|
||||||
"^[ \t]*" ; new line and maybe whitespace
|
"^[ \t]*" ; new line and maybe whitespace
|
||||||
"\\(def[ \t]+" ; function definitions start with def
|
"\\(def[ \t]+" ; function definitions start with def
|
||||||
"\\([a-zA-Z0-9_]+\\)" ; name is here
|
"\\([a-zA-Z0-9_]+\\)" ; name is here
|
||||||
|
@ -885,7 +966,7 @@ information.")
|
||||||
;; it.
|
;; it.
|
||||||
(defvar py-imenu-generic-expression
|
(defvar py-imenu-generic-expression
|
||||||
(cons
|
(cons
|
||||||
(concat
|
(concat
|
||||||
py-imenu-class-regexp
|
py-imenu-class-regexp
|
||||||
"\\|" ; or...
|
"\\|" ; or...
|
||||||
py-imenu-method-regexp
|
py-imenu-method-regexp
|
||||||
|
@ -954,7 +1035,7 @@ of the first definition found."
|
||||||
looking-p
|
looking-p
|
||||||
def-name prev-name
|
def-name prev-name
|
||||||
cur-indent def-pos
|
cur-indent def-pos
|
||||||
(class-paren (first py-imenu-generic-parens))
|
(class-paren (first py-imenu-generic-parens))
|
||||||
(def-paren (second py-imenu-generic-parens)))
|
(def-paren (second py-imenu-generic-parens)))
|
||||||
(setq looking-p
|
(setq looking-p
|
||||||
(re-search-forward py-imenu-generic-regexp (point-max) t))
|
(re-search-forward py-imenu-generic-regexp (point-max) t))
|
||||||
|
@ -1009,7 +1090,7 @@ of the first definition found."
|
||||||
(cons save-elmt sub-method-alist))
|
(cons save-elmt sub-method-alist))
|
||||||
index-alist))))
|
index-alist))))
|
||||||
;; found less indented expression, we're done.
|
;; found less indented expression, we're done.
|
||||||
(t
|
(t
|
||||||
(setq looking-p nil)
|
(setq looking-p nil)
|
||||||
(re-search-backward py-imenu-generic-regexp (point-min) t)))
|
(re-search-backward py-imenu-generic-regexp (point-min) t)))
|
||||||
;; end-cond
|
;; end-cond
|
||||||
|
@ -1023,7 +1104,7 @@ of the first definition found."
|
||||||
|
|
||||||
|
|
||||||
(defun py-choose-shell-by-shebang ()
|
(defun py-choose-shell-by-shebang ()
|
||||||
"Choose CPython or JPython mode by looking at #! on the first line.
|
"Choose CPython or Jython mode by looking at #! on the first line.
|
||||||
Returns the appropriate mode function.
|
Returns the appropriate mode function.
|
||||||
Used by `py-choose-shell', and similar to but distinct from
|
Used by `py-choose-shell', and similar to but distinct from
|
||||||
`set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)."
|
`set-auto-mode', though it uses `auto-mode-interpreter-regexp' (if available)."
|
||||||
|
@ -1047,10 +1128,10 @@ Used by `py-choose-shell', and similar to but distinct from
|
||||||
|
|
||||||
|
|
||||||
(defun py-choose-shell-by-import ()
|
(defun py-choose-shell-by-import ()
|
||||||
"Choose CPython or JPython mode based imports.
|
"Choose CPython or Jython mode based imports.
|
||||||
If a file imports any packages in `py-jpython-packages', within
|
If a file imports any packages in `py-jython-packages', within
|
||||||
`py-import-check-point-max' characters from the start of the file,
|
`py-import-check-point-max' characters from the start of the file,
|
||||||
return `jpython', otherwise return nil."
|
return `jython', otherwise return nil."
|
||||||
(let (mode)
|
(let (mode)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
|
@ -1058,14 +1139,14 @@ return `jpython', otherwise return nil."
|
||||||
(search-forward-regexp
|
(search-forward-regexp
|
||||||
"^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)"
|
"^\\(\\(from\\)\\|\\(import\\)\\) \\([^ \t\n.]+\\)"
|
||||||
py-import-check-point-max t))
|
py-import-check-point-max t))
|
||||||
(setq mode (and (member (match-string 4) py-jpython-packages)
|
(setq mode (and (member (match-string 4) py-jython-packages)
|
||||||
'jpython
|
'jython
|
||||||
))))
|
))))
|
||||||
mode))
|
mode))
|
||||||
|
|
||||||
|
|
||||||
(defun py-choose-shell ()
|
(defun py-choose-shell ()
|
||||||
"Choose CPython or JPython mode. Returns the appropriate mode function.
|
"Choose CPython or Jython mode. Returns the appropriate mode function.
|
||||||
This does the following:
|
This does the following:
|
||||||
- look for an interpreter with `py-choose-shell-by-shebang'
|
- look for an interpreter with `py-choose-shell-by-shebang'
|
||||||
- examine imports using `py-choose-shell-by-import'
|
- examine imports using `py-choose-shell-by-import'
|
||||||
|
@ -1114,6 +1195,7 @@ py-beep-if-tab-change\t\tring the bell if `tab-width' is changed"
|
||||||
(make-local-variable 'indent-region-function)
|
(make-local-variable 'indent-region-function)
|
||||||
(make-local-variable 'indent-line-function)
|
(make-local-variable 'indent-line-function)
|
||||||
(make-local-variable 'add-log-current-defun-function)
|
(make-local-variable 'add-log-current-defun-function)
|
||||||
|
(make-local-variable 'fill-paragraph-function)
|
||||||
;;
|
;;
|
||||||
(set-syntax-table py-mode-syntax-table)
|
(set-syntax-table py-mode-syntax-table)
|
||||||
(setq major-mode 'python-mode
|
(setq major-mode 'python-mode
|
||||||
|
@ -1132,6 +1214,8 @@ py-beep-if-tab-change\t\tring the bell if `tab-width' is changed"
|
||||||
indent-line-function 'py-indent-line
|
indent-line-function 'py-indent-line
|
||||||
;; tell add-log.el how to find the current function/method/variable
|
;; tell add-log.el how to find the current function/method/variable
|
||||||
add-log-current-defun-function 'py-current-defun
|
add-log-current-defun-function 'py-current-defun
|
||||||
|
|
||||||
|
fill-paragraph-function 'py-fill-paragraph
|
||||||
)
|
)
|
||||||
(use-local-map py-mode-map)
|
(use-local-map py-mode-map)
|
||||||
;; add the menu
|
;; add the menu
|
||||||
|
@ -1171,17 +1255,18 @@ py-beep-if-tab-change\t\tring the bell if `tab-width' is changed"
|
||||||
(py-toggle-shells (py-choose-shell))))
|
(py-toggle-shells (py-choose-shell))))
|
||||||
|
|
||||||
|
|
||||||
(defun jpython-mode ()
|
(make-obsolete 'jpython-mode 'jython-mode)
|
||||||
"Major mode for editing JPython/Jython files.
|
(defun jython-mode ()
|
||||||
|
"Major mode for editing Jython/Jython files.
|
||||||
This is a simple wrapper around `python-mode'.
|
This is a simple wrapper around `python-mode'.
|
||||||
It runs `jpython-mode-hook' then calls `python-mode.'
|
It runs `jython-mode-hook' then calls `python-mode.'
|
||||||
It is added to `interpreter-mode-alist' and `py-choose-shell'.
|
It is added to `interpreter-mode-alist' and `py-choose-shell'.
|
||||||
"
|
"
|
||||||
(interactive)
|
(interactive)
|
||||||
(python-mode)
|
(python-mode)
|
||||||
(py-toggle-shells 'jpython)
|
(py-toggle-shells 'jython)
|
||||||
(when jpython-mode-hook
|
(when jython-mode-hook
|
||||||
(run-hooks 'jpython-mode-hook)))
|
(run-hooks 'jython-mode-hook)))
|
||||||
|
|
||||||
|
|
||||||
;; It's handy to add recognition of Python files to the
|
;; It's handy to add recognition of Python files to the
|
||||||
|
@ -1189,16 +1274,16 @@ It is added to `interpreter-mode-alist' and `py-choose-shell'.
|
||||||
;; can specify different `derived-modes' based on the #! line, but
|
;; can specify different `derived-modes' based on the #! line, but
|
||||||
;; with the latter, we can't. So we just won't add them if they're
|
;; with the latter, we can't. So we just won't add them if they're
|
||||||
;; already added.
|
;; already added.
|
||||||
(let ((modes '(("jpython" . jpython-mode)
|
;;;###autoload
|
||||||
("jython" . jpython-mode)
|
(let ((modes '(("jython" . jython-mode)
|
||||||
("python" . python-mode))))
|
("python" . python-mode))))
|
||||||
(while modes
|
(while modes
|
||||||
(when (not (assoc (car modes) interpreter-mode-alist))
|
(when (not (assoc (car modes) interpreter-mode-alist))
|
||||||
(push (car modes) interpreter-mode-alist))
|
(push (car modes) interpreter-mode-alist))
|
||||||
(setq modes (cdr modes))))
|
(setq modes (cdr modes))))
|
||||||
|
;;;###autoload
|
||||||
(when (not (or (rassq 'python-mode auto-mode-alist)
|
(when (not (or (rassq 'python-mode auto-mode-alist)
|
||||||
(rassq 'jpython-mode auto-mode-alist)))
|
(rassq 'jython-mode auto-mode-alist)))
|
||||||
(push '("\\.py$" . python-mode) auto-mode-alist))
|
(push '("\\.py$" . python-mode) auto-mode-alist))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1283,12 +1368,13 @@ comint believe the user typed this string so that
|
||||||
(defun py-comint-output-filter-function (string)
|
(defun py-comint-output-filter-function (string)
|
||||||
"Watch output for Python prompt and exec next file waiting in queue.
|
"Watch output for Python prompt and exec next file waiting in queue.
|
||||||
This function is appropriate for `comint-output-filter-functions'."
|
This function is appropriate for `comint-output-filter-functions'."
|
||||||
;; TBD: this should probably use split-string
|
;;remove ansi terminal escape sequences from string, not sure why they are
|
||||||
(when (and (or (string-equal string ">>> ")
|
;;still around...
|
||||||
(and (>= (length string) 5)
|
(setq string (ansi-color-filter-apply string))
|
||||||
(string-equal (substring string -5) "\n>>> ")))
|
(when (and (string-match py-shell-input-prompt-1-regexp string)
|
||||||
py-file-queue)
|
py-file-queue)
|
||||||
(pop-to-buffer (current-buffer))
|
(if py-shell-switch-buffers-on-execute
|
||||||
|
(pop-to-buffer (current-buffer)))
|
||||||
(py-safe (delete-file (car py-file-queue)))
|
(py-safe (delete-file (car py-file-queue)))
|
||||||
(setq py-file-queue (cdr py-file-queue))
|
(setq py-file-queue (cdr py-file-queue))
|
||||||
(if py-file-queue
|
(if py-file-queue
|
||||||
|
@ -1344,7 +1430,7 @@ script, and set to python-mode, and pdbtrack will find it.)"
|
||||||
(- procmark
|
(- procmark
|
||||||
py-pdbtrack-track-range))
|
py-pdbtrack-track-range))
|
||||||
procmark))
|
procmark))
|
||||||
target target_fname target_lineno)
|
target target_fname target_lineno target_buffer)
|
||||||
|
|
||||||
(if (not (string-match (concat py-pdbtrack-input-prompt "$") block))
|
(if (not (string-match (concat py-pdbtrack-input-prompt "$") block))
|
||||||
(py-pdbtrack-overlay-arrow nil)
|
(py-pdbtrack-overlay-arrow nil)
|
||||||
|
@ -1372,8 +1458,7 @@ script, and set to python-mode, and pdbtrack will find it.)"
|
||||||
We look first to visit the file indicated in the trace.
|
We look first to visit the file indicated in the trace.
|
||||||
|
|
||||||
Failing that, we look for the most recently visited python-mode buffer
|
Failing that, we look for the most recently visited python-mode buffer
|
||||||
with the same name or having
|
with the same name or having the named function.
|
||||||
having the named function.
|
|
||||||
|
|
||||||
If we're unable find the source code we return a string describing the
|
If we're unable find the source code we return a string describing the
|
||||||
problem as best as we can determine."
|
problem as best as we can determine."
|
||||||
|
@ -1417,11 +1502,10 @@ problem as best as we can determine."
|
||||||
(defun py-pdbtrack-grub-for-buffer (funcname lineno)
|
(defun py-pdbtrack-grub-for-buffer (funcname lineno)
|
||||||
"Find most recent buffer itself named or having function funcname.
|
"Find most recent buffer itself named or having function funcname.
|
||||||
|
|
||||||
We first check the last buffer this function found, if any, then walk
|
We walk the buffer-list history for python-mode buffers that are
|
||||||
throught the buffer-list history for python-mode buffers that are
|
|
||||||
named for funcname or define a function funcname."
|
named for funcname or define a function funcname."
|
||||||
(let ((buffers (buffer-list))
|
(let ((buffers (buffer-list))
|
||||||
curbuf
|
buf
|
||||||
got)
|
got)
|
||||||
(while (and buffers (not got))
|
(while (and buffers (not got))
|
||||||
(setq buf (car buffers)
|
(setq buf (car buffers)
|
||||||
|
@ -1436,7 +1520,7 @@ named for funcname or define a function funcname."
|
||||||
(buffer-substring (point-min)
|
(buffer-substring (point-min)
|
||||||
(point-max))))))
|
(point-max))))))
|
||||||
(setq got buf)))
|
(setq got buf)))
|
||||||
(setq py-pdbtrack-last-grubbed-buffer got)))
|
got))
|
||||||
|
|
||||||
(defun py-postprocess-output-buffer (buf)
|
(defun py-postprocess-output-buffer (buf)
|
||||||
"Highlight exceptions found in BUF.
|
"Highlight exceptions found in BUF.
|
||||||
|
@ -1466,7 +1550,7 @@ If an exception occurred return t, otherwise return nil. BUF must exist."
|
||||||
(defconst py-output-buffer "*Python Output*")
|
(defconst py-output-buffer "*Python Output*")
|
||||||
(make-variable-buffer-local 'py-output-buffer)
|
(make-variable-buffer-local 'py-output-buffer)
|
||||||
|
|
||||||
;; for toggling between CPython and JPython
|
;; for toggling between CPython and Jython
|
||||||
(defvar py-which-shell nil)
|
(defvar py-which-shell nil)
|
||||||
(defvar py-which-args py-python-command-args)
|
(defvar py-which-args py-python-command-args)
|
||||||
(defvar py-which-bufname "Python")
|
(defvar py-which-bufname "Python")
|
||||||
|
@ -1475,14 +1559,14 @@ If an exception occurred return t, otherwise return nil. BUF must exist."
|
||||||
(make-variable-buffer-local 'py-which-bufname)
|
(make-variable-buffer-local 'py-which-bufname)
|
||||||
|
|
||||||
(defun py-toggle-shells (arg)
|
(defun py-toggle-shells (arg)
|
||||||
"Toggles between the CPython and JPython shells.
|
"Toggles between the CPython and Jython shells.
|
||||||
|
|
||||||
With positive argument ARG (interactively \\[universal-argument]),
|
With positive argument ARG (interactively \\[universal-argument]),
|
||||||
uses the CPython shell, with negative ARG uses the JPython shell, and
|
uses the CPython shell, with negative ARG uses the Jython shell, and
|
||||||
with a zero argument, toggles the shell.
|
with a zero argument, toggles the shell.
|
||||||
|
|
||||||
Programmatically, ARG can also be one of the symbols `cpython' or
|
Programmatically, ARG can also be one of the symbols `cpython' or
|
||||||
`jpython', equivalent to positive arg and negative arg respectively."
|
`jython', equivalent to positive arg and negative arg respectively."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
;; default is to toggle
|
;; default is to toggle
|
||||||
(if (null arg)
|
(if (null arg)
|
||||||
|
@ -1495,7 +1579,7 @@ Programmatically, ARG can also be one of the symbols `cpython' or
|
||||||
(setq arg -1)
|
(setq arg -1)
|
||||||
(setq arg 1)))
|
(setq arg 1)))
|
||||||
((equal arg 'cpython) (setq arg 1))
|
((equal arg 'cpython) (setq arg 1))
|
||||||
((equal arg 'jpython) (setq arg -1)))
|
((equal arg 'jython) (setq arg -1)))
|
||||||
(let (msg)
|
(let (msg)
|
||||||
(cond
|
(cond
|
||||||
((< 0 arg)
|
((< 0 arg)
|
||||||
|
@ -1503,14 +1587,16 @@ Programmatically, ARG can also be one of the symbols `cpython' or
|
||||||
(setq py-which-shell py-python-command
|
(setq py-which-shell py-python-command
|
||||||
py-which-args py-python-command-args
|
py-which-args py-python-command-args
|
||||||
py-which-bufname "Python"
|
py-which-bufname "Python"
|
||||||
msg "CPython"
|
msg "CPython")
|
||||||
mode-name "Python"))
|
(if (string-equal py-which-bufname "Jython")
|
||||||
|
(setq mode-name "Python")))
|
||||||
((> 0 arg)
|
((> 0 arg)
|
||||||
(setq py-which-shell py-jpython-command
|
(setq py-which-shell py-jython-command
|
||||||
py-which-args py-jpython-command-args
|
py-which-args py-jython-command-args
|
||||||
py-which-bufname "JPython"
|
py-which-bufname "Jython"
|
||||||
msg "JPython"
|
msg "Jython")
|
||||||
mode-name "JPython"))
|
(if (string-equal py-which-bufname "Python")
|
||||||
|
(setq mode-name "Jython")))
|
||||||
)
|
)
|
||||||
(message "Using the %s shell" msg)
|
(message "Using the %s shell" msg)
|
||||||
(setq py-output-buffer (format "*%s Output*" py-which-bufname))))
|
(setq py-output-buffer (format "*%s Output*" py-which-bufname))))
|
||||||
|
@ -1532,9 +1618,9 @@ prompt). This argument is ignored when this function is called
|
||||||
programmatically, or when running in Emacs 19.34 or older.
|
programmatically, or when running in Emacs 19.34 or older.
|
||||||
|
|
||||||
Note: You can toggle between using the CPython interpreter and the
|
Note: You can toggle between using the CPython interpreter and the
|
||||||
JPython interpreter by hitting \\[py-toggle-shells]. This toggles
|
Jython interpreter by hitting \\[py-toggle-shells]. This toggles
|
||||||
buffer local variables which control whether all your subshell
|
buffer local variables which control whether all your subshell
|
||||||
interactions happen to the `*JPython*' or `*Python*' buffers (the
|
interactions happen to the `*Jython*' or `*Python*' buffers (the
|
||||||
latter is the name used for the CPython buffer).
|
latter is the name used for the CPython buffer).
|
||||||
|
|
||||||
Warning: Don't use an interactive Python if you change sys.ps1 or
|
Warning: Don't use an interactive Python if you change sys.ps1 or
|
||||||
|
@ -1568,10 +1654,14 @@ filter."
|
||||||
(concat
|
(concat
|
||||||
(mapconcat 'identity py-which-args " ") " ")
|
(mapconcat 'identity py-which-args " ") " ")
|
||||||
))))
|
))))
|
||||||
(switch-to-buffer-other-window
|
(if (not (equal (buffer-name) "*Python*"))
|
||||||
(apply 'make-comint py-which-bufname py-which-shell nil args))
|
(switch-to-buffer-other-window
|
||||||
|
(apply 'make-comint py-which-bufname py-which-shell nil args))
|
||||||
|
(apply 'make-comint py-which-bufname py-which-shell nil args))
|
||||||
(make-local-variable 'comint-prompt-regexp)
|
(make-local-variable 'comint-prompt-regexp)
|
||||||
(setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
|
(setq comint-prompt-regexp (concat py-shell-input-prompt-1-regexp "\\|"
|
||||||
|
py-shell-input-prompt-2-regexp "\\|"
|
||||||
|
"^([Pp]db) "))
|
||||||
(add-hook 'comint-output-filter-functions
|
(add-hook 'comint-output-filter-functions
|
||||||
'py-comint-output-filter-function)
|
'py-comint-output-filter-function)
|
||||||
;; pdbtrack
|
;; pdbtrack
|
||||||
|
@ -1642,11 +1732,13 @@ is inserted at the end. See also the command `py-clear-queue'."
|
||||||
(setq start (point))
|
(setq start (point))
|
||||||
(or (< start end)
|
(or (< start end)
|
||||||
(error "Region is empty"))
|
(error "Region is empty"))
|
||||||
|
(setq py-line-number-offset (count-lines 1 start))
|
||||||
(let ((needs-if (/= (py-point 'bol) (py-point 'boi))))
|
(let ((needs-if (/= (py-point 'bol) (py-point 'boi))))
|
||||||
(set-buffer buf)
|
(set-buffer buf)
|
||||||
(python-mode)
|
(python-mode)
|
||||||
(when needs-if
|
(when needs-if
|
||||||
(insert "if 1:\n"))
|
(insert "if 1:\n")
|
||||||
|
(setq py-line-number-offset (- py-line-number-offset 1)))
|
||||||
(insert-buffer-substring cur start end)
|
(insert-buffer-substring cur start end)
|
||||||
;; Set the shell either to the #! line command, or to the
|
;; Set the shell either to the #! line command, or to the
|
||||||
;; py-which-shell buffer local variable.
|
;; py-which-shell buffer local variable.
|
||||||
|
@ -1683,8 +1775,9 @@ is inserted at the end. See also the command `py-clear-queue'."
|
||||||
(setq py-exception-buffer (cons file (current-buffer))))
|
(setq py-exception-buffer (cons file (current-buffer))))
|
||||||
(t
|
(t
|
||||||
;; TBD: a horrible hack, but why create new Custom variables?
|
;; TBD: a horrible hack, but why create new Custom variables?
|
||||||
(let ((cmd (concat shell (if (string-equal py-which-bufname "JPython")
|
(let ((cmd (concat py-which-shell (if (string-equal py-which-bufname
|
||||||
" -" ""))))
|
"Jython")
|
||||||
|
" -" ""))))
|
||||||
;; otherwise either run it synchronously in a subprocess
|
;; otherwise either run it synchronously in a subprocess
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(set-buffer buf)
|
(set-buffer buf)
|
||||||
|
@ -1718,12 +1811,14 @@ sent. A trailing newline will be supplied if needed.
|
||||||
See the `\\[py-execute-region]' docs for an account of some
|
See the `\\[py-execute-region]' docs for an account of some
|
||||||
subtleties, including the use of the optional ASYNC argument."
|
subtleties, including the use of the optional ASYNC argument."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(if py-master-file
|
(let ((old-buffer (current-buffer)))
|
||||||
(let* ((filename (expand-file-name py-master-file))
|
(if py-master-file
|
||||||
(buffer (or (get-file-buffer filename)
|
(let* ((filename (expand-file-name py-master-file))
|
||||||
(find-file-noselect filename))))
|
(buffer (or (get-file-buffer filename)
|
||||||
(set-buffer buffer)))
|
(find-file-noselect filename))))
|
||||||
(py-execute-region (point-min) (point-max) async))
|
(set-buffer buffer)))
|
||||||
|
(py-execute-region (point-min) (point-max) async)
|
||||||
|
(pop-to-buffer old-buffer)))
|
||||||
|
|
||||||
(defun py-execute-import-or-reload (&optional async)
|
(defun py-execute-import-or-reload (&optional async)
|
||||||
"Import the current buffer's file in a Python interpreter.
|
"Import the current buffer's file in a Python interpreter.
|
||||||
|
@ -1819,6 +1914,9 @@ subtleties, including the use of the optional ASYNC argument."
|
||||||
(t (find-file (read-file-name "Exception file: "
|
(t (find-file (read-file-name "Exception file: "
|
||||||
nil
|
nil
|
||||||
file t))))))
|
file t))))))
|
||||||
|
;; Fiddle about with line number
|
||||||
|
(setq line (+ py-line-number-offset line))
|
||||||
|
|
||||||
(pop-to-buffer buffer)
|
(pop-to-buffer buffer)
|
||||||
;; Force Python mode
|
;; Force Python mode
|
||||||
(if (not (eq major-mode 'python-mode))
|
(if (not (eq major-mode 'python-mode))
|
||||||
|
@ -1999,16 +2097,29 @@ This function is normally bound to `indent-line-function' so
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let* ((ci (current-indentation))
|
(let* ((ci (current-indentation))
|
||||||
(move-to-indentation-p (<= (current-column) ci))
|
(move-to-indentation-p (<= (current-column) ci))
|
||||||
(need (py-compute-indentation (not arg))))
|
(need (py-compute-indentation (not arg)))
|
||||||
;; see if we need to dedent
|
(cc (current-column)))
|
||||||
(if (py-outdent-p)
|
;; dedent out a level if previous command was the same unless we're in
|
||||||
(setq need (- need py-indent-offset)))
|
;; column 1
|
||||||
(if (/= ci need)
|
(if (and (equal last-command this-command)
|
||||||
(save-excursion
|
(/= cc 0))
|
||||||
(beginning-of-line)
|
(progn
|
||||||
(delete-horizontal-space)
|
(beginning-of-line)
|
||||||
(indent-to need)))
|
(delete-horizontal-space)
|
||||||
(if move-to-indentation-p (back-to-indentation))))
|
(indent-to (* (/ (- cc 1) py-indent-offset) py-indent-offset)))
|
||||||
|
(progn
|
||||||
|
;; see if we need to dedent
|
||||||
|
(if (py-outdent-p)
|
||||||
|
(setq need (- need py-indent-offset)))
|
||||||
|
(if (or py-tab-always-indent
|
||||||
|
move-to-indentation-p)
|
||||||
|
(progn (if (/= ci need)
|
||||||
|
(save-excursion
|
||||||
|
(beginning-of-line)
|
||||||
|
(delete-horizontal-space)
|
||||||
|
(indent-to need)))
|
||||||
|
(if move-to-indentation-p (back-to-indentation)))
|
||||||
|
(insert-tab))))))
|
||||||
|
|
||||||
(defun py-newline-and-indent ()
|
(defun py-newline-and-indent ()
|
||||||
"Strives to act like the Emacs `newline-and-indent'.
|
"Strives to act like the Emacs `newline-and-indent'.
|
||||||
|
@ -2052,39 +2163,23 @@ dedenting."
|
||||||
((py-continuation-line-p)
|
((py-continuation-line-p)
|
||||||
(let ((startpos (point))
|
(let ((startpos (point))
|
||||||
(open-bracket-pos (py-nesting-level))
|
(open-bracket-pos (py-nesting-level))
|
||||||
endpos searching found state)
|
endpos searching found state cind cline)
|
||||||
(if open-bracket-pos
|
(if open-bracket-pos
|
||||||
(progn
|
(progn
|
||||||
;; align with first item in list; else a normal
|
(setq endpos (py-point 'bol))
|
||||||
;; indent beyond the line with the open bracket
|
(py-goto-initial-line)
|
||||||
(goto-char (1+ open-bracket-pos)) ; just beyond bracket
|
(setq cind (current-indentation))
|
||||||
;; is the first list item on the same line?
|
(setq cline cind)
|
||||||
(skip-chars-forward " \t")
|
(dolist (bp
|
||||||
(if (null (memq (following-char) '(?\n ?# ?\\)))
|
(nth 9 (save-excursion
|
||||||
; yes, so line up with it
|
(parse-partial-sexp (point) endpos)))
|
||||||
(current-column)
|
cind)
|
||||||
;; first list item on another line, or doesn't exist yet
|
(if (search-forward "\n" bp t) (setq cline cind))
|
||||||
(forward-line 1)
|
(goto-char (1+ bp))
|
||||||
(while (and (< (point) startpos)
|
(skip-chars-forward " \t")
|
||||||
(looking-at "[ \t]*[#\n\\\\]")) ; skip noise
|
(setq cind (if (memq (following-char) '(?\n ?# ?\\))
|
||||||
(forward-line 1))
|
(+ cline py-indent-offset)
|
||||||
(if (and (< (point) startpos)
|
(current-column)))))
|
||||||
(/= startpos
|
|
||||||
(save-excursion
|
|
||||||
(goto-char (1+ open-bracket-pos))
|
|
||||||
(forward-comment (point-max))
|
|
||||||
(point))))
|
|
||||||
;; again mimic the first list item
|
|
||||||
(current-indentation)
|
|
||||||
;; else they're about to enter the first item
|
|
||||||
(goto-char open-bracket-pos)
|
|
||||||
(setq placeholder (point))
|
|
||||||
(py-goto-initial-line)
|
|
||||||
(py-goto-beginning-of-tqs
|
|
||||||
(save-excursion (nth 3 (parse-partial-sexp
|
|
||||||
placeholder (point)))))
|
|
||||||
(+ (current-indentation) py-indent-offset))))
|
|
||||||
|
|
||||||
;; else on backslash continuation line
|
;; else on backslash continuation line
|
||||||
(forward-line -1)
|
(forward-line -1)
|
||||||
(if (py-continuation-line-p) ; on at least 3rd line in block
|
(if (py-continuation-line-p) ; on at least 3rd line in block
|
||||||
|
@ -2832,7 +2927,7 @@ pleasant."
|
||||||
;; ripped from cc-mode
|
;; ripped from cc-mode
|
||||||
(defun py-forward-into-nomenclature (&optional arg)
|
(defun py-forward-into-nomenclature (&optional arg)
|
||||||
"Move forward to end of a nomenclature section or word.
|
"Move forward to end of a nomenclature section or word.
|
||||||
With \\[universal-argument] (programmatically, optional argument ARG),
|
With \\[universal-argument] (programmatically, optional argument ARG),
|
||||||
do it that many times.
|
do it that many times.
|
||||||
|
|
||||||
A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
|
A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
|
||||||
|
@ -2886,6 +2981,11 @@ A `nomenclature' is a fancy way of saying AWordWithMixedCaseNotUnderscores."
|
||||||
|
|
||||||
|
|
||||||
;; Pychecker
|
;; Pychecker
|
||||||
|
|
||||||
|
;; hack for FSF Emacs
|
||||||
|
(unless (fboundp 'read-shell-command)
|
||||||
|
(defalias 'read-shell-command 'read-string))
|
||||||
|
|
||||||
(defun py-pychecker-run (command)
|
(defun py-pychecker-run (command)
|
||||||
"*Run pychecker (default on the file currently visited)."
|
"*Run pychecker (default on the file currently visited)."
|
||||||
(interactive
|
(interactive
|
||||||
|
@ -3410,7 +3510,7 @@ multi-line statement we need to skip over the continuation lines."
|
||||||
|
|
||||||
(defun py-statement-opens-block-p ()
|
(defun py-statement-opens-block-p ()
|
||||||
"Return t iff the current statement opens a block.
|
"Return t iff the current statement opens a block.
|
||||||
I.e., iff it ends with a colon that is not in a comment. Point should
|
I.e., iff it ends with a colon that is not in a comment. Point should
|
||||||
be at the start of a statement."
|
be at the start of a statement."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((start (point))
|
(let ((start (point))
|
||||||
|
@ -3494,8 +3594,8 @@ does not include blank lines, comments, or continuation lines."
|
||||||
KEY is a regular expression describing a Python keyword. Skip blank
|
KEY is a regular expression describing a Python keyword. Skip blank
|
||||||
lines and non-indenting comments. If the statement found starts with
|
lines and non-indenting comments. If the statement found starts with
|
||||||
KEY, then stop, otherwise go back to first enclosing block starting
|
KEY, then stop, otherwise go back to first enclosing block starting
|
||||||
with KEY. If successful, leave point at the start of the KEY line and
|
with KEY. If successful, leave point at the start of the KEY line and
|
||||||
return t. Otherwise, leav point at an undefined place and return nil."
|
return t. Otherwise, leave point at an undefined place and return nil."
|
||||||
;; skip blanks and non-indenting #
|
;; skip blanks and non-indenting #
|
||||||
(py-goto-initial-line)
|
(py-goto-initial-line)
|
||||||
(while (and
|
(while (and
|
||||||
|
@ -3503,7 +3603,7 @@ return t. Otherwise, leav point at an undefined place and return nil."
|
||||||
(zerop (forward-line -1))) ; go back
|
(zerop (forward-line -1))) ; go back
|
||||||
nil)
|
nil)
|
||||||
(py-goto-initial-line)
|
(py-goto-initial-line)
|
||||||
(let* ((re (concat "[ \t]*" key "\\b"))
|
(let* ((re (concat "[ \t]*" key "\\>"))
|
||||||
(case-fold-search nil) ; let* so looking-at sees this
|
(case-fold-search nil) ; let* so looking-at sees this
|
||||||
(found (looking-at re))
|
(found (looking-at re))
|
||||||
(dead nil))
|
(dead nil))
|
||||||
|
@ -3529,7 +3629,7 @@ Prefix with \"...\" if leading whitespace was skipped."
|
||||||
`Keyword' is defined (essentially) as the regular expression
|
`Keyword' is defined (essentially) as the regular expression
|
||||||
([a-z]+). Returns nil if none was found."
|
([a-z]+). Returns nil if none was found."
|
||||||
(let ((case-fold-search nil))
|
(let ((case-fold-search nil))
|
||||||
(if (looking-at "[ \t]*\\([a-z]+\\)\\b")
|
(if (looking-at "[ \t]*\\([a-z]+\\)\\>")
|
||||||
(intern (buffer-substring (match-beginning 1) (match-end 1)))
|
(intern (buffer-substring (match-beginning 1) (match-end 1)))
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
|
@ -3537,14 +3637,49 @@ Prefix with \"...\" if leading whitespace was skipped."
|
||||||
"Python value for `add-log-current-defun-function'.
|
"Python value for `add-log-current-defun-function'.
|
||||||
This tells add-log.el how to find the current function/method/variable."
|
This tells add-log.el how to find the current function/method/variable."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(if (re-search-backward py-defun-start-re nil t)
|
|
||||||
(or (match-string 3)
|
;; Move back to start of the current statement.
|
||||||
(let ((method (match-string 2)))
|
|
||||||
(if (and (not (zerop (length (match-string 1))))
|
(py-goto-initial-line)
|
||||||
(re-search-backward py-class-start-re nil t))
|
(back-to-indentation)
|
||||||
(concat (match-string 1) "." method)
|
(while (and (or (looking-at py-blank-or-comment-re)
|
||||||
method)))
|
(py-in-literal))
|
||||||
nil)))
|
(not (bobp)))
|
||||||
|
(backward-to-indentation 1))
|
||||||
|
(py-goto-initial-line)
|
||||||
|
|
||||||
|
(let ((scopes "")
|
||||||
|
(sep "")
|
||||||
|
dead assignment)
|
||||||
|
|
||||||
|
;; Check for an assignment. If this assignment exists inside a
|
||||||
|
;; def, it will be overwritten inside the while loop. If it
|
||||||
|
;; exists at top lever or inside a class, it will be preserved.
|
||||||
|
|
||||||
|
(when (looking-at "[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*=")
|
||||||
|
(setq scopes (buffer-substring (match-beginning 1) (match-end 1)))
|
||||||
|
(setq assignment t)
|
||||||
|
(setq sep "."))
|
||||||
|
|
||||||
|
;; Prepend the name of each outer socpe (def or class).
|
||||||
|
|
||||||
|
(while (not dead)
|
||||||
|
(if (and (py-go-up-tree-to-keyword "\\(class\\|def\\)")
|
||||||
|
(looking-at
|
||||||
|
"[ \t]*\\(class\\|def\\)[ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*"))
|
||||||
|
(let ((name (buffer-substring (match-beginning 2) (match-end 2))))
|
||||||
|
(if (and assignment (looking-at "[ \t]*def"))
|
||||||
|
(setq scopes name)
|
||||||
|
(setq scopes (concat name sep scopes))
|
||||||
|
(setq sep "."))))
|
||||||
|
(setq assignment nil)
|
||||||
|
(condition-case nil ; Terminate nicely at top level.
|
||||||
|
(py-goto-block-up 'no-mark)
|
||||||
|
(error (setq dead t))))
|
||||||
|
(if (string= scopes "")
|
||||||
|
nil
|
||||||
|
scopes))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defconst py-help-address "python-mode@python.org"
|
(defconst py-help-address "python-mode@python.org"
|
||||||
|
@ -3586,7 +3721,7 @@ non-nil) just submit an enhancement request."
|
||||||
"Dear Barry,") ;salutation
|
"Dear Barry,") ;salutation
|
||||||
(if enhancement-p nil
|
(if enhancement-p nil
|
||||||
(set-mark (point))
|
(set-mark (point))
|
||||||
(insert
|
(insert
|
||||||
"Please replace this text with a sufficiently large code sample\n\
|
"Please replace this text with a sufficiently large code sample\n\
|
||||||
and an exact recipe so that I can reproduce your problem. Failure\n\
|
and an exact recipe so that I can reproduce your problem. Failure\n\
|
||||||
to do so may mean a greater delay in fixing your bug.\n\n")
|
to do so may mean a greater delay in fixing your bug.\n\n")
|
||||||
|
@ -3606,7 +3741,7 @@ These are Python temporary files awaiting execution."
|
||||||
(add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
|
(add-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)
|
||||||
|
|
||||||
;; Add a designator to the minor mode strings
|
;; Add a designator to the minor mode strings
|
||||||
(or (assq 'py-pdbtrack-minor-mode-string minor-mode-alist)
|
(or (assq 'py-pdbtrack-is-tracking-p minor-mode-alist)
|
||||||
(push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string)
|
(push '(py-pdbtrack-is-tracking-p py-pdbtrack-minor-mode-string)
|
||||||
minor-mode-alist))
|
minor-mode-alist))
|
||||||
|
|
||||||
|
@ -3745,20 +3880,35 @@ and initial `#'s.
|
||||||
If point is inside a string, narrow to that string and fill.
|
If point is inside a string, narrow to that string and fill.
|
||||||
"
|
"
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let* ((bod (py-point 'bod))
|
;; fill-paragraph will narrow incorrectly
|
||||||
(pps (parse-partial-sexp bod (point))))
|
(save-restriction
|
||||||
(cond
|
(widen)
|
||||||
;; are we inside a comment or on a line with only whitespace before
|
(let* ((bod (py-point 'bod))
|
||||||
;; the comment start?
|
(pps (parse-partial-sexp bod (point))))
|
||||||
((or (nth 4 pps)
|
(cond
|
||||||
(save-excursion (beginning-of-line) (looking-at "[ \t]*#")))
|
;; are we inside a comment or on a line with only whitespace before
|
||||||
(py-fill-comment justify))
|
;; the comment start?
|
||||||
;; are we inside a string?
|
((or (nth 4 pps)
|
||||||
((nth 3 pps)
|
(save-excursion (beginning-of-line) (looking-at "[ \t]*#")))
|
||||||
(py-fill-string (nth 8 pps)))
|
(py-fill-comment justify))
|
||||||
;; otherwise use the default
|
;; are we inside a string?
|
||||||
(t
|
((nth 3 pps)
|
||||||
(fill-paragraph justify)))))
|
(py-fill-string (nth 8 pps)))
|
||||||
|
;; are we at the opening quote of a string, or in the indentation?
|
||||||
|
((save-excursion
|
||||||
|
(forward-word 1)
|
||||||
|
(eq (py-in-literal) 'string))
|
||||||
|
(save-excursion
|
||||||
|
(py-fill-string (py-point 'boi))))
|
||||||
|
;; are we at or after the closing quote of a string?
|
||||||
|
((save-excursion
|
||||||
|
(backward-word 1)
|
||||||
|
(eq (py-in-literal) 'string))
|
||||||
|
(save-excursion
|
||||||
|
(py-fill-string (py-point 'boi))))
|
||||||
|
;; otherwise use the default
|
||||||
|
(t
|
||||||
|
(fill-paragraph justify))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,15 @@
|
||||||
|
|
||||||
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
|
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
|
||||||
|
|
||||||
|
/* Free list for method objects to safe malloc/free overhead
|
||||||
|
* The im_self element is used to chain the elements.
|
||||||
|
*/
|
||||||
|
static PyMethodObject *free_list;
|
||||||
|
static int numfree = 0;
|
||||||
|
#ifndef PyMethod_MAXFREELIST
|
||||||
|
#define PyMethod_MAXFREELIST 256
|
||||||
|
#endif
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyMethod_Function(PyObject *im)
|
PyMethod_Function(PyObject *im)
|
||||||
{
|
{
|
||||||
|
@ -30,8 +39,6 @@ PyMethod_Self(PyObject *im)
|
||||||
function.
|
function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyMethodObject *free_list;
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyMethod_New(PyObject *func, PyObject *self)
|
PyMethod_New(PyObject *func, PyObject *self)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +55,7 @@ PyMethod_New(PyObject *func, PyObject *self)
|
||||||
if (im != NULL) {
|
if (im != NULL) {
|
||||||
free_list = (PyMethodObject *)(im->im_self);
|
free_list = (PyMethodObject *)(im->im_self);
|
||||||
PyObject_INIT(im, &PyMethod_Type);
|
PyObject_INIT(im, &PyMethod_Type);
|
||||||
|
numfree--;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
|
im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
|
||||||
|
@ -165,8 +173,14 @@ method_dealloc(register PyMethodObject *im)
|
||||||
PyObject_ClearWeakRefs((PyObject *)im);
|
PyObject_ClearWeakRefs((PyObject *)im);
|
||||||
Py_DECREF(im->im_func);
|
Py_DECREF(im->im_func);
|
||||||
Py_XDECREF(im->im_self);
|
Py_XDECREF(im->im_self);
|
||||||
im->im_self = (PyObject *)free_list;
|
if (numfree < PyMethod_MAXFREELIST) {
|
||||||
free_list = im;
|
im->im_self = (PyObject *)free_list;
|
||||||
|
free_list = im;
|
||||||
|
numfree++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyObject_GC_Del(im);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -375,7 +389,9 @@ PyMethod_Fini(void)
|
||||||
PyMethodObject *im = free_list;
|
PyMethodObject *im = free_list;
|
||||||
free_list = (PyMethodObject *)(im->im_self);
|
free_list = (PyMethodObject *)(im->im_self);
|
||||||
PyObject_GC_Del(im);
|
PyObject_GC_Del(im);
|
||||||
|
numfree--;
|
||||||
}
|
}
|
||||||
|
assert(numfree == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
|
|
|
@ -184,9 +184,11 @@ show_counts(void)
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* Dictionary reuse scheme to save calls to malloc, free, and memset */
|
/* Dictionary reuse scheme to save calls to malloc, free, and memset */
|
||||||
#define MAXFREEDICTS 80
|
#ifndef PyDict_MAXFREELIST
|
||||||
static PyDictObject *free_dicts[MAXFREEDICTS];
|
#define PyDict_MAXFREELIST 80
|
||||||
static int num_free_dicts = 0;
|
#endif
|
||||||
|
static PyDictObject *free_list[PyDict_MAXFREELIST];
|
||||||
|
static int numfree = 0;
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyDict_New(void)
|
PyDict_New(void)
|
||||||
|
@ -200,8 +202,8 @@ PyDict_New(void)
|
||||||
Py_AtExit(show_counts);
|
Py_AtExit(show_counts);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (num_free_dicts) {
|
if (numfree) {
|
||||||
mp = free_dicts[--num_free_dicts];
|
mp = free_list[--numfree];
|
||||||
assert (mp != NULL);
|
assert (mp != NULL);
|
||||||
assert (Py_TYPE(mp) == &PyDict_Type);
|
assert (Py_TYPE(mp) == &PyDict_Type);
|
||||||
_Py_NewReference((PyObject *)mp);
|
_Py_NewReference((PyObject *)mp);
|
||||||
|
@ -897,8 +899,8 @@ dict_dealloc(register PyDictObject *mp)
|
||||||
}
|
}
|
||||||
if (mp->ma_table != mp->ma_smalltable)
|
if (mp->ma_table != mp->ma_smalltable)
|
||||||
PyMem_DEL(mp->ma_table);
|
PyMem_DEL(mp->ma_table);
|
||||||
if (num_free_dicts < MAXFREEDICTS && Py_TYPE(mp) == &PyDict_Type)
|
if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type)
|
||||||
free_dicts[num_free_dicts++] = mp;
|
free_list[numfree++] = mp;
|
||||||
else
|
else
|
||||||
Py_TYPE(mp)->tp_free((PyObject *)mp);
|
Py_TYPE(mp)->tp_free((PyObject *)mp);
|
||||||
Py_TRASHCAN_SAFE_END(mp)
|
Py_TRASHCAN_SAFE_END(mp)
|
||||||
|
|
|
@ -401,14 +401,15 @@ static PyGetSetDef frame_getsetlist[] = {
|
||||||
call depth of more than 20 or 30 is probably already exceptional
|
call depth of more than 20 or 30 is probably already exceptional
|
||||||
unless the program contains run-away recursion. I hope.
|
unless the program contains run-away recursion. I hope.
|
||||||
|
|
||||||
Later, MAXFREELIST was added to bound the # of frames saved on
|
Later, PyFrame_MAXFREELIST was added to bound the # of frames saved on
|
||||||
free_list. Else programs creating lots of cyclic trash involving
|
free_list. Else programs creating lots of cyclic trash involving
|
||||||
frames could provoke free_list into growing without bound.
|
frames could provoke free_list into growing without bound.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static PyFrameObject *free_list = NULL;
|
static PyFrameObject *free_list = NULL;
|
||||||
static int numfree = 0; /* number of frames currently in free_list */
|
static int numfree = 0; /* number of frames currently in free_list */
|
||||||
#define MAXFREELIST 200 /* max value for numfree */
|
/* max value for numfree */
|
||||||
|
#define PyFrame_MAXFREELIST 200
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_dealloc(PyFrameObject *f)
|
frame_dealloc(PyFrameObject *f)
|
||||||
|
@ -441,7 +442,7 @@ frame_dealloc(PyFrameObject *f)
|
||||||
co = f->f_code;
|
co = f->f_code;
|
||||||
if (co->co_zombieframe == NULL)
|
if (co->co_zombieframe == NULL)
|
||||||
co->co_zombieframe = f;
|
co->co_zombieframe = f;
|
||||||
else if (numfree < MAXFREELIST) {
|
else if (numfree < PyFrame_MAXFREELIST) {
|
||||||
++numfree;
|
++numfree;
|
||||||
f->f_back = free_list;
|
f->f_back = free_list;
|
||||||
free_list = f;
|
free_list = f;
|
||||||
|
|
|
@ -64,18 +64,20 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Empty list reuse scheme to save calls to malloc and free */
|
/* Empty list reuse scheme to save calls to malloc and free */
|
||||||
#define MAXFREELISTS 80
|
#ifndef PyList_MAXFREELIST
|
||||||
static PyListObject *free_lists[MAXFREELISTS];
|
#define PyList_MAXFREELIST 80
|
||||||
static int num_free_lists = 0;
|
#endif
|
||||||
|
static PyListObject *free_list[PyList_MAXFREELIST];
|
||||||
|
static int numfree = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
PyList_Fini(void)
|
PyList_Fini(void)
|
||||||
{
|
{
|
||||||
PyListObject *op;
|
PyListObject *op;
|
||||||
|
|
||||||
while (num_free_lists) {
|
while (numfree) {
|
||||||
num_free_lists--;
|
numfree--;
|
||||||
op = free_lists[num_free_lists];
|
op = free_list[numfree];
|
||||||
assert(PyList_CheckExact(op));
|
assert(PyList_CheckExact(op));
|
||||||
PyObject_GC_Del(op);
|
PyObject_GC_Del(op);
|
||||||
}
|
}
|
||||||
|
@ -95,9 +97,9 @@ PyList_New(Py_ssize_t size)
|
||||||
/* Check for overflow */
|
/* Check for overflow */
|
||||||
if (nbytes / sizeof(PyObject *) != (size_t)size)
|
if (nbytes / sizeof(PyObject *) != (size_t)size)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
if (num_free_lists) {
|
if (numfree) {
|
||||||
num_free_lists--;
|
numfree--;
|
||||||
op = free_lists[num_free_lists];
|
op = free_list[numfree];
|
||||||
_Py_NewReference((PyObject *)op);
|
_Py_NewReference((PyObject *)op);
|
||||||
} else {
|
} else {
|
||||||
op = PyObject_GC_New(PyListObject, &PyList_Type);
|
op = PyObject_GC_New(PyListObject, &PyList_Type);
|
||||||
|
@ -265,8 +267,8 @@ list_dealloc(PyListObject *op)
|
||||||
}
|
}
|
||||||
PyMem_FREE(op->ob_item);
|
PyMem_FREE(op->ob_item);
|
||||||
}
|
}
|
||||||
if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op))
|
if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
|
||||||
free_lists[num_free_lists++] = op;
|
free_list[numfree++] = op;
|
||||||
else
|
else
|
||||||
Py_TYPE(op)->tp_free((PyObject *)op);
|
Py_TYPE(op)->tp_free((PyObject *)op);
|
||||||
Py_TRASHCAN_SAFE_END(op)
|
Py_TRASHCAN_SAFE_END(op)
|
||||||
|
|
|
@ -4,7 +4,14 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
|
/* Free list for method objects to safe malloc/free overhead
|
||||||
|
* The m_self element is used to chain the objects.
|
||||||
|
*/
|
||||||
static PyCFunctionObject *free_list = NULL;
|
static PyCFunctionObject *free_list = NULL;
|
||||||
|
static int numfree = 0;
|
||||||
|
#ifndef PyCFunction_MAXFREELIST
|
||||||
|
#define PyCFunction_MAXFREELIST 256
|
||||||
|
#endif
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
|
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
|
||||||
|
@ -14,6 +21,7 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
|
||||||
if (op != NULL) {
|
if (op != NULL) {
|
||||||
free_list = (PyCFunctionObject *)(op->m_self);
|
free_list = (PyCFunctionObject *)(op->m_self);
|
||||||
PyObject_INIT(op, &PyCFunction_Type);
|
PyObject_INIT(op, &PyCFunction_Type);
|
||||||
|
numfree--;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
|
op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
|
||||||
|
@ -116,8 +124,14 @@ meth_dealloc(PyCFunctionObject *m)
|
||||||
_PyObject_GC_UNTRACK(m);
|
_PyObject_GC_UNTRACK(m);
|
||||||
Py_XDECREF(m->m_self);
|
Py_XDECREF(m->m_self);
|
||||||
Py_XDECREF(m->m_module);
|
Py_XDECREF(m->m_module);
|
||||||
m->m_self = (PyObject *)free_list;
|
if (numfree < PyCFunction_MAXFREELIST) {
|
||||||
free_list = m;
|
m->m_self = (PyObject *)free_list;
|
||||||
|
free_list = m;
|
||||||
|
numfree++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyObject_GC_Del(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -312,14 +326,16 @@ PyCFunction_Fini(void)
|
||||||
PyCFunctionObject *v = free_list;
|
PyCFunctionObject *v = free_list;
|
||||||
free_list = (PyCFunctionObject *)(v->m_self);
|
free_list = (PyCFunctionObject *)(v->m_self);
|
||||||
PyObject_GC_Del(v);
|
PyObject_GC_Del(v);
|
||||||
|
numfree--;
|
||||||
}
|
}
|
||||||
|
assert(numfree == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
|
/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
|
||||||
but it's part of the API so we need to keep a function around that
|
but it's part of the API so we need to keep a function around that
|
||||||
existing C extensions can call.
|
existing C extensions can call.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef PyCFunction_New
|
#undef PyCFunction_New
|
||||||
PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
|
PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,11 @@ _PySet_Dummy(void)
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* Reuse scheme to save calls to malloc, free, and memset */
|
/* Reuse scheme to save calls to malloc, free, and memset */
|
||||||
#define MAXFREESETS 80
|
#ifndef PySet_MAXFREELIST
|
||||||
static PySetObject *free_sets[MAXFREESETS];
|
#define PySet_MAXFREELIST 80
|
||||||
static int num_free_sets = 0;
|
#endif
|
||||||
|
static PySetObject *free_list[PySet_MAXFREELIST];
|
||||||
|
static int numfree = 0;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -561,8 +563,8 @@ set_dealloc(PySetObject *so)
|
||||||
}
|
}
|
||||||
if (so->table != so->smalltable)
|
if (so->table != so->smalltable)
|
||||||
PyMem_DEL(so->table);
|
PyMem_DEL(so->table);
|
||||||
if (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so))
|
if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so))
|
||||||
free_sets[num_free_sets++] = so;
|
free_list[numfree++] = so;
|
||||||
else
|
else
|
||||||
Py_TYPE(so)->tp_free(so);
|
Py_TYPE(so)->tp_free(so);
|
||||||
Py_TRASHCAN_SAFE_END(so)
|
Py_TRASHCAN_SAFE_END(so)
|
||||||
|
@ -975,9 +977,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create PySetObject structure */
|
/* create PySetObject structure */
|
||||||
if (num_free_sets &&
|
if (numfree &&
|
||||||
(type == &PySet_Type || type == &PyFrozenSet_Type)) {
|
(type == &PySet_Type || type == &PyFrozenSet_Type)) {
|
||||||
so = free_sets[--num_free_sets];
|
so = free_list[--numfree];
|
||||||
assert (so != NULL && PyAnySet_CheckExact(so));
|
assert (so != NULL && PyAnySet_CheckExact(so));
|
||||||
Py_TYPE(so) = type;
|
Py_TYPE(so) = type;
|
||||||
_Py_NewReference((PyObject *)so);
|
_Py_NewReference((PyObject *)so);
|
||||||
|
@ -1045,9 +1047,9 @@ PySet_Fini(void)
|
||||||
{
|
{
|
||||||
PySetObject *so;
|
PySetObject *so;
|
||||||
|
|
||||||
while (num_free_sets) {
|
while (numfree) {
|
||||||
num_free_sets--;
|
numfree--;
|
||||||
so = free_sets[num_free_sets];
|
so = free_list[numfree];
|
||||||
PyObject_GC_Del(so);
|
PyObject_GC_Del(so);
|
||||||
}
|
}
|
||||||
Py_CLEAR(dummy);
|
Py_CLEAR(dummy);
|
||||||
|
|
|
@ -4,19 +4,19 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
/* Speed optimization to avoid frequent malloc/free of small tuples */
|
/* Speed optimization to avoid frequent malloc/free of small tuples */
|
||||||
#ifndef MAXSAVESIZE
|
#ifndef PyTuple_MAXSAVESIZE
|
||||||
#define MAXSAVESIZE 20 /* Largest tuple to save on free list */
|
#define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAXSAVEDTUPLES
|
#ifndef PyTuple_MAXFREELIST
|
||||||
#define MAXSAVEDTUPLES 2000 /* Maximum number of tuples of each size to save */
|
#define PyTuple_MAXFREELIST 2000 /* Maximum number of tuples of each size to save */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MAXSAVESIZE > 0
|
#if PyTuple_MAXSAVESIZE > 0
|
||||||
/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty
|
/* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, entry 0 is the empty
|
||||||
tuple () of which at most one instance will be allocated.
|
tuple () of which at most one instance will be allocated.
|
||||||
*/
|
*/
|
||||||
static PyTupleObject *free_tuples[MAXSAVESIZE];
|
static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];
|
||||||
static int num_free_tuples[MAXSAVESIZE];
|
static int numfree[PyTuple_MAXSAVESIZE];
|
||||||
#endif
|
#endif
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
int fast_tuple_allocs;
|
int fast_tuple_allocs;
|
||||||
|
@ -32,18 +32,18 @@ PyTuple_New(register Py_ssize_t size)
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#if MAXSAVESIZE > 0
|
#if PyTuple_MAXSAVESIZE > 0
|
||||||
if (size == 0 && free_tuples[0]) {
|
if (size == 0 && free_list[0]) {
|
||||||
op = free_tuples[0];
|
op = free_list[0];
|
||||||
Py_INCREF(op);
|
Py_INCREF(op);
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
tuple_zero_allocs++;
|
tuple_zero_allocs++;
|
||||||
#endif
|
#endif
|
||||||
return (PyObject *) op;
|
return (PyObject *) op;
|
||||||
}
|
}
|
||||||
if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
|
if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) {
|
||||||
free_tuples[size] = (PyTupleObject *) op->ob_item[0];
|
free_list[size] = (PyTupleObject *) op->ob_item[0];
|
||||||
num_free_tuples[size]--;
|
numfree[size]--;
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
fast_tuple_allocs++;
|
fast_tuple_allocs++;
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,10 +71,10 @@ PyTuple_New(register Py_ssize_t size)
|
||||||
}
|
}
|
||||||
for (i=0; i < size; i++)
|
for (i=0; i < size; i++)
|
||||||
op->ob_item[i] = NULL;
|
op->ob_item[i] = NULL;
|
||||||
#if MAXSAVESIZE > 0
|
#if PyTuple_MAXSAVESIZE > 0
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
free_tuples[0] = op;
|
free_list[0] = op;
|
||||||
++num_free_tuples[0];
|
++numfree[0];
|
||||||
Py_INCREF(op); /* extra INCREF so that this is never freed */
|
Py_INCREF(op); /* extra INCREF so that this is never freed */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -167,14 +167,14 @@ tupledealloc(register PyTupleObject *op)
|
||||||
i = len;
|
i = len;
|
||||||
while (--i >= 0)
|
while (--i >= 0)
|
||||||
Py_XDECREF(op->ob_item[i]);
|
Py_XDECREF(op->ob_item[i]);
|
||||||
#if MAXSAVESIZE > 0
|
#if PyTuple_MAXSAVESIZE > 0
|
||||||
if (len < MAXSAVESIZE &&
|
if (len < PyTuple_MAXSAVESIZE &&
|
||||||
num_free_tuples[len] < MAXSAVEDTUPLES &&
|
numfree[len] < PyTuple_MAXFREELIST &&
|
||||||
Py_TYPE(op) == &PyTuple_Type)
|
Py_TYPE(op) == &PyTuple_Type)
|
||||||
{
|
{
|
||||||
op->ob_item[0] = (PyObject *) free_tuples[len];
|
op->ob_item[0] = (PyObject *) free_list[len];
|
||||||
num_free_tuples[len]++;
|
numfree[len]++;
|
||||||
free_tuples[len] = op;
|
free_list[len] = op;
|
||||||
goto done; /* return */
|
goto done; /* return */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -756,16 +756,16 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
|
||||||
void
|
void
|
||||||
PyTuple_Fini(void)
|
PyTuple_Fini(void)
|
||||||
{
|
{
|
||||||
#if MAXSAVESIZE > 0
|
#if PyTuple_MAXSAVESIZE > 0
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
Py_XDECREF(free_tuples[0]);
|
Py_XDECREF(free_list[0]);
|
||||||
free_tuples[0] = NULL;
|
free_list[0] = NULL;
|
||||||
|
|
||||||
for (i = 1; i < MAXSAVESIZE; i++) {
|
for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
|
||||||
PyTupleObject *p, *q;
|
PyTupleObject *p, *q;
|
||||||
p = free_tuples[i];
|
p = free_list[i];
|
||||||
free_tuples[i] = NULL;
|
free_list[i] = NULL;
|
||||||
while (p) {
|
while (p) {
|
||||||
q = p;
|
q = p;
|
||||||
p = (PyTupleObject *)(p->ob_item[0]);
|
p = (PyTupleObject *)(p->ob_item[0]);
|
||||||
|
|
|
@ -54,7 +54,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
/* Limit for the Unicode object free list */
|
/* Limit for the Unicode object free list */
|
||||||
|
|
||||||
#define MAX_UNICODE_FREELIST_SIZE 1024
|
#define PyUnicode_MAXFREELIST 1024
|
||||||
|
|
||||||
/* Limit for the Unicode object free list stay alive optimization.
|
/* Limit for the Unicode object free list stay alive optimization.
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
all objects on the free list having a size less than this
|
all objects on the free list having a size less than this
|
||||||
limit. This reduces malloc() overhead for small Unicode objects.
|
limit. This reduces malloc() overhead for small Unicode objects.
|
||||||
|
|
||||||
At worst this will result in MAX_UNICODE_FREELIST_SIZE *
|
At worst this will result in PyUnicode_MAXFREELIST *
|
||||||
(sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT +
|
(sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT +
|
||||||
malloc()-overhead) bytes of unused garbage.
|
malloc()-overhead) bytes of unused garbage.
|
||||||
|
|
||||||
|
@ -106,8 +106,8 @@ extern "C" {
|
||||||
static PyObject *interned;
|
static PyObject *interned;
|
||||||
|
|
||||||
/* Free list for Unicode objects */
|
/* Free list for Unicode objects */
|
||||||
static PyUnicodeObject *unicode_freelist;
|
static PyUnicodeObject *free_list;
|
||||||
static int unicode_freelist_size;
|
static int numfree;
|
||||||
|
|
||||||
/* The empty Unicode object is shared to improve performance. */
|
/* The empty Unicode object is shared to improve performance. */
|
||||||
static PyUnicodeObject *unicode_empty;
|
static PyUnicodeObject *unicode_empty;
|
||||||
|
@ -313,10 +313,10 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unicode freelist & memory allocation */
|
/* Unicode freelist & memory allocation */
|
||||||
if (unicode_freelist) {
|
if (free_list) {
|
||||||
unicode = unicode_freelist;
|
unicode = free_list;
|
||||||
unicode_freelist = *(PyUnicodeObject **)unicode;
|
free_list = *(PyUnicodeObject **)unicode;
|
||||||
unicode_freelist_size--;
|
numfree--;
|
||||||
if (unicode->str) {
|
if (unicode->str) {
|
||||||
/* Keep-Alive optimization: we only upsize the buffer,
|
/* Keep-Alive optimization: we only upsize the buffer,
|
||||||
never downsize it. */
|
never downsize it. */
|
||||||
|
@ -386,7 +386,7 @@ void unicode_dealloc(register PyUnicodeObject *unicode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyUnicode_CheckExact(unicode) &&
|
if (PyUnicode_CheckExact(unicode) &&
|
||||||
unicode_freelist_size < MAX_UNICODE_FREELIST_SIZE) {
|
numfree < PyUnicode_MAXFREELIST) {
|
||||||
/* Keep-Alive optimization */
|
/* Keep-Alive optimization */
|
||||||
if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
|
if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
|
||||||
PyMem_DEL(unicode->str);
|
PyMem_DEL(unicode->str);
|
||||||
|
@ -398,9 +398,9 @@ void unicode_dealloc(register PyUnicodeObject *unicode)
|
||||||
unicode->defenc = NULL;
|
unicode->defenc = NULL;
|
||||||
}
|
}
|
||||||
/* Add to free list */
|
/* Add to free list */
|
||||||
*(PyUnicodeObject **)unicode = unicode_freelist;
|
*(PyUnicodeObject **)unicode = free_list;
|
||||||
unicode_freelist = unicode;
|
free_list = unicode;
|
||||||
unicode_freelist_size++;
|
numfree++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyMem_DEL(unicode->str);
|
PyMem_DEL(unicode->str);
|
||||||
|
@ -8033,7 +8033,7 @@ unicode_zfill(PyUnicodeObject *self, PyObject *args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
unicode_freelistsize(PyUnicodeObject *self)
|
unicode_freelistsize(PyUnicodeObject *self)
|
||||||
{
|
{
|
||||||
return PyLong_FromLong(unicode_freelist_size);
|
return PyLong_FromLong(numfree);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9090,8 +9090,8 @@ void _PyUnicode_Init(void)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Init the implementation */
|
/* Init the implementation */
|
||||||
unicode_freelist = NULL;
|
free_list = NULL;
|
||||||
unicode_freelist_size = 0;
|
numfree = 0;
|
||||||
unicode_empty = _PyUnicode_New(0);
|
unicode_empty = _PyUnicode_New(0);
|
||||||
if (!unicode_empty)
|
if (!unicode_empty)
|
||||||
return;
|
return;
|
||||||
|
@ -9127,7 +9127,7 @@ _PyUnicode_Fini(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u = unicode_freelist; u != NULL;) {
|
for (u = free_list; u != NULL;) {
|
||||||
PyUnicodeObject *v = u;
|
PyUnicodeObject *v = u;
|
||||||
u = *(PyUnicodeObject **)u;
|
u = *(PyUnicodeObject **)u;
|
||||||
if (v->str)
|
if (v->str)
|
||||||
|
@ -9135,8 +9135,8 @@ _PyUnicode_Fini(void)
|
||||||
Py_XDECREF(v->defenc);
|
Py_XDECREF(v->defenc);
|
||||||
PyObject_Del(v);
|
PyObject_Del(v);
|
||||||
}
|
}
|
||||||
unicode_freelist = NULL;
|
free_list = NULL;
|
||||||
unicode_freelist_size = 0;
|
numfree = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -652,11 +652,16 @@ compiler_next_instr(struct compiler *c, basicblock *b)
|
||||||
return b->b_iused++;
|
return b->b_iused++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the i_lineno member of the instruction at offse off if the
|
/* Set the i_lineno member of the instruction at offset off if the
|
||||||
line number for the current expression/statement (?) has not
|
line number for the current expression/statement has not
|
||||||
already been set. If it has been set, the call has no effect.
|
already been set. If it has been set, the call has no effect.
|
||||||
|
|
||||||
Every time a new node is b
|
The line number is reset in the following cases:
|
||||||
|
- when entering a new scope
|
||||||
|
- on each statement
|
||||||
|
- on each expression that start a new line
|
||||||
|
- before the "except" clause
|
||||||
|
- before the "for" and "while" expressions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1750,9 +1755,8 @@ compiler_for(struct compiler *c, stmt_ty s)
|
||||||
VISIT(c, expr, s->v.For.iter);
|
VISIT(c, expr, s->v.For.iter);
|
||||||
ADDOP(c, GET_ITER);
|
ADDOP(c, GET_ITER);
|
||||||
compiler_use_next_block(c, start);
|
compiler_use_next_block(c, start);
|
||||||
/* XXX(nnorwitz): is there a better way to handle this?
|
/* for expressions must be traced on each iteration,
|
||||||
for loops are special, we want to be able to trace them
|
so we need to set an extra line number. */
|
||||||
each time around, so we need to set an extra line number. */
|
|
||||||
c->u->u_lineno_set = 0;
|
c->u->u_lineno_set = 0;
|
||||||
ADDOP_JREL(c, FOR_ITER, cleanup);
|
ADDOP_JREL(c, FOR_ITER, cleanup);
|
||||||
VISIT(c, expr, s->v.For.target);
|
VISIT(c, expr, s->v.For.target);
|
||||||
|
@ -1799,6 +1803,9 @@ compiler_while(struct compiler *c, stmt_ty s)
|
||||||
if (!compiler_push_fblock(c, LOOP, loop))
|
if (!compiler_push_fblock(c, LOOP, loop))
|
||||||
return 0;
|
return 0;
|
||||||
if (constant == -1) {
|
if (constant == -1) {
|
||||||
|
/* while expressions must be traced on each iteration,
|
||||||
|
so we need to set an extra line number. */
|
||||||
|
c->u->u_lineno_set = 0;
|
||||||
VISIT(c, expr, s->v.While.test);
|
VISIT(c, expr, s->v.While.test);
|
||||||
ADDOP_JREL(c, JUMP_IF_FALSE, anchor);
|
ADDOP_JREL(c, JUMP_IF_FALSE, anchor);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
|
@ -1979,8 +1986,8 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
s->v.TryExcept.handlers, i);
|
s->v.TryExcept.handlers, i);
|
||||||
if (!handler->type && i < n-1)
|
if (!handler->type && i < n-1)
|
||||||
return compiler_error(c, "default 'except:' must be last");
|
return compiler_error(c, "default 'except:' must be last");
|
||||||
c->u->u_lineno_set = 0;
|
c->u->u_lineno_set = 0;
|
||||||
c->u->u_lineno = handler->lineno;
|
c->u->u_lineno = handler->lineno;
|
||||||
except = compiler_new_block(c);
|
except = compiler_new_block(c);
|
||||||
if (except == NULL)
|
if (except == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3762,10 +3769,7 @@ assemble_lnotab(struct assembler *a, struct instr *i)
|
||||||
assert(d_bytecode >= 0);
|
assert(d_bytecode >= 0);
|
||||||
assert(d_lineno >= 0);
|
assert(d_lineno >= 0);
|
||||||
|
|
||||||
/* XXX(nnorwitz): is there a better way to handle this?
|
if(d_bytecode == 0 && d_lineno == 0)
|
||||||
for loops are special, we want to be able to trace them
|
|
||||||
each time around, so we need to set an extra line number. */
|
|
||||||
if (d_lineno == 0 && i->i_opcode != FOR_ITER)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (d_bytecode > 255) {
|
if (d_bytecode > 255) {
|
||||||
|
|
Loading…
Reference in New Issue